[OpenBIOS] [PATCH 07/11] ppc: add PReP residual data block

Mark Cave-Ayland mark.cave-ayland at ilande.co.uk
Sat May 26 21:29:52 CEST 2018


This is borrowed from OpenHackWare in order to provide hardware data to
the client OS.

Signed-off-by: Mark Cave-Ayland <mark.cave-ayland at ilande.co.uk>
---
 arch/ppc/qemu/context.c     | 129 +++++++++++++++++++++++++++++++++++++++++++-
 arch/ppc/qemu/context.h     |   1 +
 include/arch/ppc/residual.h | 116 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 244 insertions(+), 2 deletions(-)
 create mode 100644 include/arch/ppc/residual.h

diff --git a/arch/ppc/qemu/context.c b/arch/ppc/qemu/context.c
index 65cd4e4..03ca173 100644
--- a/arch/ppc/qemu/context.c
+++ b/arch/ppc/qemu/context.c
@@ -1,12 +1,19 @@
 /*
  * context switching
  * 2003-10 by SONE Takeshi
+ *
+ * Residual data portions:
+ *     Copyright (c) 2004-2005 Jocelyn Mayer
  */
 
 #include "config.h"
 #include "kernel/kernel.h"
 #include "context.h"
+#include "arch/ppc/processor.h"
+#include "arch/ppc/residual.h"
+#include "drivers/drivers.h"
 #include "libopenbios/bindings.h"
+#include "libopenbios/ofmem.h"
 #include "libopenbios/initprogram.h"
 #include "libopenbios/sys_info.h"
 
@@ -97,12 +104,117 @@ init_context(uint8_t *stack, uint32_t stack_size, int num_params)
     return ctx;
 }
 
