qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH] Add resolutions via the command-line
@ 2016-09-18  3:31 G 3
  2016-09-19  6:24 ` Benjamin Herrenschmidt
  0 siblings, 1 reply; 18+ messages in thread
From: G 3 @ 2016-09-18  3:31 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: qemu-devel qemu-devel, list@suse.de:PowerPC list:PowerPC

Add the ability to add resolutions from the command-line. This patch  
works by
looking for a property called 'resolutions' in the options 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>
---
  QemuVGADriver/src/QemuVga.c | 227 ++++++++++++++++++++++++++++++++++ 
+++++++++-
  1 file changed, 225 insertions(+), 2 deletions(-)

diff --git a/QemuVGADriver/src/QemuVga.c b/QemuVGADriver/src/QemuVga.c
index 4584242..d74fa41 100644
--- a/QemuVGADriver/src/QemuVga.c
+++ b/QemuVGADriver/src/QemuVga.c
@@ -3,6 +3,7 @@
  #include "DriverQDCalls.h"
  #include "QemuVga.h"
  #include <Timer.h>
+#include <stdlib.h>

  /* List of supported modes */
  struct vMode {
@@ -18,7 +19,21 @@ static struct vMode vModes[] =  {
  	{ 1600, 1200 },
  	{ 1920, 1080 },
  	{ 1920, 1200 },
-	{ 0,0 }
+	
+	/* The rest are place holders */
+	{ 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 },
  };

  static void VgaWriteB(UInt16 port, UInt8 val)
@@ -147,11 +162,219 @@ static InterruptMemberNumber  
PCIInterruptHandler(InterruptSetMember ISTmember,
  }
  #endif

+/*
+ * Get the resolution set at the specified index.
+ * The string returned needs to be freed when no longer used.
+ */
+static char *get_set(const char *resolution_set_str, int set_number)
+{
+	const int max_buf_size = 100;
+	char c, *buffer;
+	int index, comma_count;
+
+	buffer = (char *) malloc(max_buf_size);
+	comma_count = 0;
+	index = 0;
+	set_number++; /* Makes things easier to understand */
+
+	c = *(resolution_set_str++);
+	while (c != '\0') {
+		buffer[index++] = c;
+		c = *(resolution_set_str++);
+		if (c == ',') {
+			comma_count++;
+			if (comma_count == set_number || index >= max_buf_size) {
+				buffer[index] = '\0';
+				return buffer;
+			}
+			
+			else {
+				/* reset the buffer */
+				index = 0;
+				c = *(resolution_set_str++);
+			}
+		}
+	}
+	
+	buffer[index] = '\0';
+
+	return buffer;
+}
+
+/*
+ * Get the number of resolution sets
+ */
+
+static int get_set_count(const char *resolution_sets_str)
+{
+	char c;
+	int count;
+	
+	/* Count the number of commas */
+	count = 0;
+	c = *(resolution_sets_str++);
+	while (c != '\0') {
+		if (c == ',') {
+			count++;
+		}
+		c = *(resolution_sets_str++);
+	}
+
+	return count + 1;
+}
+
+/*
+ * Returns the width value of a resolution set
+ * Example:
+ * input: 16000x9000
+ * output: 16000
+ */
+
+static int get_width(const char *resolution_str)
+{
+	int index;
+	char c;
+	const int max_buf_size = 25;
+	char buffer[max_buf_size];
+	c = *(resolution_str++);
+	index = 0;
+	while (c != 'x' && index < max_buf_size) {
+		buffer[index++] = c;
+		c = *(resolution_str++);
+	}
+	
+	/* Terminate string */
+	buffer[index] = '\0';
+	
+	return atoi(buffer);
+}
+
+/*
+ * Returns the height value of a resolution set
+ * Example
+ * input: 16000x9000
+ * output: 9000
+ */
+
+static int get_height(const char *resolution_str)
+{
+	int index;
+	char c;
+	const int max_buf_size = 25;
+	char buffer[max_buf_size];
+	
+	/* skip to character after x */
+	while (*resolution_str != 'x') {
+		resolution_str++;
+	}
+	resolution_str++;
+	
+	/* Add digits of the height to the buffer */
+	index = 0;
+	c = *(resolution_str++);
+	while (c != '\0') {
+		buffer[index++] = c;
+		c = *(resolution_str++);
+		if(index >= max_buf_size) {
+			break;
+		}
+	}
+	
+	/* Terminate string */
+	buffer[index] = '\0';
+	
+	return atoi(buffer);
+}
+
+/*
+ * Looks in the /chosen node for the value of the resolutions property
+ */
+static int add_user_resolutions(void)
+{	
+	RegEntryID *entry_id;
+	OSErr err;
+	Boolean is_done;
+	void *value;
+	RegPropertyValueSize property_size;
+	int index, res_set_count;
+	char *set_str;
+		
+	#define PROPERTY_NAME "resolutions"
+	#define NODE_PATH "Devices:device-tree:options"
+
+	/* init the entry variable */
+	err = RegistryEntryIDInit(entry_id);
+	if (err != noErr) {
+		lprintf("Error: Failed to init entry variable! (%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 (%d)\n", err);
+		return err;
+	}
+
+	/* Get the size of the property */
+	err = RegistryPropertyGetSize(entry_id, PROPERTY_NAME,  
&property_size);
+	if (err != noErr) {
+		lprintf("Error: Failed to get property size! (%d)\n", err);
+		return err;
+	}
+
+	/* allocate memory to the value variable */
+	value = (void *) malloc(property_size);
+	
+	/* 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!\n", PROPERTY_NAME);
+		return err;
+	}
+
+	/* Limit the number of resolutions to 20 */
+	#define sane_number_of_resolutions 20
+	res_set_count = get_set_count(value);
+	res_set_count = (res_set_count > sane_number_of_resolutions ?  
sane_number_of_resolutions : res_set_count);
+
+	/* Add each resolution set */
+	for(index = 0; index < res_set_count; index++) {
+		set_str = get_set(value, index);
+		vModes[index].width = get_width(set_str);
+		vModes[index].height = get_height(set_str);
+		free(set_str);
+	}
+
+	free(value);
+}
+
+/* Returns the number of resolutions */
+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++)
+	{
+		/* Don't count any place holders */
+		if (vModes[index].width != 0) {
+			num_of_resolutions++;
+		}
+	}
+	
+	return num_of_resolutions;
+}

  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);
@@ -183,7 +406,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);

-- 
2.6.0

^ permalink raw reply related	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2016-09-23 14:10 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-09-18  3:31 [Qemu-devel] [PATCH] Add resolutions via the command-line G 3
2016-09-19  6:24 ` Benjamin Herrenschmidt
2016-09-19 12:44   ` G 3
2016-09-19 22:44     ` Benjamin Herrenschmidt
2016-09-19 23:56       ` Alfonso Gamboa
2016-09-20  3:57         ` G 3
2016-09-20  4:01       ` G 3
2016-09-21  0:18         ` Benjamin Herrenschmidt
2016-09-21  0:35           ` G 3
2016-09-21  0:41             ` Benjamin Herrenschmidt
2016-09-21  2:54               ` G 3
2016-09-21  3:41                 ` [Qemu-devel] [OpenBIOS] " Alfonso Gamboa
2016-09-21  9:01                 ` [Qemu-devel] " Benjamin Herrenschmidt
2016-09-21 18:26                   ` G 3
2016-09-21 21:53                     ` Benjamin Herrenschmidt
2016-09-21 23:18                       ` G 3
2016-09-22  0:05                         ` Benjamin Herrenschmidt
2016-09-23 14:09                       ` [Qemu-devel] [OpenBIOS] " Mark Cave-Ayland

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).