From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:53106) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bm7J4-0005fw-MY for qemu-devel@nongnu.org; Mon, 19 Sep 2016 18:45:00 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bm7J2-0002au-7r for qemu-devel@nongnu.org; Mon, 19 Sep 2016 18:44:58 -0400 Message-ID: <1474325083.2857.35.camel@kernel.crashing.org> From: Benjamin Herrenschmidt Date: Tue, 20 Sep 2016 08:44:43 +1000 In-Reply-To: <852E4EA6-522A-499D-88DE-A1955D938D6D@gmail.com> References: <5766C91B-319D-46CD-9020-19EB5299DF99@gmail.com> <1474266273.2857.11.camel@kernel.crashing.org> <852E4EA6-522A-499D-88DE-A1955D938D6D@gmail.com> Content-Type: text/plain; charset="UTF-8" Mime-Version: 1.0 Content-Transfer-Encoding: quoted-printable Subject: Re: [Qemu-devel] [PATCH] Add resolutions via the command-line List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: G 3 Cc: qemu-devel qemu-devel , "list@suse.de:PowerPC list:PowerPC" On Mon, 2016-09-19 at 08:44 -0400, G 3 wrote: > On Sep 19, 2016, at 2:24 AM, Benjamin Herrenschmidt wrote: >=20 > >=20 > > On Sat, 2016-09-17 at 23:31 -0400, G 3 wrote: > > >=20 > > > 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. > > >=20 > > > Example command-line: > >=20 > > You must not use the C library in the ndrv (malloc, atoi, ...) > >=20 > > Stick to what's in DriverServicesLib and NameRegistryLib. >=20 > I originally thought that, but was wrong. Those C library functions=C2=A0= =C2=A0 > work. No, don't use them. They "seem" to work but bad thing will happen, especially on OS X. Cheers, Ben. >=20 > >=20 > >=20 > > >=20 > > > -prom-env > > > resolutions=3D512x342,640x480,800x600,1024x600,1200x700,1440x900 > > >=20 > > > Signed-off-by: John Arbuckle > > > --- > > > =C2=A0 QemuVGADriver/src/QemuVga.c | 227 > > > ++++++++++++++++++++++++++++++++++ > > > +++++++++- > > > =C2=A0 1 file changed, 225 insertions(+), 2 deletions(-) > > >=20 > > > 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 @@ > > > =C2=A0 #include "DriverQDCalls.h" > > > =C2=A0 #include "QemuVga.h" > > > =C2=A0 #include > > > +#include > > >=20 > > > =C2=A0 /* List of supported modes */ > > > =C2=A0 struct vMode { > > > @@ -18,7 +19,21 @@ static struct vMode vModes[] =3D=C2=A0=C2=A0{ > > > =C2=A0=C2=A0 { 1600, 1200 }, > > > =C2=A0=C2=A0 { 1920, 1080 }, > > > =C2=A0=C2=A0 { 1920, 1200 }, > > > - { 0,0 } > > > +=09 > > > + /* 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 }, > > > =C2=A0 }; > > >=20 > > > =C2=A0 static void VgaWriteB(UInt16 port, UInt8 val) > > > @@ -147,11 +162,219 @@ static InterruptMemberNumber > > > PCIInterruptHandler(InterruptSetMember ISTmember, > > > =C2=A0 } > > > =C2=A0 #endif > > >=20 > > > +/* > > > + * 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 =3D 100; > > > + char c, *buffer; > > > + int index, comma_count; > > > + > > > + buffer =3D (char *) malloc(max_buf_size); > > > + comma_count =3D 0; > > > + index =3D 0; > > > + set_number++; /* Makes things easier to understand */ > > > + > > > + c =3D *(resolution_set_str++); > > > + while (c !=3D '\0') { > > > + buffer[index++] =3D c; > > > + c =3D *(resolution_set_str++); > > > + if (c =3D=3D ',') { > > > + comma_count++; > > > + if (comma_count =3D=3D set_number || index > > > >=3D > > > max_buf_size) { > > > + buffer[index] =3D '\0'; > > > + return buffer; > > > + } > > > + =09 > > > + else { > > > + /* reset the buffer */ > > > + index =3D 0; > > > + c =3D *(resolution_set_str++); > > > + } > > > + } > > > + } > > > +=09 > > > + buffer[index] =3D '\0'; > > > + > > > + return buffer; > > > +} > > > + > > > +/* > > > + * Get the number of resolution sets > > > + */ > > > + > > > +static int get_set_count(const char *resolution_sets_str) > > > +{ > > > + char c; > > > + int count; > > > +=09 > > > + /* Count the number of commas */ > > > + count =3D 0; > > > + c =3D *(resolution_sets_str++); > > > + while (c !=3D '\0') { > > > + if (c =3D=3D ',') { > > > + count++; > > > + } > > > + c =3D *(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 =3D 25; > > > + char buffer[max_buf_size]; > > > + c =3D *(resolution_str++); > > > + index =3D 0; > > > + while (c !=3D 'x' && index < max_buf_size) { > > > + buffer[index++] =3D c; > > > + c =3D *(resolution_str++); > > > + } > > > +=09 > > > + /* Terminate string */ > > > + buffer[index] =3D '\0'; > > > +=09 > > > + 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 =3D 25; > > > + char buffer[max_buf_size]; > > > +=09 > > > + /* skip to character after x */ > > > + while (*resolution_str !=3D 'x') { > > > + resolution_str++; > > > + } > > > + resolution_str++; > > > +=09 > > > + /* Add digits of the height to the buffer */ > > > + index =3D 0; > > > + c =3D *(resolution_str++); > > > + while (c !=3D '\0') { > > > + buffer[index++] =3D c; > > > + c =3D *(resolution_str++); > > > + if(index >=3D max_buf_size) { > > > + break; > > > + } > > > + } > > > +=09 > > > + /* Terminate string */ > > > + buffer[index] =3D '\0'; > > > +=09 > > > + return atoi(buffer); > > > +} > > > + > > > +/* > > > + * Looks in the /chosen node for the value of the resolutions > > > property > > > + */ > > > +static int add_user_resolutions(void) > > > +{=09 > > > + RegEntryID *entry_id; > > > + OSErr err; > > > + Boolean is_done; > > > + void *value; > > > + RegPropertyValueSize property_size; > > > + int index, res_set_count; > > > + char *set_str; > > > + =09 > > > + #define PROPERTY_NAME "resolutions" > > > + #define NODE_PATH "Devices:device-tree:options" > > > + > > > + /* init the entry variable */ > > > + err =3D RegistryEntryIDInit(entry_id); > > > + if (err !=3D noErr) { > > > + lprintf("Error: Failed to init entry variable! > > > (%d)\n", err); > > > + return err; > > > + } > > > + is_done =3D false; > > > + > > > + /* Get the entry ID value */ > > > + err =3D RegistryCStrEntryLookup(NULL /* start root */, > > > NODE_PATH, > > > entry_id); > > > + if (err !=3D noErr) { > > > + lprintf("RegistryCStrEntryLookup() failure > > > (%d)\n", > > > err); > > > + return err; > > > + } > > > + > > > + /* Get the size of the property */ > > > + err =3D RegistryPropertyGetSize(entry_id, PROPERTY_NAME, > > > &property_size); > > > + if (err !=3D noErr) { > > > + lprintf("Error: Failed to get property size! > > > (%d)\n", err); > > > + return err; > > > + } > > > + > > > + /* allocate memory to the value variable */ > > > + value =3D (void *) malloc(property_size); > > > +=09 > > > + /* Get the value of the property */ > > > + err =3D RegistryPropertyGet(entry_id, PROPERTY_NAME, > > > value, > > > &property_size); > > > + if (err !=3D 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 =3D get_set_count(value); > > > + res_set_count =3D (res_set_count > > > > sane_number_of_resolutions > > > ? > > > sane_number_of_resolutions : res_set_count); > > > + > > > + /* Add each resolution set */ > > > + for(index =3D 0; index < res_set_count; index++) { > > > + set_str =3D get_set(value, index); > > > + vModes[index].width =3D get_width(set_str); > > > + vModes[index].height =3D 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; > > > +=09 > > > + num_of_resolutions =3D 0; > > > + size_of_array =3D sizeof(vModes) / sizeof(struct vMode); > > > +=09 > > > + for(index =3D 0; index < size_of_array; index++) > > > + { > > > + /* Don't count any place holders */ > > > + if (vModes[index].width !=3D 0) { > > > + num_of_resolutions++; > > > + } > > > + } > > > +=09 > > > + return num_of_resolutions; > > > +} > > >=20 > > > =C2=A0 OSStatus QemuVga_Init(void) > > > =C2=A0 { > > > =C2=A0=C2=A0 UInt16 id, i; > > > =C2=A0=C2=A0 UInt32 mem, width, height, depth; > > > +=09 > > > + add_user_resolutions(); > > >=20 > > > =C2=A0=C2=A0 lprintf("First MMIO read...\n"); > > > =C2=A0=C2=A0 id =3D DispiReadW(VBE_DISPI_INDEX_ID); > > > @@ -183,7 +406,7 @@ OSStatus QemuVga_Init(void) > > > =C2=A0=C2=A0 i =3D 0; > > > =C2=A0=C2=A0 } > > > =C2=A0=C2=A0 GLOBAL.bootMode =3D i; > > > - GLOBAL.numModes =3D sizeof(vModes) / sizeof(struct vMode) > > > - 1; > > > + GLOBAL.numModes =3D get_number_of_resolutions(); > > >=20 > > > =C2=A0=C2=A0 QemuVga_SetMode(GLOBAL.bootMode, depth, 0); > > >=20