/[pearpc]/src/io/prom/promboot.cc
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /src/io/prom/promboot.cc

Parent Directory Parent Directory | Revision Log Revision Log


Revision 10 - (hide annotations)
Thu Sep 6 16:47:08 2007 UTC (16 years, 7 months ago) by dpavlin
File size: 43626 byte(s)
display starting message to user
1 dpavlin 1 /*
2     * PearPC
3     * promboot.cc
4     *
5     * Copyright (C) 2004 Stefan Weyergraf
6     * Copyright (C) 2004 Sebastian Biallas (sb@biallas.net)
7     *
8     * This program is free software; you can redistribute it and/or modify
9     * it under the terms of the GNU General Public License version 2 as
10     * published by the Free Software Foundation.
11     *
12     * This program is distributed in the hope that it will be useful,
13     * but WITHOUT ANY WARRANTY; without even the implied warranty of
14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     * GNU General Public License for more details.
16     *
17     * You should have received a copy of the GNU General Public License
18     * along with this program; if not, write to the Free Software
19     * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20     */
21     #include <cstring>
22     #include <sys/time.h>
23     #include <sys/types.h>
24     #include <unistd.h>
25    
26     #include "debug/tracers.h"
27     #include "tools/debug.h"
28     #include "tools/endianess.h"
29     #include "cpu/cpu.h"
30     #include "cpu/mem.h"
31     #include "io/prom/fs/part.h"
32     #include "io/ide/ide.h"
33     #include "io/cuda/cuda.h"
34     #include "system/keyboard.h"
35     #include "system/display.h"
36     #include "system/sys.h"
37     #include "tools/debug.h"
38     #include "tools/except.h"
39     #include "tools/strtools.h"
40     #include "configparser.h"
41     #include "prom.h"
42     #include "promboot.h"
43     #include "promdt.h"
44     #include "prommem.h"
45    
46     #define MSR_SF (1<<31)
47     #define MSR_UNKNOWN (1<<30)
48     #define MSR_UNKNOWN2 (1<<27)
49     #define MSR_VEC (1<<25)
50     #define MSR_KEY (1<<19) // 603e
51     #define MSR_POW (1<<18)
52     #define MSR_TGPR (1<<15) // 603(e)
53     #define MSR_ILE (1<<16)
54     #define MSR_EE (1<<15)
55     #define MSR_PR (1<<14)
56     #define MSR_FP (1<<13)
57     #define MSR_ME (1<<12)
58     #define MSR_FE0 (1<<11)
59     #define MSR_SE (1<<10)
60     #define MSR_BE (1<<9)
61     #define MSR_FE1 (1<<8)
62     #define MSR_IP (1<<6)
63     #define MSR_IR (1<<5)
64     #define MSR_DR (1<<4)
65     #define MSR_PM (1<<2)
66     #define MSR_RI (1<<1)
67     #define MSR_LE (1)
68    
69    
70     byte ELF_PROGRAM_HEADER32_struct[]= {
71     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
72     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
73     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
74     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
75     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
76     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
77     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
78     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
79     0,
80     };
81    
82     byte MACHO_HEADER_struct[]= {
83     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
84     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
85     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
86     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
87     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
88     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
89     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
90     0,
91     };
92    
93     byte MACHO_COMMAND_struct[]= {
94     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
95     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
96     0,
97     };
98    
99     byte MACHO_SEGMENT_COMMAND_struct[]= {
100     STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
101     STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
102     STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
103     STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
104     STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
105     STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
106     STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
107     STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
108     STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
109     STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
110     STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
111     STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
112     STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
113     STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
114     STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
115     STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
116     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
117     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
118     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
119     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
120     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
121     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
122     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
123     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
124     0,
125     };
126    
127     byte MACHO_THREAD_COMMAND_struct[] = {
128     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
129     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
130    
131     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
132     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
133     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
134     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
135     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
136     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
137     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
138     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
139     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
140     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
141     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
142     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
143     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
144     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
145     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
146     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
147     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
148     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
149     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
150     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
151     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
152     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
153     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
154     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
155     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
156     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
157     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
158     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
159     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
160     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
161     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
162     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
163     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
164     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
165     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
166     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
167     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
168     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
169     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
170     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
171     0,
172     };
173    
174    
175     struct MachOHeader {
176     byte magic[4];
177     uint32 cputype;
178     uint32 cpusubtype;
179     uint32 filetype;
180     uint32 ncmds;
181     uint32 sizeofcmds;
182     uint32 flags;
183     };
184    
185     struct MachOCommand {
186     uint32 cmd; /* type of load command */
187     uint32 cmdsize; /* total size of command in bytes */
188     };
189    
190    
191     struct MachOSegmentCommand {
192     byte segname[16]; /* segment name */
193     uint32 vmaddr; /* memory address of this segment */
194     uint32 vmsize; /* memory size of this segment */
195     uint32 fileoff; /* file offset of this segment */
196     uint32 filesize; /* amount to map from the file */
197     uint32 maxprot; /* maximum VM protection */
198     uint32 initprot; /* initial VM protection */
199     uint32 nsects; /* number of sections in segment */
200     uint32 flags; /* flags */
201     };
202    
203     struct MachOPPCThreadState {
204     uint32 flavor; /* flavor of thread state */
205     uint32 count; /* count of longs in thread state */
206    
207     uint32 srr0; /* Instruction address register (PC) */
208     uint32 srr1; /* Machine state register (supervisor) */
209     uint32 r[32];
210     uint32 cr; /* Condition register */
211     uint32 xer; /* User's integer exception register */
212     uint32 lr; /* Link register */
213     uint32 ctr; /* Count register */
214     uint32 mq; /* MQ register (601 only) */
215    
216     uint32 vrsave; /* Vector Save Register */
217     };
218    
219     typedef struct COFF_HEADER {
220     uint16 machine PACKED;
221     uint16 section_count PACKED;
222     uint32 timestamp PACKED;
223     uint32 symbol_table_offset PACKED;
224     uint32 symbol_count PACKED;
225     uint16 optional_header_size PACKED;
226     uint16 characteristics PACKED;
227     };
228    
229     byte COFF_HEADER_struct[] = {
230     STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
231     STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
232     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
233     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
234     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
235     STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
236     STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
237     0
238     };
239    
240     #define COFF_SIZEOF_SHORT_NAME 8
241    
242     struct COFF_SECTION_HEADER {
243     byte name[COFF_SIZEOF_SHORT_NAME];
244     uint32 data_vsize; // or data_phys_address !
245     uint32 data_address;
246     uint32 data_size;
247     uint32 data_offset;
248     uint32 relocation_offset;
249     uint32 linenumber_offset;
250     uint16 relocation_count;
251     uint16 linenumber_count;
252     uint32 characteristics;
253     } PACKED;
254    
255     byte COFF_SECTION_HEADER_struct[] = {
256     COFF_SIZEOF_SHORT_NAME,
257     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
258     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
259     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
260     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
261     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
262     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
263     STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
264     STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
265     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
266     0
267     };
268    
269     #define ELF_SIZEOF_IDENT 16
270    
271     static byte ELF_HEADER_struct[] = {
272     ELF_SIZEOF_IDENT,
273     STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST, // e_type
274     STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST, // e_machine
275     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST, // e_version
276     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST, // e_entry
277     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST, // e_phoff
278     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST, // e_shoff
279     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST, // e_flags
280     STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST, // e_ehsize
281     STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST, // e_phentsize
282     STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST, // e_phnum
283     STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST, // e_shentsize
284     STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST, // e_shnum
285     STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST, // e_shstrndx
286     0
287     };
288    
289     static byte ELF_PHEADER_struct[] = {
290     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST, // p_type
291     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST, // p_offset
292     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST, // p_vaddr
293     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST, // p_paddr
294     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST, // p_filesz
295     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST, // p_memsz
296     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST, // p_flags
297     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST, // p_align
298     0
299     };
300    
301     static byte ELF_NHEADER_struct[] = {
302     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST, // n_namesz
303     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST, // n_descsz
304     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST, // n_type
305     0
306     };
307    
308     struct ELF_HEADER32 {
309     uint8 e_ident[ELF_SIZEOF_IDENT];
310     uint16 e_type;
311     uint16 e_machine;
312     uint32 e_version;
313     uint32 e_entry;
314     uint32 e_phoff;
315     uint32 e_shoff;
316     uint32 e_flags;
317     uint16 e_ehsize;
318     uint16 e_phentsize;
319     uint16 e_phnum;
320     uint16 e_shentsize;
321     uint16 e_shnum;
322     uint16 e_shstrndx;
323     };
324    
325     struct ELF_PROGRAM_HEADER32 {
326     uint32 p_type;
327     uint32 p_offset;
328     uint32 p_vaddr;
329     uint32 p_paddr;
330     uint32 p_filesz;
331     uint32 p_memsz;
332     uint32 p_flags;
333     uint32 p_align;
334     };
335    
336     struct ELF_NHEADER32 {
337     uint32 n_descsz;
338     uint32 n_namesz;
339     uint32 n_type;
340     };
341    
342     struct CHRP_desc {
343     uint32 real_mode;
344     uint32 real_base;
345     uint32 real_size;
346     uint32 virt_base;
347     uint32 virt_size;
348     uint32 load_base;
349     };
350    
351     static byte ELF_DESC_struct[] = {
352     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST, // real_mode
353     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST, // real_base
354     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST, // real_size
355     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST, // virt_base
356     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST, // virt_size
357     STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST, // load_base
358     0
359     };
360    
361     static bool real_mode = false;
362    
363     /*
364     * helpers
365     */
366     static bool init_page_create(uint32 ea, uint32 pa)
367     {
368     return prom_claim_page(pa) && ppc_prom_page_create(ea, pa);
369     }
370    
371     static bool chrp_init_page_create(uint32 ea, uint32 pa, int no_claim)
372     {
373     bool ret = true;
374    
375     if (!no_claim)
376     ret = prom_claim_page(pa);
377    
378     if (real_mode)
379     return ret;
380     else
381     return ret && ppc_prom_page_create(ea, pa);
382     }
383    
384     /*
385     * ELF
386     */
387     //#define ELF_LOAD_ADDRESS 0x20000
388     #define ELF_LOAD_ADDRESS 0x800000
389     #define ROM_BASE 0x40800000
390     #define MAX_ELF_HEADERS 32
391     #define PPC_PAGE_SIZE 4096
392     #define PPC_PAGE_MASK 0x00000fff
393    
394     #define PROMBOOT_OUTPUT(...) do { \
395     gDisplay->printf(__VA_ARGS__); \
396     ht_printf(__VA_ARGS__); \
397     } while(0)
398    
399     #define PLOAD_NOCOPY (1 << 0)
400     #define PLOAD_PADDR_MAP (1 << 1)
401    
402     bool promboot_copy_file_to_memory(File &f, uint32 &paddr, uint32 &vaddr, sint32 loader_size, sint32 zero_size, int flags)
403     {
404     byte page[PPC_PAGE_SIZE];
405    
406     bool no_copy = flags & PLOAD_NOCOPY;
407     bool paddr_map = flags & PLOAD_PADDR_MAP;
408    
409     bool copy = !no_copy;
410     if (paddr_map) {
411     copy = true;
412     }
413     printf("promboot_copy_file_to_memory(%08x, %08x, %08x, %08x)\n", paddr, vaddr, loader_size, zero_size);
414     while (loader_size > 0) {
415     sint32 size = loader_size;
416     if (size > PPC_PAGE_SIZE)
417     size = PPC_PAGE_SIZE;
418    
419     /* if (paddr_map && !chrp_init_page_create(vaddr, paddr, false)) {
420     PROMBOOT_OUTPUT("PROM ERROR: Unable to create load page!\n");
421     return false;
422     }*/
423    
424     if (!chrp_init_page_create(vaddr, paddr, no_copy)) {
425     PROMBOOT_OUTPUT("LOADER WARNING: data overwrite!\n");
426     return false;
427     }
428    
429     if (copy) {
430     f.readx(page, size);
431    
432     if (size < PPC_PAGE_SIZE && zero_size) {
433     sint32 offset = size;
434    
435     size += zero_size;
436     if (size > PPC_PAGE_SIZE) {
437     size = PPC_PAGE_SIZE;
438     }
439    
440     memset(page+offset, 0, size-offset);
441     }
442    
443     if (!ppc_dma_write(paddr, page, size)) {
444     PROMBOOT_OUTPUT("LOADER ERROR: Unable to write page!\n");
445     return false;
446     }
447     }
448    
449     paddr += PPC_PAGE_SIZE;
450     vaddr += PPC_PAGE_SIZE;
451     loader_size -= size;
452     }
453    
454     if (zero_size > 0) {
455     loader_size += zero_size;
456    
457     if (copy) memset(page, 0, PPC_PAGE_SIZE);
458    
459     while(loader_size > 0) {
460     sint32 size = loader_size;
461     if (size > PPC_PAGE_SIZE)
462     size = PPC_PAGE_SIZE;
463    
464     if (!chrp_init_page_create(vaddr, paddr, no_copy)) {
465     PROMBOOT_OUTPUT("LOADER WARNING: zero-page overwrite!\n");
466     return false;
467     }
468     if (copy) {
469     if (!ppc_dma_write(paddr, page, size)) {
470     PROMBOOT_OUTPUT("LOADER ERROR: Unable to write page!\n");
471     return false;
472     }
473     }
474     paddr += PPC_PAGE_SIZE;
475     vaddr += PPC_PAGE_SIZE;
476     loader_size -= size;
477     }
478     }
479     }
480    
481     extern uint32 gMemorySize;
482    
483     /* Based on those standards from:
484     * PowerPC Microprocessor Common Hardware Reference Platform (CHRP)
485     * System binding to: IEEE Std 1275-1994
486     * Standard for Boot (Initialization, Configuration)
487     * Firmware
488     * Revision: 1.8 [Approved Version]
489     * Date: Feburary 2, 1998
490     */
491     bool mapped_load_elf_from_chrp(File &f, uint disp_off)
492     {
493     String fn;
494 dpavlin 8 PROMBOOT_OUTPUT("ELF: trying to load '%y' (CHRP)\n", &f.getDesc(fn));
495 dpavlin 1 try {
496     ELF_HEADER32 hdr;
497     ELF_PROGRAM_HEADER32 *phdr;
498     ELF_NHEADER32 nhdr;
499     uint32 stack = 0;
500     uint32 stackp = 0;
501    
502     // for (int i=0; i < gMemorySize - PROM_MEM_SIZE; i+=4096)
503     // ppc_prom_page_create(i, i);
504    
505     f.seek(disp_off);
506     f.readx(&hdr, sizeof hdr);
507     createHostStructx(&hdr, sizeof hdr, ELF_HEADER_struct, big_endian);
508    
509     if (hdr.e_ident[0] != 0x7f
510     || hdr.e_ident[1] != 'E'
511     || hdr.e_ident[2] != 'L'
512     || hdr.e_ident[3] != 'F') {
513     PROMBOOT_OUTPUT("ELF ERROR: bad magic number.\n");
514     return false;
515     }
516    
517     if (hdr.e_ident[4] != 1) {
518     PROMBOOT_OUTPUT("ELF ERROR: non-32-bit ELF.\n");
519     return false;
520     }
521    
522     if (hdr.e_ident[5] != 2) {
523     PROMBOOT_OUTPUT("ELF ERROR: non-big-endian ELF.\n");
524     return false;
525     }
526    
527     if (hdr.e_type != 2) {
528     PROMBOOT_OUTPUT("ELF ERROR: non-executable ELF.\n");
529     return false;
530     }
531     if (hdr.e_machine != 20) {
532     PROMBOOT_OUTPUT("ELF ERROR: non-PowerPC ELF.\n");
533     return false;
534     }
535     if (hdr.e_version != 1) {
536     PROMBOOT_OUTPUT("ELF ERROR: bad ELF version.\n");
537     return false;
538     }
539     if (hdr.e_flags != 0) {
540     PROMBOOT_OUTPUT("ELF ERROR: non-empty flag field.\n");
541     return false;
542     }
543    
544     /* Non-specification limit */
545     if (hdr.e_phnum > MAX_ELF_HEADERS) {
546     PROMBOOT_OUTPUT("ELF ERROR: too many program headers.\n");
547     return false;
548     }
549    
550     phdr = new ELF_PROGRAM_HEADER32[hdr.e_phnum];
551     f.seek(disp_off + hdr.e_phoff);
552     f.readx(phdr, sizeof(ELF_PROGRAM_HEADER32) * hdr.e_phnum);
553     for (int i=0; i < hdr.e_phnum; i++) {
554     createHostStructx(&(phdr[i]), sizeof(phdr[i]), ELF_PHEADER_struct, big_endian);
555     }
556    
557     uint32 load_base = ELF_LOAD_ADDRESS;
558     uint32 real_base = 0x00000000;
559     uint32 real_size = 0xffffffff;
560     uint32 virt_base = 0x00000000;
561     uint32 virt_size = 0xffffffff;
562    
563     for (int i=0; i < hdr.e_phnum; i++) {
564     if (phdr[i].p_type == 4) { // PT_NOTE
565     f.seek(disp_off + phdr[i].p_offset);
566     f.readx(&nhdr, sizeof nhdr);
567    
568     createHostStructx(&nhdr, sizeof nhdr, ELF_NHEADER_struct, big_endian);
569    
570     if (nhdr.n_type != 0x1275) {
571     PROMBOOT_OUTPUT("ELF WARNING: unusual PT_NOTE section: %04x\n", nhdr.n_type);
572     continue;
573     }
574    
575     char *name;
576     name = (char *)malloc(nhdr.n_namesz);
577     f.readx(name, nhdr.n_namesz);
578     PROMBOOT_OUTPUT("ELF PT_NOTE: Name '%s'\n", name);
579     free(name);
580    
581     CHRP_desc *desc;
582     desc = (CHRP_desc *)malloc(nhdr.n_descsz);
583     f.readx(desc, nhdr.n_descsz);
584     createHostStructx(desc, sizeof(CHRP_desc), ELF_DESC_struct, big_endian);
585    
586     real_mode = desc->real_mode;
587    
588     if (desc->real_base != -1)
589     real_base = desc->real_base;
590    
591     if (desc->real_size != -1)
592     real_size = desc->real_size;
593    
594     if (desc->virt_base != -1)
595     virt_base = desc->virt_base;
596    
597     if (desc->virt_size != -1)
598     virt_size = desc->virt_size;
599    
600     if (desc->load_base != -1)
601     load_base = desc->load_base;
602    
603     free(desc);
604     break;
605     }
606     }
607    
608     PROMBOOT_OUTPUT("ELF: real-mode: %s\n", real_mode ? "true" : "false");
609     PROMBOOT_OUTPUT("ELF: real-base: %08x\n", real_base);
610     PROMBOOT_OUTPUT("ELF: real-size: %08x\n", real_size);
611     PROMBOOT_OUTPUT("ELF: virt-base: %08x\n", virt_base);
612     PROMBOOT_OUTPUT("ELF: virt-size: %08x\n", virt_size);
613     PROMBOOT_OUTPUT("ELF: load-base: %08x\n", load_base);
614    
615     if (real_mode) {
616     PROMBOOT_OUTPUT("ELF ERROR: real-mode bootup not supported.\n");
617     return false;
618     }
619    
620     sint32 client_size = f.getSize() - disp_off;
621    
622     uint32 paddr = load_base;
623     byte page[PPC_PAGE_SIZE];
624    
625     f.seek(disp_off);
626     // promboot_copy_file_to_memory(f, paddr, vaddr, client_size, 0, PLOAD_PADDR_MAP);
627    
628     for (int i=0; i < hdr.e_phnum; i++) {
629     if (phdr[i].p_type != 1) // PT_LOAD
630     continue;
631    
632     uint32 vaddr = phdr[i].p_vaddr;
633    
634     sint32 loader_size = phdr[i].p_filesz;
635     if (loader_size > phdr[i].p_memsz) {
636     loader_size = phdr[i].p_memsz;
637     }
638    
639     sint32 zero_size = 0;
640     if (phdr[i].p_memsz > phdr[i].p_filesz)
641     zero_size = phdr[i].p_memsz - phdr[i].p_filesz;
642    
643     f.seek(disp_off+phdr[i].p_offset);
644    
645     promboot_copy_file_to_memory(f, paddr, vaddr, loader_size, zero_size, 0);
646     }
647    
648     stack = gMemorySize - 21*4096 - PROM_MEM_SIZE;
649     stackp = gMemorySize - 21*4096 - PROM_MEM_SIZE;
650     //stack = (stack + PPC_PAGE_MASK) & ~PPC_PAGE_MASK;
651     //stackp = (stackp + PPC_PAGE_MASK) & ~PPC_PAGE_MASK;
652    
653     for (int i=0; i<20; i++) {
654     if (!init_page_create(stack, stackp)) {
655     PROMBOOT_OUTPUT("ELF ERROR: Unable to create stack page %i!\n", i);
656     return false;
657     }
658    
659     stack += PPC_PAGE_SIZE;
660     stackp += PPC_PAGE_SIZE;
661     }
662    
663     delete[] phdr;
664    
665     ppc_cpu_set_pc(0, hdr.e_entry);
666    
667     if (real_mode) {
668     ppc_cpu_set_msr(0, MSR_FP);
669     ppc_cpu_set_gpr(0, 1, stackp-(4096+32));
670     } else { // turn on address translation
671     ppc_cpu_set_msr(0, MSR_IR | MSR_DR | MSR_FP);
672     ppc_cpu_set_gpr(0, 1, stack-(4096+32));
673     }
674    
675     ppc_cpu_set_gpr(0, 2, 0);
676     ppc_cpu_set_gpr(0, 3, 0);
677     ppc_cpu_set_gpr(0, 4, 0);
678     ppc_cpu_set_gpr(0, 5, gPromOSIEntry);
679    
680     PROMBOOT_OUTPUT("Booting ELF...\n");
681    
682     ppc_prom_page_create(0, 0);
683     return true;
684     } catch (...) {
685     PROMBOOT_OUTPUT("ELF ERROR: caught exception.\n");
686     return false;
687     }
688     }
689    
690     bool mapped_load_elf(File &f)
691     {
692     String fn;
693     gDisplay->printf("ELF: trying to load '%y'\n", &f.getDesc(fn));
694     IO_PROM_TRACE("ELF: trying to load '%y'\n", &fn);
695     try {
696     // FIXME: better code
697     byte magic[4];
698     f.seek(0);
699     f.readx(magic, 4);
700     if ((magic[0] != 0x7f) || (magic[1] != 'E')
701     || (magic[2] != 'L') ||(magic[3] != 'F')) {
702     IO_PROM_TRACE("no ELF\n");
703     return false;
704     }
705    
706 dpavlin 8 uint32 entry;
707 dpavlin 1 uint32 la = ELF_LOAD_ADDRESS;
708     f.seek(0x2c);
709     uint16 program_hdrs;
710     f.readx(&program_hdrs, 2);
711     program_hdrs = createHostInt(&program_hdrs, 2, big_endian);
712     uint32 stack=0;
713     uint32 stackp=0;
714     for (int i=0; i<program_hdrs; i++) {
715 dpavlin 8 IO_PROM_TRACE("program header %d:\n", i);
716 dpavlin 1 ELF_PROGRAM_HEADER32 program_hdr;
717     f.seek(0x34+i*sizeof program_hdr);
718     f.readx(&program_hdr, sizeof program_hdr);
719     createHostStructx(&program_hdr, sizeof program_hdr, ELF_PROGRAM_HEADER32_struct, big_endian);
720     uint32 pages_from_file = program_hdr.p_filesz / 4096;
721     uint32 ea = program_hdr.p_vaddr;
722 dpavlin 8 ea = 0x00000000; // XXX force load to beginning of RAM
723     entry = ea;
724 dpavlin 1 sint32 vs = program_hdr.p_memsz;
725     f.seek(program_hdr.p_offset);
726     uint32 fo = program_hdr.p_offset;
727     byte page[4096];
728     while (pages_from_file) {
729 dpavlin 8 IO_PROM_TRACE("loading from %08x to ea:%08x (pa:%08x)\n", fo, ea, la);
730 dpavlin 1 f.readx(page, sizeof page);
731     if (!init_page_create(ea, la)) return false;
732     if (!ppc_dma_write(la, page, 4096)) {
733     return false;
734     }
735     pages_from_file--;
736     la += 4096;
737     ea += 4096;
738     fo += 4096;
739     vs -= 4096;
740     }
741     if (program_hdr.p_filesz % 4096) {
742 dpavlin 8 ht_printf("loading remaining from %08x to ea:%08x (pa:%08x)\n", fo, ea, la);
743 dpavlin 1 f.read(page, program_hdr.p_filesz % 4096);
744     if (!init_page_create(ea, la)) return false;
745     if (!ppc_dma_write(la+(ea&0xfff), page, program_hdr.p_filesz % 4096)) {
746     return false;
747     }
748     la += 4096;
749     ea += 4096;
750     fo += 4096;
751     vs -= 4096;
752     }
753     while (vs > 0) {
754 dpavlin 8 ht_printf("creating for ea:%08x (pa:%08x)\n", ea, la);
755 dpavlin 1 if (!init_page_create(ea, la)) return false;
756     la += 4096;
757     ea += 4096;
758     vs -= 4096;
759     }
760     stack = ea;
761     stackp = la;
762     }
763    
764     stack = gMemorySize - 65536 - (4096*20) - PROM_MEM_SIZE;
765     stackp = gMemorySize - 65536 - (4096*20) - PROM_MEM_SIZE;
766     // allocate stack
767     for (int i=0; i<20; i++) {
768     if (!init_page_create(stack, stackp)) return false;
769     stack += 4096;
770     stackp += 4096;
771     }
772    
773 dpavlin 10 gDisplay->printf("starting from PC %08x\n", entry);
774 dpavlin 1
775     // turn on address translation
776     ppc_cpu_set_msr(0, MSR_IR | MSR_DR | MSR_FP);
777     ppc_cpu_set_pc(0, entry);
778    
779     ppc_cpu_set_gpr(0, 1, gMemorySize - 65536 - 32 - PROM_MEM_SIZE);
780     ppc_cpu_set_gpr(0, 2, 0);
781     ppc_cpu_set_gpr(0, 3, 0);
782     ppc_cpu_set_gpr(0, 4, 0);
783     ppc_cpu_set_gpr(0, 5, gPromOSIEntry);
784    
785     // wtf?!
786     ppc_prom_page_create(0, 0);
787     return true;
788     } catch (...) {
789     return false;
790     }
791     }
792    
793     /*
794     * XCOFF
795     */
796     bool mapped_load_xcoff(File &f, uint disp_ofs)
797     {
798     String fn;
799     gDisplay->printf("XCOFF trying to load '%y'\n", &f.getDesc(fn));
800     IO_PROM_TRACE("XCOFF trying to load '%y'\n", &fn);
801    
802     f.seek(disp_ofs);
803     try {
804     COFF_HEADER hdr;
805     f.readx(&hdr, sizeof hdr);
806     createHostStructx(&hdr, sizeof hdr, COFF_HEADER_struct, big_endian);
807     if (hdr.machine != 0x1df) {
808     IO_PROM_TRACE("invalid machine %04x (expecting 01df)\n", hdr.machine);
809     return false;
810     }
811     if (hdr.optional_header_size != 0x48) {
812     IO_PROM_TRACE("invalid optional header size %04x (expecting 0048)\n", hdr.optional_header_size);
813     return false;
814     }
815     uint32 stack=0;
816     uint32 stackp=0;
817     uint32 entrypoint;
818     uint32 entrypoint_ofs = 0;
819     f.seek(disp_ofs+0x24);
820     f.readx(&entrypoint, 4);
821     entrypoint = createHostInt(&entrypoint, 4, big_endian);
822    
823     for (int i=0; i<hdr.section_count; i++) {
824     // ht_printf("program header %d:\n", i);
825     COFF_SECTION_HEADER shdr;
826     f.seek(disp_ofs+0x5c+i*sizeof shdr);
827     f.readx(&shdr, sizeof shdr);
828     createHostStructx(&shdr, sizeof shdr, COFF_SECTION_HEADER_struct, big_endian);
829     if ((entrypoint >= shdr.data_address) && (entrypoint < shdr.data_address+shdr.data_size)) {
830     IO_PROM_TRACE("found entrypoint-structure in section %d\n", i);
831     entrypoint_ofs = entrypoint - shdr.data_address + shdr.data_offset;
832     }
833     uint32 in_file_size = (shdr.data_offset) ? shdr.data_size : 0;
834     uint32 pages_from_file = in_file_size / 4096;
835     uint32 pa = shdr.data_vsize; /* really: physical addr */
836     uint32 ea = shdr.data_address;
837     sint32 vs = shdr.data_size;
838     f.seek(disp_ofs+shdr.data_offset);
839     uint32 fo = shdr.data_offset;
840     byte page[4096];
841     while (pages_from_file) {
842     // ht_printf("loading from %08x to ea:%08x (pa:%08x)\n", fo, ea, pa);
843     f.readx(page, sizeof page);
844     if (!init_page_create(ea, pa)) return false;
845     if (!ppc_dma_write(pa, page, 4096)) {
846     return false;
847     }
848     pages_from_file--;
849     pa += 4096;
850     ea += 4096;
851     fo += 4096;
852     vs -= 4096;
853     }
854     if (in_file_size % 4096) {
855     // ht_printf("loading remaining from %08x to ea:%08x (pa:%08x)\n", fo, ea, pa);
856     f.readx(page, in_file_size % 4096);
857     if (!init_page_create(ea, pa)) return false;
858     if (!ppc_dma_write(pa+(ea&0xfff), page, in_file_size % 4096)) {
859     return false;
860     }
861     pa += 4096;
862     ea += 4096;
863     fo += 4096;
864     vs -= 4096;
865     }
866     while (vs > 0) {
867     // ht_printf("creating for ea:%08x (pa:%08x)\n", ea, pa);
868     if (!init_page_create(ea, pa)) return false;
869     pa += 4096;
870     ea += 4096;
871     vs -= 4096;
872     }
873     stack = ea;
874     stackp = pa;
875     }
876     if (!entrypoint_ofs) {
877     IO_PROM_TRACE("couldn't find entrypoint offset\n");
878     return false;
879     }
880     // allocate stack
881     for (int i=0; i<20; i++) {
882     if (!init_page_create(stack, stackp)) return false;
883     stack += 4096;
884     stackp += 4096;
885     }
886    
887     uint32 real_entrypoint = 0;
888     f.seek(disp_ofs+entrypoint_ofs);
889     f.read(&real_entrypoint, 4);
890     real_entrypoint = createHostInt(&real_entrypoint, 4, big_endian);
891     IO_PROM_TRACE("real_entrypoint = %08x\n", real_entrypoint);
892     // turn on address translation
893     ppc_cpu_set_msr(0, MSR_IR | MSR_DR | MSR_FP);
894     ppc_cpu_set_pc(0, real_entrypoint);
895    
896     ppc_cpu_set_gpr(0, 1, stack-(4096+32));
897     ppc_cpu_set_gpr(0, 2, 0);
898     ppc_cpu_set_gpr(0, 3, 0);
899     ppc_cpu_set_gpr(0, 4, 0);
900     ppc_cpu_set_gpr(0, 5, gPromOSIEntry);
901    
902     return true;
903     } catch (...) {
904     return false;
905     }
906     }
907    
908     static void chrpReadWaitForChar(File &f, char *buf, uint buflen, char waitFor)
909     {
910     while (buflen) {
911     f.readx(buf, 1);
912    
913     if (*buf == 0x0d) *buf = '\n';
914    
915     if (!*buf) throw new MsgException("Binary files not allowed here");
916     if (*buf == waitFor) {
917     *buf = 0;
918     return;
919     }
920     buf++;
921     buflen--;
922     }
923     throw new MsgException("wait for char failed");
924     }
925    
926     static void chrpReadWaitForString(File &f, char *buf, uint buflen, char *waitFor)
927     {
928     uint zlen = strlen(waitFor);
929     char *z = strdup(waitFor);
930     *z = 0;
931     *buf = 0;
932     if (!zlen) return;
933     FileOfs o = f.tell();
934     while (buflen) {
935     f.seek(o);
936     f.readx(z, zlen);
937     if (strcmp(z, waitFor) == 0) {
938     *buf = 0;
939     free(z);
940     return;
941     }
942     if (buf != NULL) {
943     *buf = (*z == 0xd) ? '\n' : *z;
944     buf++;
945     buflen--;
946     }
947     o++;
948     }
949     free(z);
950     throw new MsgException("wait for string failed");
951     }
952    
953     #if 0
954     static void readCHRPIcon(byte *icon, char *&t, uint width, uint height)
955     {
956     memset(icon, 0, width*height);
957     uint y = 0;
958     uint x = 0;
959     while (t[0] && t[1]) {
960     if (t[0] == '\n') {
961     while (*t == '\n') t++;
962     // fprintf(stderr, "parse icon: line %d length %d\n", y, x);
963     x = 0;
964     y++;
965     if (y >= height) break;
966     continue;
967     }
968     if (x>=width) break;
969     hexb_ex(icon[x+y*width], t);
970     t += 2;
971     x++;
972     }
973     }
974     #endif
975    
976     static bool chrpBoot(const char *bootpath, const char *bootargs)
977     {
978     IO_PROM_TRACE("CHRP boot file (bootpath = %s, bootargs = %s).\n", bootpath, bootargs);
979     // set bootpath in device tree
980     PromNode *chosen = findDevice("/chosen", FIND_DEVICE_FIND, NULL);
981     if (chosen) {
982     PromProp *bp = chosen->findProp("bootpath");
983     if (bp) {
984     PromPropString *s = dynamic_cast<PromPropString*>(bp);
985     if (s) {
986     free(s->value);
987     s->value = strdup(bootpath);
988     }
989     } else {
990     chosen->addProp(new PromPropString("bootpath", bootpath));
991     }
992     PromProp *ba = chosen->findProp("bootargs");
993     if (ba) {
994     PromPropString *s = dynamic_cast<PromPropString*>(ba);
995     if (s) {
996     free(s->value);
997     s->value = strdup(bootargs);
998     }
999     } else {
1000     chosen->addProp(new PromPropString("bootargs", bootargs));
1001     }
1002     }
1003    
1004     PromInstanceHandle ih;
1005     if (!findDevice(bootpath, FIND_DEVICE_OPEN, &ih)) return false;
1006    
1007     PromInstanceDiskFile *ix = dynamic_cast<PromInstanceDiskFile*>(handleToInstance(ih));
1008     if (!ix || !ix->mFile) {
1009     IO_PROM_TRACE("couldn't load CHRP boot file (1) (bootpath = %s).\n", bootpath);
1010     return false;
1011     }
1012    
1013     PromNode *pn = ix->getType();
1014     File *f = ix->mFile;
1015    
1016     if (!mapped_load_elf(*f)
1017     && !mapped_load_xcoff(*f, 0)
1018     && !mapped_load_chrp(*f)) {
1019     IO_PROM_TRACE("couldn't load CHRP boot file (2) (bootpath = %s).\n", bootpath);
1020     pn->close(ih);
1021     return false;
1022     }
1023     pn->close(ih);
1024     return true;
1025     }
1026    
1027     bool mapped_load_chrp(File &f)
1028     {
1029     String fn;
1030     gDisplay->printf("CHRP: trying to load '%y'\n", &f.getDesc(fn));
1031     IO_PROM_TRACE("CHRP: trying to load '%y'\n", &fn);
1032     try {
1033     char hdr[13];
1034     f.seek(0);
1035     if (f.read(hdr, 12) != 12) return false;
1036     hdr[12] = 0;
1037     IO_PROM_TRACE("header: %s\n", hdr);
1038     if (strncmp(hdr, "<CHRP-BOOT>", 11)) return false;
1039     IO_PROM_TRACE("CHRP-BOOT OK\n");
1040     char buf[32*1024];
1041     uint buflen;
1042     char tag[32*1024];
1043     char expect[4*1024+1]; // sizeof buf+1
1044     while (1) {
1045     chrpReadWaitForChar(f, buf, sizeof buf, '\n');
1046     buflen = strlen(buf);
1047     IO_PROM_TRACE("read %d bytes: %s\n", buflen, buf);
1048     if (buflen < 1)
1049     continue;
1050     if ((buf[0] != '<') || (buflen<3) || (buf[buflen-1] != '>')) return false;
1051     if (buf[1] == '/') {
1052     if (memcmp(buf, "</CHRP-BOOT>", buflen-1) != 0)
1053     return false;
1054     byte b;
1055     FileOfs from = f.tell();
1056     while (1) {
1057     if (!f.read(&b, 1)) return false;
1058     if (b == 0x01) break;
1059     }
1060     if (b != 0x01) return false;
1061     if (!f.read(&b, 1)) return false;
1062     if (b == 0xdf) {
1063     PROMBOOT_OUTPUT("Loading XCOFF...\n");
1064     return mapped_load_xcoff(f, f.tell()-2);
1065     } else if (b == 0x02) {
1066     f.seek(from);
1067     while (1) {
1068     if (!f.read(&b, 1))
1069     return false;
1070     if (b == 0x7f) break;
1071     }
1072    
1073     PROMBOOT_OUTPUT("Loading ELF...\n");
1074     return mapped_load_elf_from_chrp(f, f.tell()-1);
1075     } else
1076     return false;
1077     }
1078     expect[0] = '<';
1079     expect[1] = '/';
1080     int index;
1081     for (index=0; index<buflen-1; index++) {
1082     if (buf[index+1] == ' ') break;
1083     if (buf[index+1] == '>') break;
1084     expect[index+2] = buf[index+1];
1085     }
1086     //memcpy(expect+2, buf+1, buflen-1);
1087     //expect[buflen+1] = '\n';
1088     expect[index+2] = '>';
1089     expect[index+3] = 0;
1090     strcpy(tag, buf);
1091     IO_PROM_TRACE("waitforstring: %s\n", expect);
1092     chrpReadWaitForString(f, buf, sizeof buf, expect);
1093     IO_PROM_TRACE("found: %s\n", buf);
1094     if (strcmp(tag, "<BOOT-SCRIPT>") == 0) {
1095     char *bootpath = strstr(buf, "boot ");
1096     if (bootpath) {
1097     bootpath += 5;
1098     char *bootpathend = strchr(bootpath, '\n');
1099     if (!bootpathend) bootpathend = bootpath + strlen(bootpath);
1100     char mybootpath[1024];
1101     char *mybootargs = NULL;
1102     strncpy(mybootpath, bootpath, sizeof mybootpath-1);
1103     mybootpath[bootpathend-bootpath] = 0;
1104     mybootpath[sizeof mybootpath-1] = 0;
1105     mybootargs = mybootpath+ sizeof mybootpath-1;
1106     int l = strlen(mybootpath);
1107     for (int i=0; i<l; i++) {
1108     if (mybootpath[i] == '\n') {
1109     mybootpath[i] = 0;
1110     break;
1111     } else if (mybootpath[i] == ' ') {
1112     mybootpath[i] = 0;
1113     mybootargs = mybootpath+i+1;
1114     break;
1115     }
1116     }
1117     return chrpBoot(mybootpath, mybootargs);
1118     }
1119     }
1120     #if 0
1121     if (strcmp(tag, "<OS-BADGE-ICONS>") == 0) {
1122     char *t = buf;
1123     uint width = 1000, height = 1000;
1124     char fmt[64];
1125     while (*t && *t != '\n') t++;
1126     if (*t == '\n') t++;
1127     if (t-buf < (int)sizeof buf) {
1128     strncpy(fmt, buf, t-buf);
1129     fmt[t-buf] = 0;
1130     } else {
1131     fmt[0] = 0;
1132     }
1133     // fprintf(stderr, "format string: %s\n", fmt);
1134     if (strlen(fmt) == 4) {
1135     uint8 x;
1136     if (hexb_ex(x, fmt)) width = x;
1137     if (hexb_ex(x, fmt+2)) height = x;
1138     } else if (strlen(fmt) == 8) {
1139     uint16 x;
1140     if (hexw_ex(x, fmt)) width = x;
1141     if (hexw_ex(x, fmt+4)) height = x;
1142     }
1143     if ((width > 128) || (height > 128)) {
1144     // safety
1145     width = 16;
1146     height = 16;
1147     }
1148     byte icon0[width*height];
1149     byte icon1[width*height];
1150     byte icon2[width*height];
1151     readCHRPIcon(icon0, t, width, height);
1152     readCHRPIcon(icon1, t, width, height);
1153     readCHRPIcon(icon2, t, width, height);
1154     uint8 colors2_r[] = {0xff, 0xaa, 0x55, 0x00};
1155     uint8 colors3_r[] = {0xff, 0xdb, 0xb7, 0x92, 0x6e, 0x49, 0x25, 0x00};
1156     uint8 colors2[] = {0x00, 0x55, 0xaa, 0xff};
1157     uint8 colors3[] = {0x00, 0x25, 0x49, 0x6e, 0x92, 0xb7, 0xdb, 0xff};
1158     for (uint y=0; y < height; y++) {
1159     for (uint x=0; x < height; x++) {
1160     uint8 r = colors3_r[(icon0[x+y*width]>>5) & 0x7];
1161     uint8 g = colors3_r[(icon0[x+y*width]>>2) & 0x7];
1162     uint8 b = colors2_r[(icon0[x+y*width]>>0) & 0x3];
1163     uint src = icon0[x+y*width];
1164     r = (src>>5) & 0x7;
1165     g = (src>>2) & 0x7;
1166     b = (src>>0) & 0x3;
1167     r = colors3_r[r];
1168     g = colors3_r[g];
1169     b = colors2_r[b];
1170     RGBA rgba = MK_RGBA(r, g, b, icon2[x+y*width]);
1171     gDisplay->putPixelRGBA(20+2*x+0, 20+2*y+0, rgba);
1172     gDisplay->putPixelRGBA(20+2*x+0, 20+2*y+1, rgba);
1173     gDisplay->putPixelRGBA(20+2*x+1, 20+2*y+0, rgba);
1174     gDisplay->putPixelRGBA(20+2*x+1, 20+2*y+1, rgba);
1175     r = ~icon1[x+y*width];
1176     g = ~icon1[x+y*width];
1177     b = ~icon1[x+y*width];
1178     rgba = MK_RGBA(r, g, b, icon2[x+y*width]);
1179     gDisplay->putPixelRGBA(60+x, 20+y, rgba);
1180     }
1181     }
1182     // while (1) ;
1183     }
1184     #endif
1185     }
1186     return false;
1187     } catch (Exception *x) {
1188     String s;
1189     IO_PROM_TRACE("mapped_load_chrp: exception: %y\n", &x->reason(s));
1190     return false;
1191     } catch (...) {
1192     return false;
1193     }
1194     }
1195    
1196     /*
1197     * brute force loading
1198     */
1199     bool mapped_load_flat(const char *filename, uint fileofs, uint filesize, uint vaddr, uint pc)
1200     {
1201     gDisplay->printf("FLAT loading: %s\n", filename);
1202    
1203     uint32 pa;
1204     uint32 ea;
1205     // allocate image
1206     pa = vaddr;
1207     ea = vaddr;
1208    
1209     uint32 loadaddr = pa;
1210    
1211     for (uint p = 0; p<(filesize+4095) / 4096; p++) {
1212     if (!init_page_create(ea, pa)) return false;
1213     ea += 4096;
1214     pa += 4096;
1215     }
1216    
1217     // allocate stack
1218     int stackea = 44*1024*1024;
1219     int stacksize = 40*4096;
1220     ea = stackea;
1221     pa = stackea;
1222     for (int i=0; i<(stacksize+4095) / 4096; i++) {
1223     if (!init_page_create(ea, pa)) return false;
1224     ea += 4096;
1225     pa += 4096;
1226     }
1227    
1228     // allocate bss
1229     int bssea = 0x1c25000;
1230     int bsssize = 0x9c000;
1231     pa = bssea;
1232     ea = bssea;
1233     for (int i=0; i<(bsssize+4095) / 4096; i++) {
1234     if (!init_page_create(ea, pa)) return false;
1235     ea += 4096;
1236     pa += 4096;
1237     }
1238    
1239     FILE *f;
1240     if (!(f = fopen(filename, "rb"))) {
1241     return false;
1242     }
1243    
1244     fseek(f, fileofs, SEEK_SET);
1245    
1246     byte *p = (byte *)malloc(filesize);
1247     if (!p) return false;
1248    
1249     if (fread(p, filesize, 1, f) != 1) {
1250     free(p);
1251     return false;
1252     }
1253    
1254     ppc_dma_write(loadaddr, p, filesize);
1255    
1256     free(p);
1257    
1258     ppc_cpu_set_msr(0, MSR_IR | MSR_DR | MSR_FP);
1259     ppc_cpu_set_pc(0, pc);
1260    
1261     ppc_cpu_set_gpr(0, 1, stackea+stacksize/2);
1262     ppc_cpu_set_gpr(0, 2, 0);
1263     ppc_cpu_set_gpr(0, 3, 0x47110815);
1264     ppc_cpu_set_gpr(0, 4, 0);
1265     ppc_cpu_set_gpr(0, 5, gPromOSIEntry);
1266     return true;
1267     }
1268    
1269     bool mapped_load_direct(File &f, uint vaddr, uint pc)
1270     {
1271     String fn;
1272     gDisplay->printf("direct: trying to load '%y'\n", &f.getDesc(fn));
1273     IO_PROM_TRACE("direct: trying to load '%y'\n", &fn);
1274    
1275     uint32 pa;
1276     uint32 ea;
1277     // allocate image
1278     pa = vaddr;
1279     ea = vaddr;
1280    
1281     uint32 loadaddr = pa;
1282    
1283     uint size = f.getSize();
1284     for (uint p = 0; p<(size+4095) / 4096; p++) {
1285     if (!init_page_create(ea, pa)) return false;
1286     ea += 4096;
1287     pa += 4096;
1288     }
1289    
1290     // allocate stack
1291     int stackea = (vaddr+size + 4096) & 0xfffff000;
1292     int stacksize = 40*4096;
1293     ea = stackea;
1294     pa = stackea;
1295     for (int i=0; i<(stacksize+4095) / 4096; i++) {
1296     if (!init_page_create(ea, pa)) return false;
1297     ea += 4096;
1298     pa += 4096;
1299     }
1300    
1301     // allocate bss
1302     /* int bssea = 0x1c25000;
1303     int bsssize = 0x9c000;
1304     pa = bssea;
1305     ea = bssea;
1306     for (int i=0; i<(bsssize+4095) / 4096; i++) {
1307     if (!init_page_create(ea, pa)) return false;
1308     ea += 4096;
1309     pa += 4096;
1310     }*/
1311    
1312     // memcpy(pt, mem, size);
1313     f.seek(0);
1314    
1315     byte *p = (byte *)malloc(f.getSize());
1316     if (!p) return false;
1317    
1318     if (f.read(p, f.getSize()) != f.getSize()) {
1319     free(p);
1320     return false;
1321     }
1322    
1323     ppc_dma_write(loadaddr, p, f.getSize());
1324    
1325     free(p);
1326    
1327     ppc_cpu_set_msr(0, MSR_IR | MSR_DR | MSR_FP);
1328     ppc_cpu_set_pc(0, pc);
1329    
1330     ppc_cpu_set_gpr(0, 1, stackea+stacksize/2);
1331     ppc_cpu_set_gpr(0, 2, 0);
1332     ppc_cpu_set_gpr(0, 3, 0x47110815);
1333     ppc_cpu_set_gpr(0, 4, 0);
1334     ppc_cpu_set_gpr(0, 5, gPromOSIEntry);
1335     return true;
1336     }
1337    
1338     /*
1339     * Mach-O
1340     */
1341     #if 0
1342     bool mapped_load_mach_o(const char *filename)
1343     {
1344     gDisplay->printf("MACH-O loading: %s\n", filename);
1345     byte *pt;
1346     if (ppc_direct_physical_memory_handle(0x0, pt)) {
1347     return false;
1348     }
1349    
1350     FILE *f;
1351     f = fopen(filename, "rb");
1352     MachOHeader hdr;
1353     if (fread(&hdr, sizeof hdr, 1, f) != 1) return false;
1354     createHostStructx(&hdr, sizeof hdr, MACHO_HEADER_struct, big_endian);
1355     for (uint i=0; i < hdr.ncmds; i++) {
1356     // ht_printf("cmd %d/%d\n", i+1, hdr.ncmds);
1357     long fpos = ftell(f);
1358     MachOCommand cmd;
1359     if (fread(&cmd, sizeof cmd, 1, f) != 1) return false;
1360     createHostStructx(&cmd, sizeof cmd, MACHO_COMMAND_struct, big_endian);
1361     if (cmd.cmd == 1) {
1362     MachOSegmentCommand seg;
1363     if (fread(&seg, sizeof seg, 1, f) != 1) return false;
1364     createHostStructx(&seg, sizeof seg, MACHO_SEGMENT_COMMAND_struct, big_endian);
1365     // ht_printf("mapping %08x->%08x (%d bytes)\n", seg.fileoff, seg.vmaddr, seg.filesize);
1366     fseek(f, seg.fileoff, SEEK_SET);
1367     memset(pt+seg.vmaddr, 0, seg.vmsize);
1368     if (fread(pt+seg.vmaddr, seg.filesize, 1, f) != 1) return false;
1369     } else if (cmd.cmd == 5) {
1370     MachOPPCThreadState ts;
1371     if (fread(&ts, sizeof ts, 1, f) != 1) return false;
1372     createHostStructx(&ts, sizeof ts, MACHO_THREAD_COMMAND_struct, big_endian);
1373    
1374     gCPU.pc = ts.srr0;
1375     gCPU.srr[0] = ts.srr0;
1376     gCPU.srr[1] = ts.srr1;
1377    
1378     gCPU.gpr[1] = 8*1024*1024;
1379     gCPU.gpr[3] = 0x47110815;
1380     gCPU.gpr[4] = 0x4d4f5358; // MOSX
1381     gCPU.gpr[5] = gPromOSIEntry; // prom entry
1382     // gSinglestep = true;
1383     }
1384     fseek(f, fpos, SEEK_SET);
1385     fseek(f, cmd.cmdsize, SEEK_CUR);
1386     }
1387     fclose(f);
1388     return true;
1389     }
1390     #endif
1391    
1392     /*
1393     *
1394     */
1395     class BootRec: public Object {
1396     public:
1397     PromNodeDisk *d;
1398     PartitionEntry *pe;
1399     int partnum;
1400     String *devname;
1401    
1402     BootRec(PromNodeDisk *aD, PartitionEntry *aPe, int aPartnum, const String &aDevname)
1403     {
1404     d = aD;
1405     pe = aPe;
1406     partnum = aPartnum;
1407     devname = new String(aDevname);
1408     }
1409     virtual ~BootRec()
1410     {
1411     delete devname;
1412     }
1413     };
1414    
1415     static void read_partitions(Container &brs, bool only_bootable)
1416     {
1417     brs.delAll();
1418     char *boot_devices[] = {"cdrom0", "cdrom1", "disk0", "disk1", NULL};
1419     char **boot_device = boot_devices;
1420     while (*boot_device) {
1421     PromNode *node = findDevice(*boot_device, FIND_DEVICE_FIND, NULL);
1422     PromNodeDisk *d = dynamic_cast<PromNodeDisk*>(node);
1423     if (d) {
1424     Enumerator *e = d->pm->getPartitions();
1425     int partnum=0;
1426     foreach(PartitionEntry, pe, *e,
1427     if (!only_bootable || (pe->mBootMethod != BM_none)) {
1428     brs.insert(new BootRec(d, pe, partnum, *boot_device));
1429     }
1430     partnum++;
1431     );
1432     }
1433     boot_device++;
1434     }
1435     }
1436    
1437     bool prom_user_boot_partition(File *&ret_file, uint32 &size, bool &direct, uint32 &loadAddr, uint32 &entryAddr)
1438     {
1439     gDisplay->setAnsiColor(VCP(VC_LIGHT(VC_YELLOW), VC_TRANSPARENT));
1440     gDisplay->printf("\n PROM boot-loader\n");
1441     gDisplay->printf(" ==================\n\n");
1442     Array brs(true);
1443     read_partitions(brs, true);
1444     char key2digit[256];
1445     for (int i=0; i<256; i++) key2digit[i] = -1;
1446     key2digit[KEY_0] = 0;
1447     key2digit[KEY_1] = 1;
1448     key2digit[KEY_2] = 2;
1449     key2digit[KEY_3] = 3;
1450     key2digit[KEY_4] = 4;
1451     key2digit[KEY_5] = 5;
1452     key2digit[KEY_6] = 6;
1453     key2digit[KEY_7] = 7;
1454     key2digit[KEY_8] = 8;
1455     key2digit[KEY_9] = 9;
1456    
1457     bool only_bootable = true;
1458    
1459     while (1) {
1460     if (gPromBootMethod == prombmSelect) gDisplay->printf("Which partition do you want to boot?\n");
1461     if (only_bootable) {
1462     gDisplay->printf("\n%d bootable partition(s) found:\n", brs.count());
1463     if (gPromBootMethod == prombmSelect) {
1464     gDisplay->printf(" 0. Show all (even unbootable)\n");
1465     }
1466     } else {
1467     gDisplay->printf("\n%d partition(s) found:\n", brs.count());
1468     gDisplay->printf(" 0. Show only bootable\n");
1469     }
1470     for (uint i=0; i < brs.count(); i++) {
1471     BootRec *bootrec = dynamic_cast<BootRec *>(brs[i]);
1472     gDisplay->printf(" %2d. partition %d of '%y' (%s/%s)\n", i+1, bootrec->partnum, bootrec->devname, bootrec->pe->mName, bootrec->pe->mType);
1473     }
1474     uint choice = 0;
1475     if (gPromBootMethod == prombmSelect) {
1476     gDisplay->printf("\nYour choice (ESC abort):");
1477     while (1) {
1478     gDisplay->printf("\r\e[0K\rYour choice (ESC abort): %d", choice);
1479     uint32 keycode;
1480     do {
1481     while (!cuda_prom_get_key(keycode)) sys_suspend();
1482     } while (keycode & 0x80);
1483    
1484     if (keycode == KEY_DELETE) choice = 0; else
1485     if (keycode == KEY_RETURN) break; else
1486     if (keycode == KEY_ESCAPE) return false;
1487    
1488     if ((keycode<256) && (key2digit[keycode]>=0)) {
1489     choice *= 10;
1490     choice += key2digit[keycode];
1491     }
1492     }
1493     } else {
1494     choice = 1;
1495     }
1496     if (choice == 0) {
1497     gDisplay->printf("\n\n");
1498     only_bootable = !only_bootable;
1499     read_partitions(brs, only_bootable);
1500     continue;
1501     }
1502     gPromBootMethod = prombmSelect;
1503     if ((choice > 0) && (choice <= brs.count())) {
1504     choice--;
1505     BootRec *bootrec = dynamic_cast<BootRec *>(brs[choice]);
1506     if (bootrec->pe->mBootMethod == BM_none) {
1507     gDisplay->printf("\nThis partition is not bootable!\n");
1508     continue;
1509     }
1510     gDisplay->printf("\nBooting %d: '%y:%d'...\n", choice+1, bootrec->devname, bootrec->partnum);
1511     // FIXME: ic hack
1512     IDEConfig *ic = ide_get_config(bootrec->d->mNumber);
1513     File *rawFile = ic->device->promGetRawFile();
1514     File *bootFile = bootrec->pe->mInstantiateBootFile(rawFile,
1515     bootrec->pe->mInstantiateBootFilePrivData);
1516     if (!bootFile) {
1517     IO_PROM_ERR("can't open boot file\n");
1518     return false;
1519     }
1520     uint bootFileSize = bootFile->getSize();
1521     if (bootFileSize > 64*1024*1024) {
1522     gDisplay->printf("Boot file too large. size=%d (>64MB)\n", bootFileSize);
1523     continue;
1524     }
1525     // set bootpath
1526     char bootpath[1024];
1527     char devicebootpath[1024];
1528     bootrec->d->toPath(devicebootpath, sizeof devicebootpath);
1529     ht_snprintf(bootpath, sizeof bootpath, "%s:%d,BootX", devicebootpath, bootrec->partnum);
1530     // ht_snprintf(bootpath, sizeof bootpath, "/pci/pci-bridge/pci-ata/ata-4/disk1@1:9,BootX");
1531     PromNode *chosen = findDevice("/chosen", FIND_DEVICE_FIND, NULL);
1532     if (chosen) {
1533     chosen->addProp(new PromPropString("bootpath", bootpath));
1534     }
1535    
1536     ret_file = bootFile;
1537     // FIXME: HACK!!!
1538     gBootPartNum = bootrec->partnum;
1539     gBootNodeID = bootrec->d->getPHandle();
1540    
1541     gDisplay->setAnsiColor(VCP(VC_LIGHT(VC_BLUE), VC_TRANSPARENT));
1542     size = bootFileSize;
1543     switch (bootrec->pe->mBootMethod) {
1544     case BM_chrp: {
1545     direct = false;
1546     return true;
1547     }
1548     case BM_direct: {
1549     direct = true;
1550     loadAddr = bootrec->pe->mBootImageLoadAddr;
1551     entryAddr = bootrec->pe->mBootImageEntrypoint;
1552     return true;
1553     }
1554     default:
1555     ASSERT(0);
1556     }
1557     return false;
1558     } else {
1559     gDisplay->printf("\nInvalid choice, try again.\n");
1560     }
1561     }
1562     return false;
1563     }
1564    
1565     bool prom_load_boot_file()
1566     {
1567     if (gPromBootMethod == prombmForce) {
1568     if (gConfig->haveKey("prom_loadfile")) {
1569     String loadfile;
1570     gConfig->getConfigString("prom_loadfile", loadfile);
1571     PromNode *pn = findDevice(gPromBootPath.contentChar(), FIND_DEVICE_FIND, NULL);
1572     if (pn) {
1573     gBootNodeID = pn->getPHandle();
1574     String dev, rest;
1575     gPromBootPath.leftSplit(':', dev, rest);
1576     String partNum, rest2;
1577     rest.leftSplit(',', partNum, rest2);
1578     uint32 p;
1579     if (partNum.toInt32(p)) gBootPartNum = p;
1580     }
1581    
1582     LocalFile f(loadfile);
1583     // if (!mapped_load_elf_from_chrp(f, 0)
1584     if (!mapped_load_elf(f)
1585     && !mapped_load_xcoff(f, 0)
1586     && !mapped_load_chrp(f)) {
1587     IO_PROM_WARN("couldn't load '%y'.\n", &loadfile);
1588     return false;
1589     }
1590     } else {
1591     IO_PROM_ERR("bootmethod is 'force', but no prom_loadfile defined\n");
1592     return false;
1593     }
1594     } else {
1595     uint32 loadAddr;
1596     uint32 entryAddr;
1597     File *f;
1598     uint32 msize;
1599     bool direct;
1600     if (!prom_user_boot_partition(f, msize, direct, loadAddr, entryAddr)) {
1601     IO_PROM_WARN("Can't boot a partition.\nTry bootmethod 'force' and specify a 'prom_loadfile' in your config-file...\n");
1602     return false;
1603     }
1604     try {
1605     LocalFile lf("bootfile.dump", IOAM_WRITE, FOM_CREATE);
1606     f->seek(0);
1607     f->copyAllTo(&lf);
1608     } catch (...) {
1609     printf("error dumping bootfile");
1610     }
1611     if (direct) {
1612     if (!mapped_load_direct(*f, loadAddr, entryAddr)) {
1613     IO_PROM_TRACE("couldn't load.\n");
1614     return false;
1615     }
1616     } else {
1617     if (!mapped_load_chrp(*f)) {
1618     IO_PROM_TRACE("couldn't load.\n");
1619     return false;
1620     }
1621     }
1622     delete f;
1623     }
1624     return true;
1625     }

  ViewVC Help
Powered by ViewVC 1.1.26