[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);
> > >
- [Qemu-devel] [PATCH] Add resolutions via the command-line, G 3, 2016/09/17
- Re: [Qemu-devel] [PATCH] Add resolutions via the command-line, Benjamin Herrenschmidt, 2016/09/19
- Re: [Qemu-devel] [PATCH] Add resolutions via the command-line, G 3, 2016/09/19
- Re: [Qemu-devel] [PATCH] Add resolutions via the command-line, G 3, 2016/09/20
- Re: [Qemu-devel] [PATCH] Add resolutions via the command-line, Benjamin Herrenschmidt, 2016/09/20
- Re: [Qemu-devel] [PATCH] Add resolutions via the command-line, G 3, 2016/09/20
- Re: [Qemu-devel] [PATCH] Add resolutions via the command-line, Benjamin Herrenschmidt, 2016/09/20
- Re: [Qemu-devel] [PATCH] Add resolutions via the command-line, G 3, 2016/09/20
- Re: [Qemu-devel] [OpenBIOS] [PATCH] Add resolutions via the command-line, Alfonso Gamboa, 2016/09/20
- Re: [Qemu-devel] [PATCH] Add resolutions via the command-line, Benjamin Herrenschmidt, 2016/09/21
- Re: [Qemu-devel] [PATCH] Add resolutions via the command-line, G 3, 2016/09/21