diff mbox

[v4] Add resolutions via the command-line

Message ID C0D6DBF1-FDBA-4D85-93EF-84810CEC44E1@gmail.com
State New
Headers show

Commit Message

Programmingkid Sept. 24, 2016, 4:42 p.m. UTC
Add the ability to add resolutions from the command-line. This patch  
works by
looking for a property called 'resolutions' in the QEMU,VGA node of  
OpenBIOS.
If it is found all the resolutions are parsed and loaded.

Example command-line:

-prom-env resolutions=512x342,640x480,800x600,1024x600,1200x700,1440x900

Signed-off-by: John Arbuckle <programmingkidx@gmail.com>
---
v4
Removed all ASCII text processing code and replaced it with integer  
processing code.

v3
Changed implementation of atoi().
Removed strlen() implementation.
Removed pow() implementation.
Changed entry_id from pointer to automatic variable.

v2
Implemented my own malloc(), strlen(), pow(), and atoi() functions.
Removed free() calls.
Changed get_set_count() to get_resolution_set_count().


  QemuVGADriver/src/QemuVga.c | 107 ++++++++++++++++++++++++++++++++++ 
+++++++++-
  1 file changed, 105 insertions(+), 2 deletions(-)

  OSStatus QemuVga_Init(void)
  {
  	UInt16 id, i;
  	UInt32 mem, width, height, depth;

+	add_user_resolutions();
+
  	lprintf("First MMIO read...\n");
  	id = DispiReadW(VBE_DISPI_INDEX_ID);
  	mem = DispiReadW(VBE_DISPI_INDEX_VIDEO_MEMORY_64K);
@@ -183,7 +286,7 @@ OSStatus QemuVga_Init(void)
  		i = 0;
  	}
  	GLOBAL.bootMode = i;
-	GLOBAL.numModes = sizeof(vModes) / sizeof(struct vMode) - 1;
+	GLOBAL.numModes = get_number_of_resolutions();

  	QemuVga_SetMode(GLOBAL.bootMode, depth, 0);
diff mbox

Patch

diff --git a/QemuVGADriver/src/QemuVga.c b/QemuVGADriver/src/QemuVga.c
index 4584242..9d2967e 100644
--- a/QemuVGADriver/src/QemuVga.c
+++ b/QemuVGADriver/src/QemuVga.c
@@ -18,9 +18,25 @@  static struct vMode vModes[] =  {
  	{ 1600, 1200 },
  	{ 1920, 1080 },
  	{ 1920, 1200 },
-	{ 0,0 }
+	{ 0,0 },
+	{ 0,0 },
+	{ 0,0 },
+	{ 0,0 },
+	{ 0,0 },
+	{ 0,0 },
+	{ 0,0 },
+	{ 0,0 },
+	{ 0,0 },
+	{ 0,0 },
+	{ 0,0 },
+	{ 0,0 },
+	{ 0,0 },
  };

+/* The number of width-height pairs in the above vModes structure */
+#define AVAILABLE_SLOTS 20
+
+
  static void VgaWriteB(UInt16 port, UInt8 val)
  {
  	UInt8 *ptr;
@@ -148,11 +164,98 @@  static InterruptMemberNumber PCIInterruptHandler 
(InterruptSetMember ISTmember,
  #endif


+/* Returns the number of resolutions in the vModes array */
+static int get_number_of_resolutions()
+{
+	int size_of_array, num_of_resolutions, index;
+	
+	num_of_resolutions = 0;
+	size_of_array = sizeof(vModes) / sizeof(struct vMode);
+	
+	for(index = 0; index < size_of_array; index++)
+	{
+		if (vModes[index].width != 0) {
+			num_of_resolutions++;
+		}
+	}
+	
+	return num_of_resolutions;
+}
+
+
+/* Looks in the /options node for the value of the resolutions  
property */
+static int add_user_resolutions(void)
+{	
+	RegEntryID entry_id;
+	OSErr err;
+	OSStatus os_status = noErr;
+	Boolean is_done;
+	void *value;
+	RegPropertyValueSize property_size = -1;
+	int index, res_set_count, *res_values;
+
+	#define PROPERTY_NAME "resolutions"
+	#define NODE_PATH "Devices:device-tree:pci:QEMU,VGA"
+
+	/* init the entry variable */
+	err = RegistryEntryIDInit(&entry_id);
+	if (err != noErr) {
+		lprintf("Error: Failed to init entry variable! (Error: %d)\n", err);
+		return err;
+	}
+	is_done = false;
+
+	/* Get the entry ID value */
+	err = RegistryCStrEntryLookup(NULL /* start root */, NODE_PATH,  
&entry_id);
+	if (err != noErr) {
+		lprintf("RegistryCStrEntryLookup() failure (Error: %d)\n", err);
+		return err;
+	}
+
+	/* Get the size of the property */
+	os_status = RegistryPropertyGetSize(&entry_id, PROPERTY_NAME,  
&property_size);
+	if (os_status != noErr) {
+		lprintf("Error: Failed to get property size! (Error: %d)\n",  
os_status);
+		return os_status;
+	}
+
+	/* Allocate memory to the value variable */
+	value = (void *) PoolAllocateResident(property_size, false);
+	if (value == NULL) {
+		lprintf("Error: Failed to allocate memory to value variable\n");
+		return -1;
+	}
+
+	/* Get the value of the property */
+	err = RegistryPropertyGet(&entry_id, PROPERTY_NAME, value,  
&property_size);
+	if (err != noErr) {
+		lprintf("Error: Failed to find property value %s! (Error: %d)\n",  
PROPERTY_NAME, err);
+		return err;
+	}
+	
+	res_values = value;
+	res_set_count = property_size/4/2; /* divide by bytes per cell then  
by cells per set */
+	
+	/* Limit the number of resolutions to number of available slots in  
vMode */
+	res_set_count = (res_set_count > AVAILABLE_SLOTS ?  
AVAILABLE_SLOTS : res_set_count);
+
+	/* Load each resolution set */
+	for(index = 0; index < res_set_count; index++)
+	{
+		vModes[index].width = *(res_values++);
+		vModes[index].height = *(res_values++);
+	}
+	return 0;
+}
+
+