qemu-ppc
[Top][All Lists]
Advanced

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

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


From: Benjamin Herrenschmidt
Subject: Re: [Qemu-ppc] [PATCH] Add resolutions via the command-line
Date: Mon, 19 Sep 2016 16:24:33 +1000

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.

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