+
+/* Build PReP residual data */
+static void *
+residual_build(uint32_t memsize, uint32_t load_base, uint32_t load_size)
+{
+    residual_t *res;
+    const unsigned char model[] = "Qemu\0PPC\0";
+    int i;
+
+    res = malloc(sizeof(residual_t));
+    if (res == NULL) {
+        return NULL;
+    }
+
+    res->length = sizeof(residual_t);
+    res->version = 1;
+    res->revision = 0;
+    memcpy(res->vital.model, model, sizeof(model));
+    res->vital.version = 1;
+    res->vital.revision = 0;
+    res->vital.firmware = 0x1D1;
+    res->vital.NVRAM_size = 0x2000;
+    res->vital.nSIMMslots = 1;
+    res->vital.nISAslots = 0;
+    res->vital.nPCIslots = 0;
+    res->vital.nPCMCIAslots = 0;
+    res->vital.nMCAslots = 0;
+    res->vital.nEISAslots = 0;
+    res->vital.CPUHz = 200 * 1000 * 1000;
+    res->vital.busHz = 100 * 1000 * 1000;
+    res->vital.PCIHz = 33 * 1000 * 1000;
+    res->vital.TBdiv = 1000;
+    res->vital.wwidth = 32;
+    res->vital.page_size = 4096;
+    res->vital.ChBlocSize = 32;
+    res->vital.GrSize = 32;
+    res->vital.cache_size = 0;
+    res->vital.cache_type = 0; /* No cache */
+    res->vital.cache_assoc = 8; /* Same as 601 */
+    res->vital.cache_lnsize = 32;
+    res->vital.Icache_size = 0;
+    res->vital.Icache_assoc = 8;
+    res->vital.Icache_lnsize = 32;
+    res->vital.Dcache_size = 0;
+    res->vital.Dcache_assoc = 8;
+    res->vital.Dcache_lnsize = 32;
+    res->vital.TLB_size = 0;
+    res->vital.TLB_type = 0; /* None */
+    res->vital.TLB_assoc = 2;
+    res->vital.ITLB_size = 0;
+    res->vital.ITLB_assoc = 2;
+    res->vital.DTLB_size = 0;
+    res->vital.DTLB_assoc = 2;
+    res->vital.ext_vital = NULL;
+    res->nCPUs = 1;
+    res->CPUs[0].pvr = mfpvr();
+    res->CPUs[0].serial = 0;
+    res->CPUs[0].L2_size = 0;
+    res->CPUs[0].L2_assoc = 8;
+    /* Memory infos */
+    res->max_mem = memsize;
+    res->good_mem = memsize;
+    /* Memory mappings */
+    /* First segment: firmware */
+    res->maps[0].usage = 0x0007;
+    res->maps[0].base  = 0xfff00000;
+    res->maps[0].count = 0x00100000 >> 12;
+    i = 1;
+    /* Boot image */
+    load_size = (load_size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
+    res->maps[i].usage = 0x0008;
+    res->maps[i].base  = load_base >> 12;
+    res->maps[i].count = load_size >> 12;
+    i++;
+    /* Free memory */
+    res->maps[i].usage = 0x0010;
+    res->maps[i].base  = (load_base + load_size) >> 12;
+    res->maps[i].count = (memsize >> 12) - res->maps[i].base;
+    i++;
+    /* ISA IO region : 8MB */
+    res->maps[i].usage = 0x0040;
+    res->maps[i].base  = 0x80000000 >> 12;
+    res->maps[i].count = 0x00800000 >> 12;
+    i++;
+    /* System registers : 8MB */
+    res->maps[i].usage = 0x0200;
+    res->maps[i].base  = 0xBF800000 >> 12;
+    res->maps[i].count = 0x00800000 >> 12;
+    i++;
+    /* System ROM : 64 kB */
+    res->maps[i].usage = 0x2000;
+    res->maps[i].base  = 0xFFFF0000 >> 12;
+    res->maps[i].count = 0x00010000 >> 12;
+    i++;
+    res->nmaps = i;
+    /* Memory SIMMs */
+    res->nmems = 1;
+    res->memories[0].size = memsize;
+    /* Describe no devices */
+    res->ndevices = 0;
+
+    return res;
+}
+
 /* init-program */
 int
 arch_init_program(void)
 {
     volatile struct context *ctx = __context;
-    ucell entry, param;
+    ucell entry, param, loadbase, loadsize;
+    ofmem_t *ofmem = ofmem_arch_get_private();
     
     /* According to IEEE 1275, PPC bindings:
      *
@@ -112,7 +224,8 @@ arch_init_program(void)
      *    r6 = address of client program arguments (unused)
      *    r7 = length of client program arguments (unused)
      *
-     *      Yaboot and Linux use r3 and r4 for initrd address and size
+     *    Yaboot and Linux use r3 and r4 for initrd address and size
+     *    PReP machines use r3 and r4 for residual data and load image
      */
 
     ctx->regs[REG_R5] = (unsigned long)of_client_callback;
@@ -129,6 +242,18 @@ arch_init_program(void)
     entry = POP();
     ctx->pc = entry;
 
+    /* Residual data for PReP */
+    if (!is_apple()) {
+        fword("load-base");
+        loadbase = POP();
+        fword("load-size");
+        loadsize = POP();
+
+        ctx->regs[REG_R3] = (uintptr_t)residual_build((uint32_t)ofmem->ramsize,
+                                                      loadbase, loadsize);
+        ctx->regs[REG_R4] = loadbase;
+    }
+
     return 0;
 }
 
diff --git a/arch/ppc/qemu/context.h b/arch/ppc/qemu/context.h
index 8135bb4..7cf9da8 100644
--- a/arch/ppc/qemu/context.h
+++ b/arch/ppc/qemu/context.h
@@ -10,6 +10,7 @@ struct context {
     /* General registers */
     unsigned long regs[34];
 #define REG_R3 3
+#define REG_R4 7
 #define REG_R5 8
 #define REG_R6 9
 #define REG_R7 10
diff --git a/include/arch/ppc/residual.h b/include/arch/ppc/residual.h
new file mode 100644
index 0000000..8e9d89c
--- /dev/null
+++ b/include/arch/ppc/residual.h
@@ -0,0 +1,116 @@
+/*
+ * residual.h
+ *
+ * Structures for build PReP residual data as used in OpenHackWare
+ *
+ * Copyright (c) 2004-2005 Jocelyn Mayer
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License V2
+ *   as published by the Free Software Foundation
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* Residual data */
+#define MAX_CPUS 16
+#define MAX_SEGS 64
+#define MAX_MEMS 64
+#define MAX_DEVS 256
+
+typedef struct vital_t {
+    /* Motherboard dependents */
+    uint8_t model[32];
+    uint8_t serial[64];
+    uint16_t version;
+    uint16_t revision;
+    uint32_t firmware;
+    uint32_t NVRAM_size;
+    uint32_t nSIMMslots;
+    uint32_t nISAslots;
+    uint32_t nPCIslots;
+    uint32_t nPCMCIAslots;
+    uint32_t nMCAslots;
+    uint32_t nEISAslots;
+    uint32_t CPUHz;
+    uint32_t busHz;
+    uint32_t PCIHz;
+    uint32_t TBdiv;
+    /* CPU infos */
+    uint32_t wwidth;
+    uint32_t page_size;
+    uint32_t ChBlocSize;
+    uint32_t GrSize;
+    /* Cache and TLBs */
+    uint32_t cache_size;
+    uint32_t cache_type;
+    uint32_t cache_assoc;
+    uint32_t cache_lnsize;
+    uint32_t Icache_size;
+    uint32_t Icache_assoc;
+    uint32_t Icache_lnsize;
+    uint32_t Dcache_size;
+    uint32_t Dcache_assoc;
+    uint32_t Dcache_lnsize;
+    uint32_t TLB_size;
+    uint32_t TLB_type;
+    uint32_t TLB_assoc;
+    uint32_t ITLB_size;
+    uint32_t ITLB_assoc;
+    uint32_t DTLB_size;
+    uint32_t DTLB_assoc;
+    void *ext_vital;
+} vital_t;
+
+typedef struct PPC_CPU_t {
+    uint32_t pvr;
+    uint32_t serial;
+    uint32_t L2_size;
+    uint32_t L2_assoc;
+} PPC_CPU_t;
+
+typedef struct map_t {
+    uint32_t usage;
+    uint32_t base;
+    uint32_t count;
+} map_t;
+
+typedef struct PPC_mem_t {
+    uint32_t size;
+} PPC_mem_t;
+
+typedef struct PPC_device_t {
+    uint32_t busID;
+    uint32_t devID;
+    uint32_t serial;
+    uint32_t flags;
+    uint32_t type;
+    uint32_t subtype;
+    uint32_t interface;
+    uint32_t spare;
+} PPC_device_t;
+
+typedef struct residual_t {
+    uint32_t  length;
+    uint16_t  version;
+    uint16_t  revision;
+    vital_t   vital;
+    uint32_t  nCPUs;
+    PPC_CPU_t CPUs[MAX_CPUS];
+    uint32_t  max_mem;
+    uint32_t  good_mem;
+    uint32_t  nmaps;
+    map_t     maps[MAX_SEGS];
+    uint32_t  nmems;
+    PPC_mem_t memories[MAX_MEMS];
+    uint32_t  ndevices;
+    PPC_device_t devices[MAX_DEVS];
+    /* TOFIX: No PNP devices */
+} residual_t;
-- 
2.11.0




More information about the OpenBIOS mailing list