/[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 1 - (show annotations)
Wed Sep 5 17:11:21 2007 UTC (16 years, 7 months ago) by dpavlin
File size: 43589 byte(s)
import upstream CVS
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'\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 la = ELF_LOAD_ADDRESS;
707 f.seek(0x2c);
708 uint16 program_hdrs;
709 f.readx(&program_hdrs, 2);
710 program_hdrs = createHostInt(&program_hdrs, 2, big_endian);
711 uint32 stack=0;
712 uint32 stackp=0;
713 for (int i=0; i<program_hdrs; i++) {
714 // IO_PROM_TRACE("program header %d:\n", i);
715 ELF_PROGRAM_HEADER32 program_hdr;
716 f.seek(0x34+i*sizeof program_hdr);
717 f.readx(&program_hdr, sizeof program_hdr);
718 createHostStructx(&program_hdr, sizeof program_hdr, ELF_PROGRAM_HEADER32_struct, big_endian);
719 uint32 pages_from_file = program_hdr.p_filesz / 4096;
720 uint32 ea = program_hdr.p_vaddr;
721 sint32 vs = program_hdr.p_memsz;
722 f.seek(program_hdr.p_offset);
723 uint32 fo = program_hdr.p_offset;
724 byte page[4096];
725 while (pages_from_file) {
726 // IO_PROM_TRACE("loading from %08x to ea:%08x (pa:%08x)\n", fo, ea, la);
727 f.readx(page, sizeof page);
728 if (!init_page_create(ea, la)) return false;
729 if (!ppc_dma_write(la, page, 4096)) {
730 return false;
731 }
732 pages_from_file--;
733 la += 4096;
734 ea += 4096;
735 fo += 4096;
736 vs -= 4096;
737 }
738 if (program_hdr.p_filesz % 4096) {
739 // ht_printf("loading remaining from %08x to ea:%08x (pa:%08x)\n", fo, ea, la);
740 f.read(page, program_hdr.p_filesz % 4096);
741 if (!init_page_create(ea, la)) return false;
742 if (!ppc_dma_write(la+(ea&0xfff), page, program_hdr.p_filesz % 4096)) {
743 return false;
744 }
745 la += 4096;
746 ea += 4096;
747 fo += 4096;
748 vs -= 4096;
749 }
750 while (vs > 0) {
751 // ht_printf("creating for ea:%08x (pa:%08x)\n", ea, la);
752 if (!init_page_create(ea, la)) return false;
753 la += 4096;
754 ea += 4096;
755 vs -= 4096;
756 }
757 stack = ea;
758 stackp = la;
759 }
760
761 stack = gMemorySize - 65536 - (4096*20) - PROM_MEM_SIZE;
762 stackp = gMemorySize - 65536 - (4096*20) - PROM_MEM_SIZE;
763 // allocate stack
764 for (int i=0; i<20; i++) {
765 if (!init_page_create(stack, stackp)) return false;
766 stack += 4096;
767 stackp += 4096;
768 }
769
770
771 f.seek(0x18);
772 uint32 entry;
773 f.readx(&entry, 4);
774 entry = createHostInt(&entry, 4, big_endian);
775
776 // turn on address translation
777 ppc_cpu_set_msr(0, MSR_IR | MSR_DR | MSR_FP);
778 ppc_cpu_set_pc(0, entry);
779
780 ppc_cpu_set_gpr(0, 1, gMemorySize - 65536 - 32 - PROM_MEM_SIZE);
781 ppc_cpu_set_gpr(0, 2, 0);
782 ppc_cpu_set_gpr(0, 3, 0);
783 ppc_cpu_set_gpr(0, 4, 0);
784 ppc_cpu_set_gpr(0, 5, gPromOSIEntry);
785
786 // wtf?!
787 ppc_prom_page_create(0, 0);
788 return true;
789 } catch (...) {
790 return false;
791 }
792 }
793
794 /*
795 * XCOFF
796 */
797 bool mapped_load_xcoff(File &f, uint disp_ofs)
798 {
799 String fn;
800 gDisplay->printf("XCOFF trying to load '%y'\n", &f.getDesc(fn));
801 IO_PROM_TRACE("XCOFF trying to load '%y'\n", &fn);
802
803 f.seek(disp_ofs);
804 try {
805 COFF_HEADER hdr;
806 f.readx(&hdr, sizeof hdr);
807 createHostStructx(&hdr, sizeof hdr, COFF_HEADER_struct, big_endian);
808 if (hdr.machine != 0x1df) {
809 IO_PROM_TRACE("invalid machine %04x (expecting 01df)\n", hdr.machine);
810 return false;
811 }
812 if (hdr.optional_header_size != 0x48) {
813 IO_PROM_TRACE("invalid optional header size %04x (expecting 0048)\n", hdr.optional_header_size);
814 return false;
815 }
816 uint32 stack=0;
817 uint32 stackp=0;
818 uint32 entrypoint;
819 uint32 entrypoint_ofs = 0;
820 f.seek(disp_ofs+0x24);
821 f.readx(&entrypoint, 4);
822 entrypoint = createHostInt(&entrypoint, 4, big_endian);
823
824 for (int i=0; i<hdr.section_count; i++) {
825 // ht_printf("program header %d:\n", i);
826 COFF_SECTION_HEADER shdr;
827 f.seek(disp_ofs+0x5c+i*sizeof shdr);
828 f.readx(&shdr, sizeof shdr);
829 createHostStructx(&shdr, sizeof shdr, COFF_SECTION_HEADER_struct, big_endian);
830 if ((entrypoint >= shdr.data_address) && (entrypoint < shdr.data_address+shdr.data_size)) {
831 IO_PROM_TRACE("found entrypoint-structure in section %d\n", i);
832 entrypoint_ofs = entrypoint - shdr.data_address + shdr.data_offset;
833 }
834 uint32 in_file_size = (shdr.data_offset) ? shdr.data_size : 0;
835 uint32 pages_from_file = in_file_size / 4096;
836 uint32 pa = shdr.data_vsize; /* really: physical addr */
837 uint32 ea = shdr.data_address;
838 sint32 vs = shdr.data_size;
839 f.seek(disp_ofs+shdr.data_offset);
840 uint32 fo = shdr.data_offset;
841 byte page[4096];
842 while (pages_from_file) {
843 // ht_printf("loading from %08x to ea:%08x (pa:%08x)\n", fo, ea, pa);
844 f.readx(page, sizeof page);
845 if (!init_page_create(ea, pa)) return false;
846 if (!ppc_dma_write(pa, page, 4096)) {
847 return false;
848 }
849 pages_from_file--;
850 pa += 4096;
851 ea += 4096;
852 fo += 4096;
853 vs -= 4096;
854 }
855 if (in_file_size % 4096) {
856 // ht_printf("loading remaining from %08x to ea:%08x (pa:%08x)\n", fo, ea, pa);
857 f.readx(page, in_file_size % 4096);
858 if (!init_page_create(ea, pa)) return false;
859 if (!ppc_dma_write(pa+(ea&0xfff), page, in_file_size % 4096)) {
860 return false;
861 }
862 pa += 4096;
863 ea += 4096;
864 fo += 4096;
865 vs -= 4096;
866 }
867 while (vs > 0) {
868 // ht_printf("creating for ea:%08x (pa:%08x)\n", ea, pa);
869 if (!init_page_create(ea, pa)) return false;
870 pa += 4096;
871 ea += 4096;
872 vs -= 4096;
873 }
874 stack = ea;
875 stackp = pa;
876 }
877 if (!entrypoint_ofs) {
878 IO_PROM_TRACE("couldn't find entrypoint offset\n");
879 return false;
880 }
881 // allocate stack
882 for (int i=0; i<20; i++) {
883 if (!init_page_create(stack, stackp)) return false;
884 stack += 4096;
885 stackp += 4096;
886 }
887
888 uint32 real_entrypoint = 0;
889 f.seek(disp_ofs+entrypoint_ofs);
890 f.read(&real_entrypoint, 4);
891 real_entrypoint = createHostInt(&real_entrypoint, 4, big_endian);
892 IO_PROM_TRACE("real_entrypoint = %08x\n", real_entrypoint);
893 // turn on address translation
894 ppc_cpu_set_msr(0, MSR_IR | MSR_DR | MSR_FP);
895 ppc_cpu_set_pc(0, real_entrypoint);
896
897 ppc_cpu_set_gpr(0, 1, stack-(4096+32));
898 ppc_cpu_set_gpr(0, 2, 0);
899 ppc_cpu_set_gpr(0, 3, 0);
900 ppc_cpu_set_gpr(0, 4, 0);
901 ppc_cpu_set_gpr(0, 5, gPromOSIEntry);
902
903 return true;
904 } catch (...) {
905 return false;
906 }
907 }
908
909 static void chrpReadWaitForChar(File &f, char *buf, uint buflen, char waitFor)
910 {
911 while (buflen) {
912 f.readx(buf, 1);
913
914 if (*buf == 0x0d) *buf = '\n';
915
916 if (!*buf) throw new MsgException("Binary files not allowed here");
917 if (*buf == waitFor) {
918 *buf = 0;
919 return;
920 }
921 buf++;
922 buflen--;
923 }
924 throw new MsgException("wait for char failed");
925 }
926
927 static void chrpReadWaitForString(File &f, char *buf, uint buflen, char *waitFor)
928 {
929 uint zlen = strlen(waitFor);
930 char *z = strdup(waitFor);
931 *z = 0;
932 *buf = 0;
933 if (!zlen) return;
934 FileOfs o = f.tell();
935 while (buflen) {
936 f.seek(o);
937 f.readx(z, zlen);
938 if (strcmp(z, waitFor) == 0) {
939 *buf = 0;
940 free(z);
941 return;
942 }
943 if (buf != NULL) {
944 *buf = (*z == 0xd) ? '\n' : *z;
945 buf++;
946 buflen--;
947 }
948 o++;
949 }
950 free(z);
951 throw new MsgException("wait for string failed");
952 }
953
954 #if 0
955 static void readCHRPIcon(byte *icon, char *&t, uint width, uint height)
956 {
957 memset(icon, 0, width*height);
958 uint y = 0;
959 uint x = 0;
960 while (t[0] && t[1]) {
961 if (t[0] == '\n') {
962 while (*t == '\n') t++;
963 // fprintf(stderr, "parse icon: line %d length %d\n", y, x);
964 x = 0;
965 y++;
966 if (y >= height) break;
967 continue;
968 }
969 if (x>=width) break;
970 hexb_ex(icon[x+y*width], t);
971 t += 2;
972 x++;
973 }
974 }
975 #endif
976
977 static bool chrpBoot(const char *bootpath, const char *bootargs)
978 {
979 IO_PROM_TRACE("CHRP boot file (bootpath = %s, bootargs = %s).\n", bootpath, bootargs);
980 // set bootpath in device tree
981 PromNode *chosen = findDevice("/chosen", FIND_DEVICE_FIND, NULL);
982 if (chosen) {
983 PromProp *bp = chosen->findProp("bootpath");
984 if (bp) {
985 PromPropString *s = dynamic_cast<PromPropString*>(bp);
986 if (s) {
987 free(s->value);
988 s->value = strdup(bootpath);
989 }
990 } else {
991 chosen->addProp(new PromPropString("bootpath", bootpath));
992 }
993 PromProp *ba = chosen->findProp("bootargs");
994 if (ba) {
995 PromPropString *s = dynamic_cast<PromPropString*>(ba);
996 if (s) {
997 free(s->value);
998 s->value = strdup(bootargs);
999 }
1000 } else {
1001 chosen->addProp(new PromPropString("bootargs", bootargs));
1002 }
1003 }
1004
1005 PromInstanceHandle ih;
1006 if (!findDevice(bootpath, FIND_DEVICE_OPEN, &ih)) return false;
1007
1008 PromInstanceDiskFile *ix = dynamic_cast<PromInstanceDiskFile*>(handleToInstance(ih));
1009 if (!ix || !ix->mFile) {
1010 IO_PROM_TRACE("couldn't load CHRP boot file (1) (bootpath = %s).\n", bootpath);
1011 return false;
1012 }
1013
1014 PromNode *pn = ix->getType();
1015 File *f = ix->mFile;
1016
1017 if (!mapped_load_elf(*f)
1018 && !mapped_load_xcoff(*f, 0)
1019 && !mapped_load_chrp(*f)) {
1020 IO_PROM_TRACE("couldn't load CHRP boot file (2) (bootpath = %s).\n", bootpath);
1021 pn->close(ih);
1022 return false;
1023 }
1024 pn->close(ih);
1025 return true;
1026 }
1027
1028 bool mapped_load_chrp(File &f)
1029 {
1030 String fn;
1031 gDisplay->printf("CHRP: trying to load '%y'\n", &f.getDesc(fn));
1032 IO_PROM_TRACE("CHRP: trying to load '%y'\n", &fn);
1033 try {
1034 char hdr[13];
1035 f.seek(0);
1036 if (f.read(hdr, 12) != 12) return false;
1037 hdr[12] = 0;
1038 IO_PROM_TRACE("header: %s\n", hdr);
1039 if (strncmp(hdr, "<CHRP-BOOT>", 11)) return false;
1040 IO_PROM_TRACE("CHRP-BOOT OK\n");
1041 char buf[32*1024];
1042 uint buflen;
1043 char tag[32*1024];
1044 char expect[4*1024+1]; // sizeof buf+1
1045 while (1) {
1046 chrpReadWaitForChar(f, buf, sizeof buf, '\n');
1047 buflen = strlen(buf);
1048 IO_PROM_TRACE("read %d bytes: %s\n", buflen, buf);
1049 if (buflen < 1)
1050 continue;
1051 if ((buf[0] != '<') || (buflen<3) || (buf[buflen-1] != '>')) return false;
1052 if (buf[1] == '/') {
1053 if (memcmp(buf, "</CHRP-BOOT>", buflen-1) != 0)
1054 return false;
1055 byte b;
1056 FileOfs from = f.tell();
1057 while (1) {
1058 if (!f.read(&b, 1)) return false;
1059 if (b == 0x01) break;
1060 }
1061 if (b != 0x01) return false;
1062 if (!f.read(&b, 1)) return false;
1063 if (b == 0xdf) {
1064 PROMBOOT_OUTPUT("Loading XCOFF...\n");
1065 return mapped_load_xcoff(f, f.tell()-2);
1066 } else if (b == 0x02) {
1067 f.seek(from);
1068 while (1) {
1069 if (!f.read(&b, 1))
1070 return false;
1071 if (b == 0x7f) break;
1072 }
1073
1074 PROMBOOT_OUTPUT("Loading ELF...\n");
1075 return mapped_load_elf_from_chrp(f, f.tell()-1);
1076 } else
1077 return false;
1078 }
1079 expect[0] = '<';
1080 expect[1] = '/';
1081 int index;
1082 for (index=0; index<buflen-1; index++) {
1083 if (buf[index+1] == ' ') break;
1084 if (buf[index+1] == '>') break;
1085 expect[index+2] = buf[index+1];
1086 }
1087 //memcpy(expect+2, buf+1, buflen-1);
1088 //expect[buflen+1] = '\n';
1089 expect[index+2] = '>';
1090 expect[index+3] = 0;
1091 strcpy(tag, buf);
1092 IO_PROM_TRACE("waitforstring: %s\n", expect);
1093 chrpReadWaitForString(f, buf, sizeof buf, expect);
1094 IO_PROM_TRACE("found: %s\n", buf);
1095 if (strcmp(tag, "<BOOT-SCRIPT>") == 0) {
1096 char *bootpath = strstr(buf, "boot ");
1097 if (bootpath) {
1098 bootpath += 5;
1099 char *bootpathend = strchr(bootpath, '\n');
1100 if (!bootpathend) bootpathend = bootpath + strlen(bootpath);
1101 char mybootpath[1024];
1102 char *mybootargs = NULL;
1103 strncpy(mybootpath, bootpath, sizeof mybootpath-1);
1104 mybootpath[bootpathend-bootpath] = 0;
1105 mybootpath[sizeof mybootpath-1] = 0;
1106 mybootargs = mybootpath+ sizeof mybootpath-1;
1107 int l = strlen(mybootpath);
1108 for (int i=0; i<l; i++) {
1109 if (mybootpath[i] == '\n') {
1110 mybootpath[i] = 0;
1111 break;
1112 } else if (mybootpath[i] == ' ') {
1113 mybootpath[i] = 0;
1114 mybootargs = mybootpath+i+1;
1115 break;
1116 }
1117 }
1118 return chrpBoot(mybootpath, mybootargs);
1119 }
1120 }
1121 #if 0
1122 if (strcmp(tag, "<OS-BADGE-ICONS>") == 0) {
1123 char *t = buf;
1124 uint width = 1000, height = 1000;
1125 char fmt[64];
1126 while (*t && *t != '\n') t++;
1127 if (*t == '\n') t++;
1128 if (t-buf < (int)sizeof buf) {
1129 strncpy(fmt, buf, t-buf);
1130 fmt[t-buf] = 0;
1131 } else {
1132 fmt[0] = 0;
1133 }
1134 // fprintf(stderr, "format string: %s\n", fmt);
1135 if (strlen(fmt) == 4) {
1136 uint8 x;
1137 if (hexb_ex(x, fmt)) width = x;
1138 if (hexb_ex(x, fmt+2)) height = x;
1139 } else if (strlen(fmt) == 8) {
1140 uint16 x;
1141 if (hexw_ex(x, fmt)) width = x;
1142 if (hexw_ex(x, fmt+4)) height = x;
1143 }
1144 if ((width > 128) || (height > 128)) {
1145 // safety
1146 width = 16;
1147 height = 16;
1148 }
1149 byte icon0[width*height];
1150 byte icon1[width*height];
1151 byte icon2[width*height];
1152 readCHRPIcon(icon0, t, width, height);
1153 readCHRPIcon(icon1, t, width, height);
1154 readCHRPIcon(icon2, t, width, height);
1155 uint8 colors2_r[] = {0xff, 0xaa, 0x55, 0x00};
1156 uint8 colors3_r[] = {0xff, 0xdb, 0xb7, 0x92, 0x6e, 0x49, 0x25, 0x00};
1157 uint8 colors2[] = {0x00, 0x55, 0xaa, 0xff};
1158 uint8 colors3[] = {0x00, 0x25, 0x49, 0x6e, 0x92, 0xb7, 0xdb, 0xff};
1159 for (uint y=0; y < height; y++) {
1160 for (uint x=0; x < height; x++) {
1161 uint8 r = colors3_r[(icon0[x+y*width]>>5) & 0x7];
1162 uint8 g = colors3_r[(icon0[x+y*width]>>2) & 0x7];
1163 uint8 b = colors2_r[(icon0[x+y*width]>>0) & 0x3];
1164 uint src = icon0[x+y*width];
1165 r = (src>>5) & 0x7;
1166 g = (src>>2) & 0x7;
1167 b = (src>>0) & 0x3;
1168 r = colors3_r[r];
1169 g = colors3_r[g];
1170 b = colors2_r[b];
1171 RGBA rgba = MK_RGBA(r, g, b, icon2[x+y*width]);
1172 gDisplay->putPixelRGBA(20+2*x+0, 20+2*y+0, rgba);
1173 gDisplay->putPixelRGBA(20+2*x+0, 20+2*y+1, rgba);
1174 gDisplay->putPixelRGBA(20+2*x+1, 20+2*y+0, rgba);
1175 gDisplay->putPixelRGBA(20+2*x+1, 20+2*y+1, rgba);
1176 r = ~icon1[x+y*width];
1177 g = ~icon1[x+y*width];
1178 b = ~icon1[x+y*width];
1179 rgba = MK_RGBA(r, g, b, icon2[x+y*width]);
1180 gDisplay->putPixelRGBA(60+x, 20+y, rgba);
1181 }
1182 }
1183 // while (1) ;
1184 }
1185 #endif
1186 }
1187 return false;
1188 } catch (Exception *x) {
1189 String s;
1190 IO_PROM_TRACE("mapped_load_chrp: exception: %y\n", &x->reason(s));
1191 return false;
1192 } catch (...) {
1193 return false;
1194 }
1195 }
1196
1197 /*
1198 * brute force loading
1199 */
1200 bool mapped_load_flat(const char *filename, uint fileofs, uint filesize, uint vaddr, uint pc)
1201 {
1202 gDisplay->printf("FLAT loading: %s\n", filename);
1203
1204 uint32 pa;
1205 uint32 ea;
1206 // allocate image
1207 pa = vaddr;
1208 ea = vaddr;
1209
1210 uint32 loadaddr = pa;
1211
1212 for (uint p = 0; p<(filesize+4095) / 4096; p++) {
1213 if (!init_page_create(ea, pa)) return false;
1214 ea += 4096;
1215 pa += 4096;
1216 }
1217
1218 // allocate stack
1219 int stackea = 44*1024*1024;
1220 int stacksize = 40*4096;
1221 ea = stackea;
1222 pa = stackea;
1223 for (int i=0; i<(stacksize+4095) / 4096; i++) {
1224 if (!init_page_create(ea, pa)) return false;
1225 ea += 4096;
1226 pa += 4096;
1227 }
1228
1229 // allocate bss
1230 int bssea = 0x1c25000;
1231 int bsssize = 0x9c000;
1232 pa = bssea;
1233 ea = bssea;
1234 for (int i=0; i<(bsssize+4095) / 4096; i++) {
1235 if (!init_page_create(ea, pa)) return false;
1236 ea += 4096;
1237 pa += 4096;
1238 }
1239
1240 FILE *f;
1241 if (!(f = fopen(filename, "rb"))) {
1242 return false;
1243 }
1244
1245 fseek(f, fileofs, SEEK_SET);
1246
1247 byte *p = (byte *)malloc(filesize);
1248 if (!p) return false;
1249
1250 if (fread(p, filesize, 1, f) != 1) {
1251 free(p);
1252 return false;
1253 }
1254
1255 ppc_dma_write(loadaddr, p, filesize);
1256
1257 free(p);
1258
1259 ppc_cpu_set_msr(0, MSR_IR | MSR_DR | MSR_FP);
1260 ppc_cpu_set_pc(0, pc);
1261
1262 ppc_cpu_set_gpr(0, 1, stackea+stacksize/2);
1263 ppc_cpu_set_gpr(0, 2, 0);
1264 ppc_cpu_set_gpr(0, 3, 0x47110815);
1265 ppc_cpu_set_gpr(0, 4, 0);
1266 ppc_cpu_set_gpr(0, 5, gPromOSIEntry);
1267 return true;
1268 }
1269
1270 bool mapped_load_direct(File &f, uint vaddr, uint pc)
1271 {
1272 String fn;
1273 gDisplay->printf("direct: trying to load '%y'\n", &f.getDesc(fn));
1274 IO_PROM_TRACE("direct: trying to load '%y'\n", &fn);
1275
1276 uint32 pa;
1277 uint32 ea;
1278 // allocate image
1279 pa = vaddr;
1280 ea = vaddr;
1281
1282 uint32 loadaddr = pa;
1283
1284 uint size = f.getSize();
1285 for (uint p = 0; p<(size+4095) / 4096; p++) {
1286 if (!init_page_create(ea, pa)) return false;
1287 ea += 4096;
1288 pa += 4096;
1289 }
1290
1291 // allocate stack
1292 int stackea = (vaddr+size + 4096) & 0xfffff000;
1293 int stacksize = 40*4096;
1294 ea = stackea;
1295 pa = stackea;
1296 for (int i=0; i<(stacksize+4095) / 4096; i++) {
1297 if (!init_page_create(ea, pa)) return false;
1298 ea += 4096;
1299 pa += 4096;
1300 }
1301
1302 // allocate bss
1303 /* int bssea = 0x1c25000;
1304 int bsssize = 0x9c000;
1305 pa = bssea;
1306 ea = bssea;
1307 for (int i=0; i<(bsssize+4095) / 4096; i++) {
1308 if (!init_page_create(ea, pa)) return false;
1309 ea += 4096;
1310 pa += 4096;
1311 }*/
1312
1313 // memcpy(pt, mem, size);
1314 f.seek(0);
1315
1316 byte *p = (byte *)malloc(f.getSize());
1317 if (!p) return false;
1318
1319 if (f.read(p, f.getSize()) != f.getSize()) {
1320 free(p);
1321 return false;
1322 }
1323
1324 ppc_dma_write(loadaddr, p, f.getSize());
1325
1326 free(p);
1327
1328 ppc_cpu_set_msr(0, MSR_IR | MSR_DR | MSR_FP);
1329 ppc_cpu_set_pc(0, pc);
1330
1331 ppc_cpu_set_gpr(0, 1, stackea+stacksize/2);
1332 ppc_cpu_set_gpr(0, 2, 0);
1333 ppc_cpu_set_gpr(0, 3, 0x47110815);
1334 ppc_cpu_set_gpr(0, 4, 0);
1335 ppc_cpu_set_gpr(0, 5, gPromOSIEntry);
1336 return true;
1337 }
1338
1339 /*
1340 * Mach-O
1341 */
1342 #if 0
1343 bool mapped_load_mach_o(const char *filename)
1344 {
1345 gDisplay->printf("MACH-O loading: %s\n", filename);
1346 byte *pt;
1347 if (ppc_direct_physical_memory_handle(0x0, pt)) {
1348 return false;
1349 }
1350
1351 FILE *f;
1352 f = fopen(filename, "rb");
1353 MachOHeader hdr;
1354 if (fread(&hdr, sizeof hdr, 1, f) != 1) return false;
1355 createHostStructx(&hdr, sizeof hdr, MACHO_HEADER_struct, big_endian);
1356 for (uint i=0; i < hdr.ncmds; i++) {
1357 // ht_printf("cmd %d/%d\n", i+1, hdr.ncmds);
1358 long fpos = ftell(f);
1359 MachOCommand cmd;
1360 if (fread(&cmd, sizeof cmd, 1, f) != 1) return false;
1361 createHostStructx(&cmd, sizeof cmd, MACHO_COMMAND_struct, big_endian);
1362 if (cmd.cmd == 1) {
1363 MachOSegmentCommand seg;
1364 if (fread(&seg, sizeof seg, 1, f) != 1) return false;
1365 createHostStructx(&seg, sizeof seg, MACHO_SEGMENT_COMMAND_struct, big_endian);
1366 // ht_printf("mapping %08x->%08x (%d bytes)\n", seg.fileoff, seg.vmaddr, seg.filesize);
1367 fseek(f, seg.fileoff, SEEK_SET);
1368 memset(pt+seg.vmaddr, 0, seg.vmsize);
1369 if (fread(pt+seg.vmaddr, seg.filesize, 1, f) != 1) return false;
1370 } else if (cmd.cmd == 5) {
1371 MachOPPCThreadState ts;
1372 if (fread(&ts, sizeof ts, 1, f) != 1) return false;
1373 createHostStructx(&ts, sizeof ts, MACHO_THREAD_COMMAND_struct, big_endian);
1374
1375 gCPU.pc = ts.srr0;
1376 gCPU.srr[0] = ts.srr0;
1377 gCPU.srr[1] = ts.srr1;
1378
1379 gCPU.gpr[1] = 8*1024*1024;
1380 gCPU.gpr[3] = 0x47110815;
1381 gCPU.gpr[4] = 0x4d4f5358; // MOSX
1382 gCPU.gpr[5] = gPromOSIEntry; // prom entry
1383 // gSinglestep = true;
1384 }
1385 fseek(f, fpos, SEEK_SET);
1386 fseek(f, cmd.cmdsize, SEEK_CUR);
1387 }
1388 fclose(f);
1389 return true;
1390 }
1391 #endif
1392
1393 /*
1394 *
1395 */
1396 class BootRec: public Object {
1397 public:
1398 PromNodeDisk *d;
1399 PartitionEntry *pe;
1400 int partnum;
1401 String *devname;
1402
1403 BootRec(PromNodeDisk *aD, PartitionEntry *aPe, int aPartnum, const String &aDevname)
1404 {
1405 d = aD;
1406 pe = aPe;
1407 partnum = aPartnum;
1408 devname = new String(aDevname);
1409 }
1410 virtual ~BootRec()
1411 {
1412 delete devname;
1413 }
1414 };
1415
1416 static void read_partitions(Container &brs, bool only_bootable)
1417 {
1418 brs.delAll();
1419 char *boot_devices[] = {"cdrom0", "cdrom1", "disk0", "disk1", NULL};
1420 char **boot_device = boot_devices;
1421 while (*boot_device) {
1422 PromNode *node = findDevice(*boot_device, FIND_DEVICE_FIND, NULL);
1423 PromNodeDisk *d = dynamic_cast<PromNodeDisk*>(node);
1424 if (d) {
1425 Enumerator *e = d->pm->getPartitions();
1426 int partnum=0;
1427 foreach(PartitionEntry, pe, *e,
1428 if (!only_bootable || (pe->mBootMethod != BM_none)) {
1429 brs.insert(new BootRec(d, pe, partnum, *boot_device));
1430 }
1431 partnum++;
1432 );
1433 }
1434 boot_device++;
1435 }
1436 }
1437
1438 bool prom_user_boot_partition(File *&ret_file, uint32 &size, bool &direct, uint32 &loadAddr, uint32 &entryAddr)
1439 {
1440 gDisplay->setAnsiColor(VCP(VC_LIGHT(VC_YELLOW), VC_TRANSPARENT));
1441 gDisplay->printf("\n PROM boot-loader\n");
1442 gDisplay->printf(" ==================\n\n");
1443 Array brs(true);
1444 read_partitions(brs, true);
1445 char key2digit[256];
1446 for (int i=0; i<256; i++) key2digit[i] = -1;
1447 key2digit[KEY_0] = 0;
1448 key2digit[KEY_1] = 1;
1449 key2digit[KEY_2] = 2;
1450 key2digit[KEY_3] = 3;
1451 key2digit[KEY_4] = 4;
1452 key2digit[KEY_5] = 5;
1453 key2digit[KEY_6] = 6;
1454 key2digit[KEY_7] = 7;
1455 key2digit[KEY_8] = 8;
1456 key2digit[KEY_9] = 9;
1457
1458 bool only_bootable = true;
1459
1460 while (1) {
1461 if (gPromBootMethod == prombmSelect) gDisplay->printf("Which partition do you want to boot?\n");
1462 if (only_bootable) {
1463 gDisplay->printf("\n%d bootable partition(s) found:\n", brs.count());
1464 if (gPromBootMethod == prombmSelect) {
1465 gDisplay->printf(" 0. Show all (even unbootable)\n");
1466 }
1467 } else {
1468 gDisplay->printf("\n%d partition(s) found:\n", brs.count());
1469 gDisplay->printf(" 0. Show only bootable\n");
1470 }
1471 for (uint i=0; i < brs.count(); i++) {
1472 BootRec *bootrec = dynamic_cast<BootRec *>(brs[i]);
1473 gDisplay->printf(" %2d. partition %d of '%y' (%s/%s)\n", i+1, bootrec->partnum, bootrec->devname, bootrec->pe->mName, bootrec->pe->mType);
1474 }
1475 uint choice = 0;
1476 if (gPromBootMethod == prombmSelect) {
1477 gDisplay->printf("\nYour choice (ESC abort):");
1478 while (1) {
1479 gDisplay->printf("\r\e[0K\rYour choice (ESC abort): %d", choice);
1480 uint32 keycode;
1481 do {
1482 while (!cuda_prom_get_key(keycode)) sys_suspend();
1483 } while (keycode & 0x80);
1484
1485 if (keycode == KEY_DELETE) choice = 0; else
1486 if (keycode == KEY_RETURN) break; else
1487 if (keycode == KEY_ESCAPE) return false;
1488
1489 if ((keycode<256) && (key2digit[keycode]>=0)) {
1490 choice *= 10;
1491 choice += key2digit[keycode];
1492 }
1493 }
1494 } else {
1495 choice = 1;
1496 }
1497 if (choice == 0) {
1498 gDisplay->printf("\n\n");
1499 only_bootable = !only_bootable;
1500 read_partitions(brs, only_bootable);
1501 continue;
1502 }
1503 gPromBootMethod = prombmSelect;
1504 if ((choice > 0) && (choice <= brs.count())) {
1505 choice--;
1506 BootRec *bootrec = dynamic_cast<BootRec *>(brs[choice]);
1507 if (bootrec->pe->mBootMethod == BM_none) {
1508 gDisplay->printf("\nThis partition is not bootable!\n");
1509 continue;
1510 }
1511 gDisplay->printf("\nBooting %d: '%y:%d'...\n", choice+1, bootrec->devname, bootrec->partnum);
1512 // FIXME: ic hack
1513 IDEConfig *ic = ide_get_config(bootrec->d->mNumber);
1514 File *rawFile = ic->device->promGetRawFile();
1515 File *bootFile = bootrec->pe->mInstantiateBootFile(rawFile,
1516 bootrec->pe->mInstantiateBootFilePrivData);
1517 if (!bootFile) {
1518 IO_PROM_ERR("can't open boot file\n");
1519 return false;
1520 }
1521 uint bootFileSize = bootFile->getSize();
1522 if (bootFileSize > 64*1024*1024) {
1523 gDisplay->printf("Boot file too large. size=%d (>64MB)\n", bootFileSize);
1524 continue;
1525 }
1526 // set bootpath
1527 char bootpath[1024];
1528 char devicebootpath[1024];
1529 bootrec->d->toPath(devicebootpath, sizeof devicebootpath);
1530 ht_snprintf(bootpath, sizeof bootpath, "%s:%d,BootX", devicebootpath, bootrec->partnum);
1531 // ht_snprintf(bootpath, sizeof bootpath, "/pci/pci-bridge/pci-ata/ata-4/disk1@1:9,BootX");
1532 PromNode *chosen = findDevice("/chosen", FIND_DEVICE_FIND, NULL);
1533 if (chosen) {
1534 chosen->addProp(new PromPropString("bootpath", bootpath));
1535 }
1536
1537 ret_file = bootFile;
1538 // FIXME: HACK!!!
1539 gBootPartNum = bootrec->partnum;
1540 gBootNodeID = bootrec->d->getPHandle();
1541
1542 gDisplay->setAnsiColor(VCP(VC_LIGHT(VC_BLUE), VC_TRANSPARENT));
1543 size = bootFileSize;
1544 switch (bootrec->pe->mBootMethod) {
1545 case BM_chrp: {
1546 direct = false;
1547 return true;
1548 }
1549 case BM_direct: {
1550 direct = true;
1551 loadAddr = bootrec->pe->mBootImageLoadAddr;
1552 entryAddr = bootrec->pe->mBootImageEntrypoint;
1553 return true;
1554 }
1555 default:
1556 ASSERT(0);
1557 }
1558 return false;
1559 } else {
1560 gDisplay->printf("\nInvalid choice, try again.\n");
1561 }
1562 }
1563 return false;
1564 }
1565
1566 bool prom_load_boot_file()
1567 {
1568 if (gPromBootMethod == prombmForce) {
1569 if (gConfig->haveKey("prom_loadfile")) {
1570 String loadfile;
1571 gConfig->getConfigString("prom_loadfile", loadfile);
1572 PromNode *pn = findDevice(gPromBootPath.contentChar(), FIND_DEVICE_FIND, NULL);
1573 if (pn) {
1574 gBootNodeID = pn->getPHandle();
1575 String dev, rest;
1576 gPromBootPath.leftSplit(':', dev, rest);
1577 String partNum, rest2;
1578 rest.leftSplit(',', partNum, rest2);
1579 uint32 p;
1580 if (partNum.toInt32(p)) gBootPartNum = p;
1581 }
1582
1583 LocalFile f(loadfile);
1584 // if (!mapped_load_elf_from_chrp(f, 0)
1585 if (!mapped_load_elf(f)
1586 && !mapped_load_xcoff(f, 0)
1587 && !mapped_load_chrp(f)) {
1588 IO_PROM_WARN("couldn't load '%y'.\n", &loadfile);
1589 return false;
1590 }
1591 } else {
1592 IO_PROM_ERR("bootmethod is 'force', but no prom_loadfile defined\n");
1593 return false;
1594 }
1595 } else {
1596 uint32 loadAddr;
1597 uint32 entryAddr;
1598 File *f;
1599 uint32 msize;
1600 bool direct;
1601 if (!prom_user_boot_partition(f, msize, direct, loadAddr, entryAddr)) {
1602 IO_PROM_WARN("Can't boot a partition.\nTry bootmethod 'force' and specify a 'prom_loadfile' in your config-file...\n");
1603 return false;
1604 }
1605 try {
1606 LocalFile lf("bootfile.dump", IOAM_WRITE, FOM_CREATE);
1607 f->seek(0);
1608 f->copyAllTo(&lf);
1609 } catch (...) {
1610 printf("error dumping bootfile");
1611 }
1612 if (direct) {
1613 if (!mapped_load_direct(*f, loadAddr, entryAddr)) {
1614 IO_PROM_TRACE("couldn't load.\n");
1615 return false;
1616 }
1617 } else {
1618 if (!mapped_load_chrp(*f)) {
1619 IO_PROM_TRACE("couldn't load.\n");
1620 return false;
1621 }
1622 }
1623 delete f;
1624 }
1625 return true;
1626 }

  ViewVC Help
Powered by ViewVC 1.1.26