From patchwork Sun Sep 18 03:31:59 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Programmingkid X-Patchwork-Id: 671322 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3scF350PTjz9t17 for ; Sun, 18 Sep 2016 13:33:05 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b=QUloGrzO; dkim-atps=neutral Received: from localhost ([::1]:48526 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1blSqk-0007kd-BH for incoming@patchwork.ozlabs.org; Sat, 17 Sep 2016 23:33:02 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44492) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1blSpu-0007Oa-J5 for qemu-devel@nongnu.org; Sat, 17 Sep 2016 23:32:11 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1blSpq-0000Qb-87 for qemu-devel@nongnu.org; Sat, 17 Sep 2016 23:32:09 -0400 Received: from mail-it0-x242.google.com ([2607:f8b0:4001:c0b::242]:34061) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1blSpq-0000PG-2e; Sat, 17 Sep 2016 23:32:06 -0400 Received: by mail-it0-x242.google.com with SMTP id 186so2727311itf.1; Sat, 17 Sep 2016 20:32:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:message-id:cc:content-transfer-encoding:from:subject :date:to; bh=b5GPSOqTZV4IENXgL8nDwwSnEdQr0IoyS5Pi5WYZh1c=; b=QUloGrzOucxIGcl0LCL9XEJBHXOGvHK3Y0XCWwiepKEP4VfuIc6LaQicNPoaVHHa1W kkajrrf+FUTn0J8lrtPQEwAyIYI+VsC6lSW9stQlQcD+S01LQnmCHNTeRomZ25OzKQNo vFIV8HaTusteP1qL2H35oasW99icg6j9WvfX/adAMMlaksydEuELHtSn6sdKJRJKf23D fY1aBdnJYcaqe0UvjOHDrcHKb32xRScTFJN3FBMtFbN0iCCheZwTem80R+pHMDEy2Y+M SxdAthVR5lcmUmesddfGna/vK32qc4H+7VjPCuJhNEoGwUtUws1hm4riDBmX6LPHSysC RjUw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:message-id:cc :content-transfer-encoding:from:subject:date:to; bh=b5GPSOqTZV4IENXgL8nDwwSnEdQr0IoyS5Pi5WYZh1c=; b=NDkj+h0YFzcqfUcQPz/IifDGWr+5h39UwKsaA15Mczyam1zZq93lK5bF3OdIY5pg1y oGA4xqUxuMjErSFG3UmpRw1MfptGr1g3CB9OhtI446TyRSWekVUOXIQtvPWlYu2T8zRs 3tcvi2S0mRh8VU0QszmGh71GJtfJvxO1thGP8dTME++pGwrZ1LkksigQPRuk2i8F0n1z FRN7roBf0PGKKB/6aFyzVbsfRPKcp55QB1FdMgOn2HjN8XlQ1TFRR8MUX0jFVtFOwVOy CYhjbgnxCpDaWLntvGUgL1iAsex8WSNiv2cktIhGPOIXYahk3fcdoKw+gJaYtrfQX2gl 5uvw== X-Gm-Message-State: AE9vXwORB9NSt1CGQ1QGdunijr4OAMBbZDZ528IMyqW9JXY/arJ7+DxEkXIeellFekj9lw== X-Received: by 10.36.103.131 with SMTP id u125mr4764362itc.68.1474169524859; Sat, 17 Sep 2016 20:32:04 -0700 (PDT) Received: from [192.168.0.9] (d199-74-164-53.col.wideopenwest.com. [74.199.53.164]) by smtp.gmail.com with ESMTPSA id x100sm6575299ioe.31.2016.09.17.20.32.03 (version=TLS1 cipher=AES128-SHA bits=128/128); Sat, 17 Sep 2016 20:32:03 -0700 (PDT) Mime-Version: 1.0 (Apple Message framework v753.1) Message-Id: <5766C91B-319D-46CD-9020-19EB5299DF99@gmail.com> From: G 3 Date: Sat, 17 Sep 2016 23:31:59 -0400 To: Benjamin Herrenschmidt X-Mailer: Apple Mail (2.753.1) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2607:f8b0:4001:c0b::242 Subject: [Qemu-devel] [PATCH] Add resolutions via the command-line X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: "list@suse.de:PowerPC list:PowerPC" , qemu-devel qemu-devel Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" 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: -prom-env resolutions=512x342,640x480,800x600,1024x600,1200x700,1440x900 Signed-off-by: John Arbuckle --- QemuVGADriver/src/QemuVga.c | 227 ++++++++++++++++++++++++++++++++++ +++++++++- 1 file changed, 225 insertions(+), 2 deletions(-) + + 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); 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 +#include /* 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;