qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH] Add resolutions via the command-line


From: G 3
Subject: Re: [Qemu-devel] [PATCH] Add resolutions via the command-line
Date: Mon, 19 Sep 2016 08:44:29 -0400


On Sep 19, 2016, at 2:24 AM, Benjamin Herrenschmidt wrote:

On Sat, 2016-09-17 at 23:31 -0400, G 3 wrote:
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:

You must not use the C library in the ndrv (malloc, atoi, ...)

Stick to what's in DriverServicesLib and NameRegistryLib.

I originally thought that, but was wrong. Those C library functions work.



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

Signed-off-by: John Arbuckle <address@hidden>
---
  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);





reply via email to

[Prev in Thread] Current Thread [Next in Thread]