/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 10 - (show 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 /*
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 PROMBOOT_OUTPUT("ELF: trying to load '%y' (CHRP)\n", &f.getDesc(fn));
495 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 uint32 entry;
707 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 IO_PROM_TRACE("program header %d:\n", i);
716 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 ea = 0x00000000; // XXX force load to beginning of RAM
723 entry = ea;
724 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 IO_PROM_TRACE("loading from %08x to ea:%08x (pa:%08x)\n", fo, ea, la);
730 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 ht_printf("loading remaining from %08x to ea:%08x (pa:%08x)\n", fo, ea, la);
743 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 ht_printf("creating for ea:%08x (pa:%08x)\n", ea, la);
755 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 gDisplay->printf("starting from PC %08x\n", entry);
774
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