All of lore.kernel.org
 help / color / mirror / Atom feed
From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
To: G 3 <programmingkidx@gmail.com>
Cc: qemu-devel qemu-devel <qemu-devel@nongnu.org>,
	"list@suse.de:PowerPC list:PowerPC" <qemu-ppc@nongnu.org>
Subject: Re: [Qemu-devel] [PATCH] Add resolutions via the command-line
Date: Mon, 19 Sep 2016 16:24:33 +1000	[thread overview]
Message-ID: <1474266273.2857.11.camel@kernel.crashing.org> (raw)
In-Reply-To: <5766C91B-319D-46CD-9020-19EB5299DF99@gmail.com>

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 <programmingkidx@gmail.com>
> ---
>   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	other threads:[~2016-09-19  6:24 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-09-18  3:31 [Qemu-devel] [PATCH] Add resolutions via the command-line G 3
2016-09-19  6:24 ` Benjamin Herrenschmidt [this message]
2016-09-19 12:44   ` G 3
2016-09-19 22:44     ` Benjamin Herrenschmidt
2016-09-19 23:56       ` Alfonso Gamboa
2016-09-20  3:57         ` G 3
2016-09-20  4:01       ` G 3
2016-09-21  0:18         ` Benjamin Herrenschmidt
2016-09-21  0:35           ` G 3
2016-09-21  0:41             ` Benjamin Herrenschmidt
2016-09-21  2:54               ` G 3
2016-09-21  3:41                 ` [Qemu-devel] [OpenBIOS] " Alfonso Gamboa
2016-09-21  9:01                 ` [Qemu-devel] " Benjamin Herrenschmidt
2016-09-21 18:26                   ` G 3
2016-09-21 21:53                     ` Benjamin Herrenschmidt
2016-09-21 23:18                       ` G 3
2016-09-22  0:05                         ` Benjamin Herrenschmidt
2016-09-23 14:09                       ` [Qemu-devel] [OpenBIOS] " Mark Cave-Ayland

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1474266273.2857.11.camel@kernel.crashing.org \
    --to=benh@kernel.crashing.org \
    --cc=programmingkidx@gmail.com \
    --cc=qemu-devel@nongnu.org \
    --cc=qemu-ppc@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.