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: Benjamin Herrenschmidt
Subject: Re: [Qemu-devel] [PATCH] Add resolutions via the command-line
Date: Tue, 20 Sep 2016 08:44:43 +1000

On Mon, 2016-09-19 at 08:44 -0400, G 3 wrote:
> 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.

No, don't use them. They "seem" to work but bad thing will happen,
especially on OS X.

Cheers,
Ben.

> 
> > 
> > 
> > > 
> > > -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]