source: rtems/bsps/powerpc/motorola_powerpc/bootloader/qemu_fakeres.c @ eb36d11

5
Last change on this file since eb36d11 was 03e1d837, checked in by Sebastian Huber <sebastian.huber@…>, on Apr 24, 2018 at 5:06:36 AM

bsps/powerpc: Move bootloader to bsps

This bootloader is only used by the motorola_powerpc BSP.

This patch is a part of the BSP source reorganization.

Update #3285.

  • Property mode set to 100644
File size: 5.8 KB
Line 
1#include <bsp/residual.h>
2#include <stdint.h>
3
4/* Magic knowledge - qemu loads image here.
5 * However, we use the value from NVRAM if possible...
6 */
7#define KERNELBASE 0x01000000
8
9/* When starting qemu make sure to give the correct
10 * amount of memory!
11 *
12 * NOTE: Code now supports reading the actual memory
13 *       amount from NVRAM. The residual copy in RAM
14 *       is fixed-up accordingly.
15 */
16#define MEM_MEGS 32
17
18/* Mock up a minimal/fake residual; just enough to make the
19 * bootloader happy.
20 */
21struct fake_data {
22        unsigned long dat_len;
23        unsigned long res_off;
24        unsigned long cmd_off;
25        unsigned long cmd_len;
26        unsigned long img_adr;
27        RESIDUAL      fake_residual;
28        char          cmdline[1024];
29} fake_data = {
30dat_len: sizeof(fake_data),
31res_off: (unsigned long) &fake_data.fake_residual
32        -(unsigned long) &fake_data,
33cmd_off: (unsigned long) &fake_data.cmdline
34        -(unsigned long) &fake_data,
35cmd_len: sizeof(fake_data.cmdline),
36img_adr: KERNELBASE,
37fake_residual: 
38{
39  ResidualLength: sizeof(RESIDUAL),
40  Version:          0,
41  Revision:         0,
42  EC:               0,
43  VitalProductData: {
44        FirmwareSupplier:  QEMU,
45        ProcessorHz:    300000000, /* fantasy */
46        ProcessorBusHz: 100000000, /* qemu timebase clock */
47        TimeBaseDivisor:1*1000,
48  },
49  MaxNumCpus:       1,
50  ActualNumCpus:    1,
51  Cpus: {
52    {
53        CpuType:        0x00040103, /* FIXME: fill from PVR */
54        CpuNumber:      0, 
55    CpuState:       0,
56    },
57  },
58  /* Memory */
59  TotalMemory:      1024*1024*MEM_MEGS,
60  GoodMemory:       1024*1024*MEM_MEGS,
61  ActualNumMemSegs: 13,
62  Segs: {
63    { 0x2000, 0xFFF00, 0x00100 },
64    { 0x0020, MEM_MEGS*0x100, 0x80000 - MEM_MEGS*0x100 },
65    { 0x0008, 0x00800, 0x00168 },
66    { 0x0004, 0x00000, 0x00005 },
67    { 0x0001, 0x006F1, 0x0010F },
68    { 0x0002, 0x006AD, 0x00044 },
69    { 0x0010, 0x00005, 0x006A8 },
70    { 0x0010, 0x00968, MEM_MEGS*0x100 - 0x00968 },
71    { 0x0800, 0xC0000, 0x3F000 },
72    { 0x0600, 0xBF800, 0x00800 },
73    { 0x0500, 0x81000, 0x3E800 },
74    { 0x0480, 0x80800, 0x00800 },
75    { 0x0440, 0x80000, 0x00800 } 
76  },
77  ActualNumMemories: 0,
78  Memories: {
79        {0},
80  },
81  /* Devices */
82  ActualNumDevices:  1,
83  Devices: {
84        {
85        DeviceId: {
86                BusId:     PROCESSORDEVICE,
87                BaseType:  BridgeController,
88                SubType:   PCIBridge,
89                Interface: PCIBridgeIndirect,
90        },
91        }
92  },
93  DevicePnPHeap: {0}
94},
95/* This is overwritten by command line passed by qemu. */
96cmdline: {
97        '-','-','n','e','2','k','-','i','r','q','=','9',
98        0,
99}
100};
101
102/* Read one byte from NVRAM */
103static inline uint8_t
104nvram_rd(void)
105{
106uint8_t rval = *(volatile uint8_t*)0x80000077;
107        asm volatile("eieio");
108        return rval;
109}
110
111/* Set NVRAM address pointer */
112static inline void
113nvram_addr(uint16_t addr)
114{
115        *(volatile uint8_t*)0x80000074 = (addr & 0xff);
116        asm volatile("eieio");
117        *(volatile uint8_t*)0x80000075 = ((addr>>8) & 0xff);
118        asm volatile("eieio");
119}
120
121/* Read a 32-bit (big-endian) work from NVRAM */
122static uint32_t
123nvram_rdl_be(uint16_t addr)
124{
125int i;
126uint32_t rval = 0;
127        for ( i=0; i<sizeof(rval); i++ ) { 
128                nvram_addr( addr + i );
129                rval = (rval<<8) | nvram_rd();
130        }
131        return rval;
132}
133
134
135/* !!! NOTE !!!
136 *
137 * We use a special hack to propagate command-line info to the bootloader.
138 * This is NOT PreP compliant (but who cares).
139 * We set R6 and R7 to point to the start/end of the command line string
140 * and hacked the bootloader so it uses R6/R7 (provided that the firmware
141 * is detected as 'QEMU').
142 *
143 * (see bootloader/mm.c, bootloader/misc.c,  bootloader/bootldr.h, -- boot_data.cmd_line[])
144 */
145uint32_t
146res_copy(void)
147{
148struct   fake_data *p;
149uint32_t addr, cmdl, l, imga;
150uint32_t mem_sz, pgs;
151int      i;
152int      have_nvram;
153
154        /* Make sure we have a valid NVRAM -- just check for 'QEMU' at the
155         * beginning
156         */
157        have_nvram = ( (('Q'<<24) | ('E'<<16) | ('M'<< 8) | ('U'<< 0)) == nvram_rdl_be( 0x0000 ) );
158
159        if ( !have_nvram ) {
160                /* reading NVRAM failed - fall back to using the static residual copy;
161                 * this means no support for variable memory size or 'true' command line.
162                 */
163                return (uint32_t)&fake_data;
164        }
165
166        /* Dilemma - we don't really know where to put the residual copy
167     * (original is in ROM and cannot be modified).
168         * We can't put it at the top of memory since the bootloader starts
169         * allocating memory from there, before saving the residual, that is.
170         * Too close to the final image might not work either because RTEMS
171         * zeroes its BSS *before* making its copies of the residual and commandline.
172         *
173         * For now we hope that appending to the kernel image works (and that
174         * the bootloader puts it somewhere safe).
175         */
176        imga  = nvram_rdl_be( 0x0038 );
177        addr  = imga + nvram_rdl_be( 0x003c );
178        addr += 0x1f;
179        addr &= ~(0x1f);
180
181        p     = (struct fake_data *)addr;
182
183        /* commandline + length from NVRAM */
184        cmdl  = nvram_rdl_be( 0x0040 );
185        l     = nvram_rdl_be( 0x0044 );
186
187        if ( l > 0 ) {
188                /* have a command-line; copy it into our local buffer */
189                if ( l > sizeof( p->cmdline ) - 1 ) {
190                        l = sizeof( p->cmdline ) - 1;
191                }
192                /* original may overlap our buffer; must safely move around */
193                if ( p->cmdline < (char*)cmdl ) {
194                        for ( i=0; i<l; i++ ) {
195                                p->cmdline[i] = ((char*)cmdl)[i];
196                        }
197                } else {
198                        for ( i=l-1; i>=0; i-- ) {
199                                p->cmdline[i] = ((char*)cmdl)[i];
200                        }
201                }
202        }
203        p->cmdline[l]      = 0;
204        /* Copy rest of residual */
205        for ( i=0; i<sizeof(p->fake_residual); i++ )
206                ((char*)&p->fake_residual)[i] = ((char*)&fake_data.fake_residual)[i];
207        p->dat_len         = fake_data.dat_len;
208        p->res_off         = fake_data.res_off;
209        p->cmd_off         = fake_data.cmd_off;
210        p->cmd_len         = l+1;
211        p->img_adr         = imga;
212
213        /* Fix up memory in residual from NVRAM settings */
214
215        mem_sz = nvram_rdl_be( 0x0030 );
216        pgs    = mem_sz >> 12;
217
218        p->fake_residual.TotalMemory = mem_sz;
219        p->fake_residual.GoodMemory  = mem_sz;
220
221        p->fake_residual.Segs[1].BasePage  = pgs;
222        p->fake_residual.Segs[1].PageCount = 0x80000 - pgs;
223        p->fake_residual.Segs[7].PageCount = pgs - 0x00968;
224
225        return (uint32_t)p;
226}
Note: See TracBrowser for help on using the repository browser.