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