5eed2a3c9ae5e7e68af1c2a52545b33570098d6b
[yaboot.git] / second / yaboot.c
1 /* Yaboot - secondary boot loader for Linux on ppc.
2
3    Copyright (C) 1999 Benjamin Herrenschmidt
4
5    portions based on poof
6
7    Copyright (C) 1999 Marius Vollmer
8
9    portions based on quik
10    
11    Copyright (C) 1996 Paul Mackerras.
12
13    Because this program is derived from the corresponding file in the
14    silo-0.64 distribution, it is also
15 sys
16    Copyright (C) 1996 Pete A. Zaitcev
17                  1996 Maurizio Plaza
18                  1996 David S. Miller
19                  1996 Miguel de Icaza
20                  1996 Jakub Jelinek
21
22    This program is free software; you can redistribute it and/or modify
23    it under the terms of the GNU General Public License as published by
24    the Free Software Foundation; either version 2 of the License, or
25    (at your option) any later version.
26
27    This program is distributed in the hope that it will be useful,
28    but WITHOUT ANY WARRANTY; without even the implied warranty of
29    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
30    GNU General Public License for more details.
31
32    You should have received a copy of the GNU General Public License
33    along with this program; if not, write to the Free Software
34    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
35 */
36
37 #include "stdarg.h"
38 #include "string.h"
39 #include "ctype.h"
40 #include "stdlib.h"
41 #include "prom.h"
42 #include "file.h"
43 #include "errors.h"
44 #include "cfg.h"
45 #include "cmdline.h"
46 #include "yaboot.h"
47 #include "linux/elf.h"
48 #include "bootinfo.h"
49
50 #define CONFIG_FILE_NAME        "yaboot.conf"
51 #define CONFIG_FILE_MAX         0x8000          /* 32k */
52
53 #ifdef USE_MD5_PASSWORDS
54 #include "md5.h"
55 #endif /* USE_MD5_PASSWORDS */
56
57 /* align addr on a size boundry - adjust address up if needed -- Cort */
58 #define _ALIGN(addr,size)       (((addr)+size-1)&(~(size-1)))
59
60 /* Addresses where the PPC32 and PPC64 vmlinux kernels are linked at.
61  * These are used to determine whether we are booting a vmlinux, in
62  * which case, it will be loaded at KERNELADDR.  Otherwise (eg zImage),
63  * we load the binary where it was linked at (ie, e_entry field in
64  * the ELF header).
65  */
66 #define KERNEL_LINK_ADDR_PPC32  0xC0000000UL
67 #define KERNEL_LINK_ADDR_PPC64  0xC000000000000000ULL
68
69 typedef struct {
70     union {
71         Elf32_Ehdr  elf32hdr;
72         Elf64_Ehdr  elf64hdr;
73     } elf;
74     void*           base;
75     unsigned long   memsize;
76     unsigned long   filesize;
77     unsigned long   offset;
78     unsigned long   load_loc;
79     unsigned long   entry;
80 } loadinfo_t;
81
82 typedef void (*kernel_entry_t)( void *,
83                                 unsigned long,
84                                 prom_entry,
85                                 unsigned long,
86                                 unsigned long );
87
88 /* Imported functions */
89 extern unsigned long reloc_offset(void);
90 extern long flush_icache_range(unsigned long start, unsigned long stop);
91
92 /* Exported functions */
93 int     yaboot_start(unsigned long r3, unsigned long r4, unsigned long r5);
94
95 /* Local functions */
96 static int      yaboot_main(void);
97 static int      is_elf32(loadinfo_t *loadinfo);
98 static int      is_elf64(loadinfo_t *loadinfo);
99 static int      load_elf32(struct boot_file_t *file, loadinfo_t *loadinfo);
100 static int      load_elf64(struct boot_file_t *file, loadinfo_t *loadinfo);
101 static void     setup_display(void);
102
103 /* Locals & globals */
104
105 int useconf = 0;
106 char bootdevice[1024];
107 //char *bootpath = NULL;
108 char *password = NULL;
109 //int bootpartition = -1;
110 struct boot_fspec_t boot;
111 int _machine = _MACH_Pmac;
112
113 #ifdef CONFIG_COLOR_TEXT
114
115 /* Color values for text ui */
116 static struct ansi_color_t {
117         char*   name;
118         int     index;
119         int     value;
120 } ansi_color_table[] = {
121         { "black",              2, 30 },
122         { "blue",               0, 31 },
123         { "green",              0, 32 },
124         { "cyan",               0, 33 },
125         { "red",                0, 34 },
126         { "purple",             0, 35 },
127         { "brown",              0, 36 },
128         { "light-gray",         0, 37 },
129         { "dark-gray",          1, 30 },
130         { "light-blue",         1, 31 },
131         { "light-green",        1, 32 },
132         { "light-cyan",         1, 33 },
133         { "light-red",          1, 34 },
134         { "light-purple",       1, 35 },
135         { "yellow",             1, 36 },
136         { "white",              1, 37 },
137         { NULL,                 0, 0 },
138 };
139
140 /* Default colors for text ui */
141 int fgcolor = 15;
142 int bgcolor = 0;
143 #endif /* CONFIG_COLOR_TEXT */
144
145 #if DEBUG
146 static int test_bss;
147 static int test_data = 0;
148 #endif
149 static int pause_after;
150 static char *pause_message = "Type go<return> to continue.\n";
151 static char given_bootargs[1024];
152 static int given_bootargs_by_user = 0;
153
154 extern unsigned char linux_logo_red[];
155 extern unsigned char linux_logo_green[];
156 extern unsigned char linux_logo_blue[];
157
158 #define DEFAULT_TIMEOUT         -1
159
160 /* Entry, currently called directly by crt0 (bss not inited) */
161
162 extern char* __bss_start;
163 extern char* _end;
164
165 static struct first_info *quik_fip = NULL;
166
167 int
168 yaboot_start (unsigned long r3, unsigned long r4, unsigned long r5)
169 {
170         int result;
171         void* malloc_base = NULL;
172         prom_handle root;
173
174         /* OF seems to do it, but I'm not very confident */
175         memset(&__bss_start, 0, &_end - &__bss_start);
176         
177         /* Check for quik first stage bootloader (but I don't think we are
178          * compatible with it anyway, I'll look into backporting to older OF
179          * versions later
180          */
181         if (r5 == 0xdeadbeef) {
182                 r5 = r3;
183                 quik_fip = (struct first_info *)r4;
184         }
185
186         /* Initialize OF interface */
187         prom_init ((prom_entry) r5);
188         
189         /* Allocate some memory for malloc'ator */
190         malloc_base = prom_claim((void *)MALLOCADDR, MALLOCSIZE, 0);
191         if (malloc_base == (void *)-1) {
192                 prom_printf("Can't claim malloc buffer (%d bytes at 0x%08x)\n",
193                         MALLOCSIZE, MALLOCADDR);
194                 return -1;
195         }
196         malloc_init(malloc_base, MALLOCSIZE);
197         DEBUG_F("Malloc buffer allocated at %p (%d bytes)\n",
198                 malloc_base, MALLOCSIZE);
199                 
200         /* A few useless DEBUG_F's */
201         DEBUG_F("reloc_offset :  %ld         (should be 0)\n", reloc_offset());
202         DEBUG_F("test_bss     :  %d         (should be 0)\n", test_bss);
203         DEBUG_F("test_data    :  %d         (should be 0)\n", test_data);
204         DEBUG_F("&test_data   :  %p\n", &test_data);
205         DEBUG_F("&test_bss    :  %p\n", &test_bss);
206         DEBUG_F("linked at    :  0x%08x\n", TEXTADDR);
207
208         /* ask the OF info if we're a chrp or pmac */
209         /* we need to set _machine before calling finish_device_tree */
210         root = prom_finddevice("/");
211         if (root != 0) {
212                 static char model[256];
213                 if (prom_getprop(root, "device_type", model, 256 ) > 0 &&
214                         !strncmp("chrp", model, 4))
215                         _machine = _MACH_chrp;
216                 else {
217                         if (prom_getprop(root, "model", model, 256 ) > 0 &&
218                                 !strncmp(model, "IBM", 3))
219                                 _machine = _MACH_chrp;
220                 }
221         }
222         
223         DEBUG_F("Running on _machine = %d\n", _machine);
224         DEBUG_SLEEP;
225
226         /* Call out main */
227         result = yaboot_main();
228
229         /* Get rid of malloc pool */
230         malloc_dispose();
231         prom_release(malloc_base, MALLOCSIZE);
232         DEBUG_F("Malloc buffer released. Exiting with code %d\n",
233                 result);
234
235         /* Return to OF */
236         prom_exit();
237         
238         return result;
239         
240 }
241
242 #ifdef CONFIG_COLOR_TEXT
243 /*
244  * Validify color for text ui
245  */
246 static int
247 check_color_text_ui(char *color)
248 {
249         int i = 0;
250         while(ansi_color_table[i].name) {
251                 if (!strcmp(color, ansi_color_table[i].name))
252                         return i;
253                 i++;
254         }
255         return -1;
256 }      
257 #endif /* CONFIG_COLOR_TEXT */
258
259 /* Currently, the config file must be at the root of the filesystem.
260  * todo: recognize the full path to myself and use it to load the
261  * config file. Handle the "\\" (blessed system folder)
262  */
263 static int
264 load_config_file(char *device, char* path, int partition)
265 {
266     char *conf_file = NULL, *p;
267     struct boot_file_t file;
268     int sz, opened = 0, result = 0;
269     char conf_path[512];
270     struct boot_fspec_t fspec;
271
272     /* Allocate a buffer for the config file */
273     conf_file = malloc(CONFIG_FILE_MAX);
274     if (!conf_file) {
275         prom_printf("Can't alloc config file buffer\n");
276         goto bail;
277     }
278
279     /* Build the path to the file */
280     if (path)
281         strcpy(conf_path, path);
282     else if ( _machine == _MACH_chrp )
283         strcpy(conf_path, "/etc/");
284     else
285         conf_path[0] = 0;
286     strcat(conf_path, CONFIG_FILE_NAME);
287
288     /* Open it */
289     fspec.dev = device;
290     fspec.file = conf_path;
291     fspec.part = partition;
292     result = open_file(&fspec, &file);
293     if (result != FILE_ERR_OK) {
294          prom_printf("%s:%d", fspec.dev, fspec.part);
295          prom_perror(result, fspec.file);
296          prom_printf("Can't open config file\n");
297          goto bail;
298     }
299     opened = 1;
300
301     /* Read it */
302     sz = file.fs->read(&file, CONFIG_FILE_MAX, conf_file);
303     if (sz <= 0) {
304         prom_printf("Error, can't read config file\n");
305         goto bail;
306     }
307     prom_printf("Config file read, %d bytes\n", sz);
308
309     /* Close the file */
310     if (opened)
311         file.fs->close(&file);
312     opened = 0;
313
314     /* Call the parsing code in cfg.c */
315     if (cfg_parse(conf_path, conf_file, sz) < 0) {
316         prom_printf ("Syntax error or read error config\n");
317         goto bail;
318     }
319
320     DEBUG_F("Config file successfully parsed, %d bytes\n", sz);
321
322     /* Now, we do the initialisations stored in the config file */
323     p = cfg_get_strg(0, "init-code");
324     if (p)
325         prom_interpret(p);
326
327     password = cfg_get_strg(0, "password");
328         
329 #ifdef CONFIG_COLOR_TEXT
330     p = cfg_get_strg(0, "fgcolor");
331     if (p) {
332        DEBUG_F("fgcolor=%s\n", p);
333        fgcolor = check_color_text_ui(p);
334        if (fgcolor == -1) {
335           prom_printf("Invalid fgcolor: \"%s\".\n", p);
336        }
337     }
338     p = cfg_get_strg(0, "bgcolor");
339     if (p) {
340        DEBUG_F("bgcolor=%s\n", p);
341        bgcolor = check_color_text_ui(p);
342        if (bgcolor == -1)
343           prom_printf("Invalid bgcolor: \"%s\".\n", p);
344     }
345     if (bgcolor >= 0) {
346         char temp[64];
347         sprintf(temp, "%x to background-color", bgcolor); 
348         prom_interpret(temp); 
349 #if !DEBUG
350         prom_printf("\xc");
351 #endif /* !DEBUG */
352     }
353     if (fgcolor >= 0) {
354         char temp[64];
355         sprintf(temp, "%x to foreground-color", fgcolor); 
356         prom_interpret(temp); 
357     }
358 #endif /* CONFIG_COLOR_TEXT */
359    
360     p = cfg_get_strg(0, "init-message");
361     if (p)
362         prom_printf("%s\n", p);
363 #if 0
364     p = cfg_get_strg(0, "message");
365     if (p)
366         print_message_file(p);
367 #endif          
368
369     result = 1;
370     
371 bail:
372
373     if (opened)
374         file.fs->close(&file);
375     
376     if (result != 1 && conf_file)
377         free(conf_file);
378         
379     return result;
380 }
381
382 void maintabfunc (void)
383 {
384     if (useconf) {
385         cfg_print_images();
386         prom_printf("boot: %s", cbuff);
387     }
388 }
389
390 void
391 word_split(char **linep, char **paramsp)
392 {
393     char *p;
394
395     *paramsp = 0;
396     p = *linep;
397     if (p == 0)
398         return;
399     while (*p == ' ')
400         ++p;
401     if (*p == 0) {
402         *linep = 0;
403         return;
404     }
405     *linep = p;
406     while (*p != 0 && *p != ' ')
407         ++p;
408     while (*p == ' ')
409         *p++ = 0;
410     if (*p != 0)
411         *paramsp = p;
412 }
413
414 char *
415 make_params(char *label, char *params)
416 {
417     char *p, *q;
418     static char buffer[2048];
419
420     q = buffer;
421     *q = 0;
422
423     p = cfg_get_strg(label, "literal");
424     if (p) {
425         strcpy(q, p);
426         q = strchr(q, 0);
427         if (params) {
428             if (*p)
429                 *q++ = ' ';
430             strcpy(q, params);
431         }
432         return buffer;
433     }
434
435     p = cfg_get_strg(label, "root");
436     if (p) {
437         strcpy (q, "root=");
438         strcpy (q + 5, p);
439         q = strchr (q, 0);
440         *q++ = ' ';
441     }
442     if (cfg_get_flag(label, "read-only")) {
443         strcpy (q, "ro ");
444         q += 3;
445     }
446     if (cfg_get_flag(label, "read-write")) {
447         strcpy (q, "rw ");
448         q += 3;
449     }
450     p = cfg_get_strg(label, "ramdisk");
451     if (p) {
452         strcpy (q, "ramdisk=");
453         strcpy (q + 8, p);
454         q = strchr (q, 0);
455         *q++ = ' ';
456     }
457     p = cfg_get_strg(label, "initrd-size");
458     if (p) {
459         strcpy (q, "ramdisk_size=");
460         strcpy (q + 13, p);
461         q = strchr (q, 0);
462         *q++ = ' ';
463     }
464     if (cfg_get_flag(label, "novideo")) {
465         strcpy (q, "video=ofonly");
466         q = strchr (q, 0);
467         *q++ = ' ';
468     }
469     p = cfg_get_strg (label, "append");
470     if (p) {
471         strcpy (q, p);
472         q = strchr (q, 0);
473         *q++ = ' ';
474     }
475     *q = 0;
476     pause_after = cfg_get_flag (label, "pause-after");
477     p = cfg_get_strg(label, "pause-message");
478     if (p)
479         pause_message = p;
480     if (params)
481         strcpy(q, params);
482
483     return buffer;
484 }
485
486 void check_password(char *str)
487 {
488     int i;
489
490     for (i = 0; i < 3; i++) {
491          prom_printf ("\n%sassword: ", str);
492          passwdbuff[0] = 0;
493          cmdedit ((void (*)(void)) 0, 1);
494          prom_printf ("\n");
495 #ifdef USE_MD5_PASSWORDS
496          if (!strncmp (password, "$1$", 3)) {
497             if (!check_md5_password(passwdbuff, password))
498                return;
499          } 
500          else if (!strcmp (password, passwdbuff))
501             return;
502 #else /* !MD5 */
503          if (!strcmp (password, passwdbuff))
504             return;
505 #endif /* USE_MD5_PASSWORDS */
506          if (i < 2)
507             prom_printf ("Password incorrect. Please try again...");
508     }
509     prom_printf ("Seems like you don't know the access password.  Go away!\n");
510     prom_sleep(3);
511     prom_interpret("reset-all");
512 }
513
514 int get_params(struct boot_param_t* params)
515 {
516     int defpart;
517     char *defdevice = 0;
518     char *p, *q, *endp;
519     int c, n;
520     char *imagename = 0, *label;
521     int timeout = -1;
522     int beg = 0, end;
523     int singlekey = 0;
524     int restricted = 0;
525     static int first = 1;
526     static char bootargs[1024];
527     static char imagepath[1024];
528     static char initrdpath[1024];
529     static char sysmappath[1024];
530
531     pause_after = 0;
532     memset(params, 0, sizeof(*params));
533     params->args = "";
534     params->kernel.part = -1;
535     params->rd.part = -1;
536     params->sysmap.part = -1;
537     defpart = boot.part;
538     
539     cmdinit();
540
541     if (first) {
542         first = 0;
543         prom_get_chosen("bootargs", bootargs, sizeof(bootargs));
544         imagename = bootargs;
545         word_split(&imagename, &params->args);
546         timeout = DEFAULT_TIMEOUT;
547         if (imagename) {
548              prom_printf("Default supplied on the command line: %s ", imagename);
549              if (params->args)
550                   prom_printf("%s", params->args);
551              prom_printf("\n");
552         }
553         if (useconf && (q = cfg_get_strg(0, "timeout")) != 0 && *q != 0)
554             timeout = simple_strtol(q, NULL, 0);
555     }
556
557     prom_printf("boot: ");
558     c = -1;
559     if (timeout != -1) {
560          beg = prom_getms();
561          if (timeout > 0) {
562               end = beg + 100 * timeout;
563               do {
564                    c = prom_nbgetchar();
565               } while (c == -1 && prom_getms() <= end);
566          }
567          if (c == -1)
568               c = '\n';
569          else if (c != '\n' && c != '\t' && c != '\r' && c != '\b' ) {
570               cbuff[0] = c;
571               cbuff[1] = 0;
572          }
573     }
574
575     if (c != -1 && c != '\n' && c != '\r') {
576          if (c == '\t') {
577               maintabfunc ();
578          }  else if (c >= ' ') {
579               cbuff[0] = c;
580               cbuff[1] = 0;
581               if ((cfg_get_flag (cbuff, "single-key")) && useconf) {
582                    imagename = cbuff;
583                    singlekey = 1;
584                    prom_printf("%s\n", cbuff);
585               }
586          }
587     }
588
589     if (c == '\n' || c == '\r') {
590          if (!imagename)
591               imagename = cfg_get_default();
592          if (imagename)
593               prom_printf("%s", imagename);
594          if (params->args)
595               prom_printf(" %s", params->args);
596          prom_printf("\n");
597     } else if (!singlekey) {
598          cmdedit(maintabfunc, 0);
599          prom_printf("\n");
600          strcpy(given_bootargs, cbuff);
601          given_bootargs_by_user = 1;
602          imagename = cbuff;
603          word_split(&imagename, &params->args);
604     }
605
606     /* chrp gets this wrong, force it -- Cort */
607     if ( useconf && (!imagename || imagename[0] == 0 ))
608         imagename = cfg_get_default();
609
610     label = 0;
611     defdevice = boot.dev;
612
613     if (useconf) {
614         defdevice = cfg_get_strg(0, "device");
615         p = cfg_get_strg(0, "partition");
616         if (p) {
617             n = simple_strtol(p, &endp, 10);
618             if (endp != p && *endp == 0)
619                 defpart = n;
620         }
621         p = cfg_get_strg(0, "pause-message");
622         if (p)
623             pause_message = p;
624         if (cfg_get_flag(0, "restricted"))
625             restricted = 1;
626         p = cfg_get_strg(imagename, "image");
627         if (p && *p) {
628             label = imagename;
629             imagename = p;
630             defdevice = cfg_get_strg(label, "device");
631             if(!defdevice) defdevice=boot.dev;
632             p = cfg_get_strg(label, "partition");
633             if (p) {
634                 n = simple_strtol(p, &endp, 10);
635                 if (endp != p && *endp == 0)
636                     defpart = n;
637             }
638             if (cfg_get_flag(label, "restricted"))
639                  restricted = 1;
640             if (label) {
641                  if (params->args && password && restricted)
642                       check_password ("To specify image arguments you must enter the p");
643                  else if (password && !restricted)
644                       check_password ("P");
645             }
646             params->args = make_params(label, params->args);
647         }
648     }
649
650     if (!strcmp (imagename, "help")) {
651          prom_printf(
652               "\nPress the tab key for a list of defined images.\n"
653               "The label marked with a \"*\" is is the default image, "
654               "press <return> to boot it.\n\n"
655               "To boot any other label simply type its name and press <return>.\n\n"
656               "To boot a kernel image which is not defined in the yaboot configuration \n"
657               "file, enter the kernel image name as [device:][partno],/path, where \n"
658               "\"device:\" is the OpenFirmware device path to the disk the image \n"
659               "resides on, and \"partno\" is the partition number the image resides on.\n\n"
660               "If you omit \"device:\" and \"partno\" yaboot will use the values of \n"
661               "\"device=\" and \"partition=\" in yaboot.conf, right now those are set to: \n"
662               "device=%s\n"
663               "partition=%d\n\n", defdevice, defpart);
664          return 0;
665     }
666
667     if (!strcmp (imagename, "halt")) {
668          if (password)
669               check_password ("P");
670          prom_pause();
671          return 0;
672     }
673     if (!strcmp (imagename, "bye")) {
674          if (password) {
675               check_password ("P");
676               return 1;
677          }
678          return 1; 
679     }
680
681     if (imagename[0] == '$') {
682         /* forth command string */
683          if (password)
684               check_password ("P");
685          prom_interpret(imagename+1);
686          return 0;
687     }
688
689     strncpy(imagepath, imagename, 1024);
690
691     if (!label && password)
692          check_password ("To boot a custom image you must enter the p");
693
694     if (!parse_device_path(imagepath, defdevice, defpart,
695                            "/vmlinux", &params->kernel)) {
696          prom_printf("%s: Unable to parse\n", imagepath);
697          return 0;
698     }
699     DEBUG_F("after parse_device_path: dev=%s part=%d file=%s\n", params->kernel.dev,
700             params->kernel.part, params->kernel.file);
701
702     if (useconf) {
703         p = cfg_get_strg(label, "initrd");
704         if (p && *p) {
705             DEBUG_F("Parsing initrd path <%s>\n", p);
706             strncpy(initrdpath, p, 1024);
707             if (!parse_device_path(initrdpath, defdevice, defpart,
708                                    "/root.bin", &params->rd)) {
709                  prom_printf("%s: Unable to parse\n", imagepath);
710                  return 0;
711             }
712         }
713         p = cfg_get_strg(label, "sysmap");
714         if (p && *p) {
715             DEBUG_F("Parsing sysmap path <%s>\n", p);
716             strncpy(sysmappath, p, 1024);
717             if (!parse_device_path(sysmappath, defdevice, defpart,
718                                    "/boot/System.map", &params->sysmap)) {
719                  prom_printf("%s: Unable to parse\n", imagepath);
720                  return 0;
721             }
722         }
723     }
724     return 0;
725 }
726
727 /* This is derived from quik core. To be changed to first parse the headers
728  * doing lazy-loading, and then claim the memory before loading the kernel
729  * to it
730  * We also need to add initrd support to this whole mecanism
731  */
732 void
733 yaboot_text_ui(void)
734 {
735 #define MAX_HEADERS     32
736
737     struct boot_file_t  file;
738     int                 result;
739     static struct boot_param_t  params;
740     void                *initrd_base;
741     unsigned long       initrd_size;
742     void                *sysmap_base;
743     unsigned long       sysmap_size;
744     kernel_entry_t      kernel_entry;
745     struct bi_record*   birec;
746     char*               loc=NULL;
747     loadinfo_t          loadinfo;
748     void                *initrd_more,*initrd_want;
749     unsigned long       initrd_read;
750     
751     loadinfo.load_loc = 0;
752
753     for (;;) {
754         initrd_size = 0;
755         initrd_base = 0;
756         sysmap_base = 0;
757         sysmap_size = 0;
758         
759         if (get_params(&params))
760             return;
761         if (!params.kernel.file)
762             continue;
763         
764         prom_printf("Please wait, loading kernel...\n");
765
766         memset(&file, 0, sizeof(file));
767
768         if (strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.kernel.file[0] != '/'
769             && params.kernel.file[0] != '\\') {
770              loc=(char*)malloc(strlen(params.kernel.file)+3);
771              if (!loc) {
772                   prom_printf ("malloc error\n");
773                   goto next;
774              }
775              strcpy(loc,boot.file);
776              strcat(loc,params.kernel.file);
777              free(params.kernel.file);
778              params.kernel.file=loc;
779         }
780         result = open_file(&params.kernel, &file);
781         if (result != FILE_ERR_OK) {
782              prom_printf("%s:%d,", params.kernel.dev, params.kernel.part);
783              prom_perror(result, params.kernel.file);
784              goto next;
785         }
786
787         /* Read the Elf e_ident, e_type and e_machine fields to
788          * determine Elf file type
789          */
790         if (file.fs->read(&file, sizeof(Elf_Ident), &loadinfo.elf) < sizeof(Elf_Ident)) {
791              prom_printf("\nCan't read Elf e_ident/e_type/e_machine info\n");
792              file.fs->close(&file);
793              memset(&file, 0, sizeof(file));
794              goto next;
795         }
796
797         if (is_elf32(&loadinfo)) {
798              if (!load_elf32(&file, &loadinfo)) {
799                   file.fs->close(&file);
800                   memset(&file, 0, sizeof(file));
801                   goto next;
802              }
803              prom_printf("   Elf32 kernel loaded...\n");
804         } else if (is_elf64(&loadinfo)) {
805              if (!load_elf64(&file, &loadinfo)) {
806                   file.fs->close(&file);
807                   memset(&file, 0, sizeof(file));
808                   goto next;
809              }
810              prom_printf("   Elf64 kernel loaded...\n");
811         } else {
812              prom_printf ("%s: Not a valid ELF image\n", params.kernel.file);
813              file.fs->close(&file);
814              memset(&file, 0, sizeof(file));
815              goto next;
816         }
817         file.fs->close(&file);
818         memset(&file, 0, sizeof(file));
819
820         /* If sysmap, load it. 
821          */
822         if (params.sysmap.file) {
823              prom_printf("Loading System.map ...\n");
824              if(strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.sysmap.file[0] != '/'
825                 && params.sysmap.file[0] != '\\') {
826                   if (loc) free(loc);
827                   loc=(char*)malloc(strlen(params.sysmap.file)+3);
828                   if (!loc) {
829                        prom_printf ("malloc error\n");
830                        goto next;
831                   }
832                   strcpy(loc,boot.file);
833                   strcat(loc,params.sysmap.file);
834                   free(params.sysmap.file);
835                   params.sysmap.file=loc;
836              }
837              
838              result = open_file(&params.sysmap, &file);
839              if (result != FILE_ERR_OK) {
840                   prom_printf("%s:%d,", params.sysmap.dev, params.sysmap.part);
841                   prom_perror(result, params.sysmap.file);
842              }
843              else {
844                   sysmap_base = prom_claim(loadinfo.base+loadinfo.memsize, 0x100000, 0);
845                   if (sysmap_base == (void *)-1) {
846                        prom_printf("Claim failed for sysmap memory\n");
847                        sysmap_base = 0;
848                   } else {
849                        sysmap_size = file.fs->read(&file, 0xfffff, sysmap_base);
850                        if (sysmap_size == 0)
851                             sysmap_base = 0;
852                        else
853                             ((char *)sysmap_base)[sysmap_size++] = 0;
854                   }
855                   file.fs->close(&file);
856                   memset(&file, 0, sizeof(file));
857              }
858              if (sysmap_base) {
859                   prom_printf("System.map loaded at %p, size: %lu Kbytes\n",
860                               sysmap_base, sysmap_size >> 10);
861                   loadinfo.memsize += _ALIGN(0x100000, 0x1000);
862              } else {
863                   prom_printf("System.map load failed !\n");
864                   prom_pause();
865              }
866         }
867
868         /* If ramdisk, load it. For now, we can't tell the size it will be
869          * so we claim an arbitrary amount of 4Mb
870          */
871         if (params.rd.file) {
872             if(strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.rd.file[0] != '/'
873                && params.kernel.file[0] != '\\')
874             {
875                 if (loc) free(loc);
876                 loc=(char*)malloc(strlen(params.rd.file)+3);
877                 if (!loc) {
878                     prom_printf ("Malloc error\n");
879                     goto next;
880                 }
881                 strcpy(loc,boot.file);
882                 strcat(loc,params.rd.file);
883                 free(params.rd.file);
884                 params.rd.file=loc;
885             }
886             prom_printf("Loading ramdisk...\n");
887             result = open_file(&params.rd, &file);
888             if (result != FILE_ERR_OK) {
889                  prom_printf("%s:%d,", params.rd.dev, params.rd.part);
890                  prom_perror(result, params.rd.file);
891             }
892             else {
893 #define INITRD_CHUNKSIZE 0x400000
894                 initrd_base = prom_claim(loadinfo.base+loadinfo.memsize, INITRD_CHUNKSIZE, 0);
895                 if (initrd_base == (void *)-1) {
896                     prom_printf("Claim failed for initrd memory\n");
897                     initrd_base = 0;
898                 } else {
899                     initrd_size = file.fs->read(&file, INITRD_CHUNKSIZE, initrd_base);
900                     if (initrd_size == 0)
901                         initrd_base = 0;
902                     initrd_read = initrd_size;
903                     initrd_more = initrd_base;
904                     while (initrd_read == INITRD_CHUNKSIZE ) { /* need to read more? */
905                       initrd_want = (void *)((unsigned long)initrd_more+INITRD_CHUNKSIZE);
906                       initrd_more = prom_claim(initrd_want, INITRD_CHUNKSIZE, 0);
907                       if (initrd_more != initrd_want) {
908                         prom_printf("Claim failed for initrd memory at %p rc=%p\n",initrd_want,initrd_more);
909                         break;
910                       }
911                     initrd_read = file.fs->read(&file, INITRD_CHUNKSIZE, initrd_more);
912                     DEBUG_F("  block at %p rc=%lu\n",initrd_more,initrd_read);
913                     initrd_size += initrd_read;
914                     }
915                 }
916                 file.fs->close(&file);
917                 memset(&file, 0, sizeof(file));
918             }
919             if (initrd_base)
920                 prom_printf("ramdisk loaded at %p, size: %lu Kbytes\n",
921                         initrd_base, initrd_size >> 10);
922             else {
923                 prom_printf("ramdisk load failed !\n");
924                 prom_pause();
925             }
926         }
927
928         DEBUG_F("setting kernel args to: %s\n", params.args);
929         prom_setargs(params.args);
930         DEBUG_F("flushing icache...");
931         flush_icache_range ((long)loadinfo.base, (long)loadinfo.base+loadinfo.memsize);
932         DEBUG_F(" done\n");
933
934         /* 
935          * Fill mew boot infos
936          *
937          * The birec is low on memory, probably inside the malloc pool, so
938          * we don't write it earlier. At this point, we should not use anything
939          * coming from the malloc pool
940          */
941         birec = (struct bi_record *)_ALIGN(loadinfo.filesize+(1<<20)-1,(1<<20));
942
943         /* We make sure it's mapped. We map only 64k for now, it's plenty enough
944          * we don't claim since this precise memory range may already be claimed
945          * by the malloc pool
946          */
947         prom_map (birec, birec, 0x10000);
948         DEBUG_F("birec at %p\n", birec);
949         DEBUG_SLEEP;
950
951         birec->tag = BI_FIRST;
952         birec->size = sizeof(struct bi_record);
953         birec = (struct bi_record *)((unsigned long)birec + birec->size);
954         
955         birec->tag = BI_BOOTLOADER_ID;
956         sprintf( (char *)birec->data, "yaboot");
957         birec->size = sizeof(struct bi_record) + strlen("yaboot") + 1;
958         birec = (struct bi_record *)((unsigned long)birec + birec->size);
959         
960         birec->tag = BI_MACHTYPE;
961         birec->data[0] = _machine;
962         birec->size = sizeof(struct bi_record) + sizeof(unsigned long);
963         birec = (struct bi_record *)((unsigned long)birec + birec->size);
964
965         if (sysmap_base) {
966                 birec->tag = BI_SYSMAP;
967                 birec->data[0] = (unsigned long)sysmap_base;
968                 birec->data[1] = sysmap_size;
969                 birec->size = sizeof(struct bi_record) + sizeof(unsigned long)*2;
970                 birec = (struct bi_record *)((unsigned long)birec + birec->size);
971         }
972         birec->tag = BI_LAST;
973         birec->size = sizeof(struct bi_record);
974         birec = (struct bi_record *)((unsigned long)birec + birec->size);
975
976         /* compute the kernel's entry point. */
977         kernel_entry = loadinfo.base + loadinfo.entry - loadinfo.load_loc;
978
979         DEBUG_F("Kernel entry point = %p\n", kernel_entry);
980         DEBUG_F("kernel: arg1 = %p,\n"
981                 "        arg2 = 0x%08lx,\n"
982                 "        prom = %p,\n"
983                 "        arg4 = %d,\n"
984                 "        arg5 = %d\n\n",
985                 initrd_base + loadinfo.load_loc, initrd_size, prom, 0, 0);
986
987         DEBUG_F("Entering kernel...\n");
988
989         /* call the kernel with our stack. */
990         kernel_entry(initrd_base + loadinfo.load_loc, initrd_size, prom, 0, 0);
991         continue;
992 next:
993         ; /* do nothing */
994     }
995 }
996
997 static int
998 load_elf32(struct boot_file_t *file, loadinfo_t *loadinfo)
999 {
1000     int                 i;
1001     Elf32_Ehdr          *e = &(loadinfo->elf.elf32hdr);
1002     Elf32_Phdr          *p, *ph;
1003     int                 size = sizeof(Elf32_Ehdr) - sizeof(Elf_Ident);
1004     unsigned long       addr, loadaddr;
1005
1006     /* Read the rest of the Elf header... */
1007     if ((*(file->fs->read))(file, size, &e->e_version) < size) {
1008         prom_printf("\nCan't read Elf32 image header\n");
1009         return 0;
1010     }
1011
1012     DEBUG_F("Elf32 header:\n");
1013     DEBUG_F(" e.e_type      = %d\n", (int)e->e_type);
1014     DEBUG_F(" e.e_machine   = %d\n", (int)e->e_machine);
1015     DEBUG_F(" e.e_version   = %d\n", (int)e->e_version);
1016     DEBUG_F(" e.e_entry     = 0x%08x\n", (int)e->e_entry);
1017     DEBUG_F(" e.e_phoff     = 0x%08x\n", (int)e->e_phoff);
1018     DEBUG_F(" e.e_shoff     = 0x%08x\n", (int)e->e_shoff);
1019     DEBUG_F(" e.e_flags     = %d\n", (int)e->e_flags);
1020     DEBUG_F(" e.e_ehsize    = 0x%08x\n", (int)e->e_ehsize);
1021     DEBUG_F(" e.e_phentsize = 0x%08x\n", (int)e->e_phentsize);
1022     DEBUG_F(" e.e_phnum     = %d\n", (int)e->e_phnum);
1023
1024     loadinfo->entry = e->e_entry;
1025
1026     if (e->e_phnum > MAX_HEADERS) {
1027         prom_printf ("Can only load kernels with one program header\n");
1028         return 0;
1029     }
1030
1031     ph = (Elf32_Phdr *)malloc(sizeof(Elf32_Phdr) * e->e_phnum);
1032     if (!ph) {
1033         prom_printf ("Malloc error\n");
1034         return 0;
1035     }
1036
1037     /* Now, we read the section header */
1038     if ((*(file->fs->seek))(file, e->e_phoff) != FILE_ERR_OK) {
1039         prom_printf ("seek error\n");
1040         return 0;
1041     }
1042     if ((*(file->fs->read))(file, sizeof(Elf32_Phdr) * e->e_phnum, ph) !=
1043             sizeof(Elf32_Phdr) * e->e_phnum) {
1044         prom_printf ("read error\n");
1045         return 0;
1046     }
1047
1048     /* Scan through the program header
1049      * HACK:  We must return the _memory size of the kernel image, not the
1050      *        file size (because we have to leave room before other boot
1051      *    infos. This code works as a side effect of the fact that
1052      *    we have one section and vaddr == p_paddr
1053      */
1054     loadinfo->memsize = loadinfo->filesize = loadinfo->offset = 0;
1055     p = ph;
1056     for (i = 0; i < e->e_phnum; ++i, ++p) {
1057         if (p->p_type != PT_LOAD || p->p_offset == 0)
1058             continue;
1059         if (loadinfo->memsize == 0) {
1060             loadinfo->offset = p->p_offset;
1061             loadinfo->memsize = p->p_memsz;
1062             loadinfo->filesize = p->p_filesz;
1063             loadinfo->load_loc = p->p_vaddr;
1064         } else {
1065             loadinfo->memsize = p->p_offset + p->p_memsz - loadinfo->offset; /* XXX Bogus */
1066             loadinfo->filesize = p->p_offset + p->p_filesz - loadinfo->offset;
1067         }
1068     }
1069
1070     if (loadinfo->memsize == 0) {
1071         prom_printf("Can't find a loadable segment !\n");
1072         return 0;
1073     }
1074
1075     /* leave some room (1Mb) for boot infos */
1076     loadinfo->memsize = _ALIGN(loadinfo->memsize,(1<<20)) + 0x100000;
1077     /* Claim OF memory */
1078     DEBUG_F("Before prom_claim, mem_sz: 0x%08lx\n", loadinfo->memsize);
1079
1080     /* On some systems, loadaddr may already be claimed, so try some
1081      * other nearby addresses before giving up.
1082      */
1083     loadaddr = (e->e_entry == KERNEL_LINK_ADDR_PPC32 ||
1084                 e->e_entry == 0) ? KERNELADDR : e->e_entry;
1085     for(addr=loadaddr; addr <= loadaddr * 8 ;addr+=0x100000) {
1086         loadinfo->base = prom_claim((void *)addr, loadinfo->memsize, 0);
1087         if (loadinfo->base != (void *)-1) break;
1088     }
1089     if (loadinfo->base == (void *)-1) {
1090         prom_printf("Claim error, can't allocate kernel memory\n");
1091         return 0;
1092     }   
1093
1094     DEBUG_F("After ELF parsing, load base: %p, mem_sz: 0x%08lx\n",
1095             loadinfo->base, loadinfo->memsize);
1096     DEBUG_F("    wanted load base: 0x%08lx, mem_sz: 0x%08lx\n",
1097             loadaddr, loadinfo->memsize);
1098
1099     /* Load the program segments... */
1100     p = ph;
1101     for (i = 0; i < e->e_phnum; ++i, ++p) {
1102             unsigned long offset;
1103             if (p->p_type != PT_LOAD || p->p_offset == 0)
1104                     continue;
1105
1106             /* Now, we skip to the image itself */
1107             if ((*(file->fs->seek))(file, p->p_offset) != FILE_ERR_OK) {
1108                     prom_printf ("Seek error\n");
1109                     prom_release(loadinfo->base, loadinfo->memsize);
1110                     return 0;
1111             }
1112             offset = p->p_vaddr - loadinfo->load_loc;
1113             if ((*(file->fs->read))(file, p->p_filesz, loadinfo->base+offset) != p->p_filesz) {
1114                  prom_printf ("Read failed\n");
1115                  prom_release(loadinfo->base, loadinfo->memsize);
1116                  return 0;
1117             }
1118     }
1119
1120     free(ph);
1121     
1122     /* Return success at loading the Elf32 kernel */
1123     return 1;
1124 }
1125
1126 static int
1127 load_elf64(struct boot_file_t *file, loadinfo_t *loadinfo)
1128 {
1129     int                 i;
1130     Elf64_Ehdr          *e = &(loadinfo->elf.elf64hdr);
1131     Elf64_Phdr          *p, *ph;
1132     int                 size = sizeof(Elf64_Ehdr) - sizeof(Elf_Ident);
1133     unsigned long       addr, loadaddr;
1134
1135     /* Read the rest of the Elf header... */
1136     if ((*(file->fs->read))(file, size, &e->e_version) < size) {
1137         prom_printf("\nCan't read Elf64 image header\n");
1138         return 0;
1139     }
1140
1141     DEBUG_F("Elf64 header:\n");
1142     DEBUG_F(" e.e_type      = %d\n", (int)e->e_type);
1143     DEBUG_F(" e.e_machine   = %d\n", (int)e->e_machine);
1144     DEBUG_F(" e.e_version   = %d\n", (int)e->e_version);
1145     DEBUG_F(" e.e_entry     = 0x%016lx\n", (long)e->e_entry);
1146     DEBUG_F(" e.e_phoff     = 0x%016lx\n", (long)e->e_phoff);
1147     DEBUG_F(" e.e_shoff     = 0x%016lx\n", (long)e->e_shoff);
1148     DEBUG_F(" e.e_flags     = %d\n", (int)e->e_flags);
1149     DEBUG_F(" e.e_ehsize    = 0x%08x\n", (int)e->e_ehsize);
1150     DEBUG_F(" e.e_phentsize = 0x%08x\n", (int)e->e_phentsize);
1151     DEBUG_F(" e.e_phnum     = %d\n", (int)e->e_phnum);
1152
1153     loadinfo->entry = e->e_entry;
1154
1155     if (e->e_phnum > MAX_HEADERS) {
1156         prom_printf ("Can only load kernels with one program header\n");
1157         return 0;
1158     }
1159
1160     ph = (Elf64_Phdr *)malloc(sizeof(Elf64_Phdr) * e->e_phnum);
1161     if (!ph) {
1162         prom_printf ("Malloc error\n");
1163         return 0;
1164     }
1165
1166     /* Now, we read the section header */
1167     if ((*(file->fs->seek))(file, e->e_phoff) != FILE_ERR_OK) {
1168         prom_printf ("Seek error\n");
1169         return 0;
1170     }
1171     if ((*(file->fs->read))(file, sizeof(Elf64_Phdr) * e->e_phnum, ph) !=
1172             sizeof(Elf64_Phdr) * e->e_phnum) {
1173         prom_printf ("Read error\n");
1174         return 0;
1175     }
1176
1177     /* Scan through the program header
1178      * HACK:  We must return the _memory size of the kernel image, not the
1179      *        file size (because we have to leave room before other boot
1180      *    infos. This code works as a side effect of the fact that
1181      *    we have one section and vaddr == p_paddr
1182      */
1183     loadinfo->memsize = loadinfo->filesize = loadinfo->offset = 0;
1184     p = ph;
1185     for (i = 0; i < e->e_phnum; ++i, ++p) {
1186         if (p->p_type != PT_LOAD || p->p_offset == 0)
1187             continue;
1188         if (loadinfo->memsize == 0) {
1189             loadinfo->offset = p->p_offset;
1190             loadinfo->memsize = p->p_memsz;
1191             loadinfo->filesize = p->p_filesz;
1192             loadinfo->load_loc = p->p_vaddr;
1193         } else {
1194             loadinfo->memsize = p->p_offset + p->p_memsz - loadinfo->offset; /* XXX Bogus */
1195             loadinfo->filesize = p->p_offset + p->p_filesz - loadinfo->offset;
1196         }
1197     }
1198
1199     if (loadinfo->memsize == 0) {
1200         prom_printf("Can't find a loadable segment !\n");
1201         return 0;
1202     }
1203
1204     /* leave some room (1Mb) for boot infos */
1205     loadinfo->memsize = _ALIGN(loadinfo->memsize,(1<<20)) + 0x100000;
1206     /* Claim OF memory */
1207     DEBUG_F("Before prom_claim, mem_sz: 0x%08lx\n", loadinfo->memsize);
1208
1209     /* On some systems, loadaddr may already be claimed, so try some
1210      * other nearby addresses before giving up.
1211      */
1212     loadaddr = (e->e_entry == KERNEL_LINK_ADDR_PPC64) ? KERNELADDR : e->e_entry;
1213     for(addr=loadaddr; addr <= loadaddr * 8 ;addr+=0x100000) {
1214         loadinfo->base = prom_claim((void *)addr, loadinfo->memsize, 0);
1215         if (loadinfo->base != (void *)-1) break;
1216     }
1217     if (loadinfo->base == (void *)-1) {
1218         prom_printf("Claim error, can't allocate kernel memory\n");
1219         return 0;
1220     }   
1221
1222     DEBUG_F("After ELF parsing, load base: %p, mem_sz: 0x%08lx\n",
1223             loadinfo->base, loadinfo->memsize);
1224     DEBUG_F("    wanted load base: 0x%08lx, mem_sz: 0x%08lx\n",
1225             loadaddr, loadinfo->memsize);
1226
1227     /* Load the program segments... */
1228     p = ph;
1229     for (i = 0; i < e->e_phnum; ++i, ++p) {
1230             unsigned long offset;
1231             if (p->p_type != PT_LOAD || p->p_offset == 0)
1232                     continue;
1233
1234             /* Now, we skip to the image itself */
1235             if ((*(file->fs->seek))(file, p->p_offset) != FILE_ERR_OK) {
1236                     prom_printf ("Seek error\n");
1237                     prom_release(loadinfo->base, loadinfo->memsize);
1238                     return 0;
1239             }
1240             offset = p->p_vaddr - loadinfo->load_loc;
1241             if ((*(file->fs->read))(file, p->p_filesz, loadinfo->base+offset) != p->p_filesz) {
1242                     prom_printf ("Read failed\n");
1243                     prom_release(loadinfo->base, loadinfo->memsize);
1244                     return 0;
1245             }
1246     }
1247
1248     free(ph);
1249     
1250     /* Return success at loading the Elf64 kernel */
1251     return 1;
1252 }
1253
1254 static int
1255 is_elf32(loadinfo_t *loadinfo)
1256 {
1257         Elf32_Ehdr *e = &(loadinfo->elf.elf32hdr);
1258
1259         return (e->e_ident[EI_MAG0]  == ELFMAG0     &&
1260                 e->e_ident[EI_MAG1]  == ELFMAG1     &&
1261                 e->e_ident[EI_MAG2]  == ELFMAG2     &&
1262                 e->e_ident[EI_MAG3]  == ELFMAG3     &&
1263                 e->e_ident[EI_CLASS] == ELFCLASS32  &&
1264                 e->e_ident[EI_DATA]  == ELFDATA2MSB &&
1265                 e->e_type            == ET_EXEC     &&
1266                 e->e_machine         == EM_PPC);
1267 }
1268
1269 static int
1270 is_elf64(loadinfo_t *loadinfo)
1271 {
1272         Elf64_Ehdr *e = &(loadinfo->elf.elf64hdr);
1273
1274         return (e->e_ident[EI_MAG0]  == ELFMAG0     &&
1275                 e->e_ident[EI_MAG1]  == ELFMAG1     &&
1276                 e->e_ident[EI_MAG2]  == ELFMAG2     &&
1277                 e->e_ident[EI_MAG3]  == ELFMAG3     &&
1278                 e->e_ident[EI_CLASS] == ELFCLASS64  &&
1279                 e->e_ident[EI_DATA]  == ELFDATA2MSB &&
1280                 e->e_type            == ET_EXEC     &&
1281                 e->e_machine         == EM_PPC64);
1282 }
1283
1284 static void
1285 setup_display(void)
1286 {
1287 #ifdef CONFIG_SET_COLORMAP
1288         static unsigned char default_colors[] = {
1289                 0x00, 0x00, 0x00,
1290                 0x00, 0x00, 0xaa,
1291                 0x00, 0xaa, 0x00,
1292                 0x00, 0xaa, 0xaa,
1293                 0xaa, 0x00, 0x00,
1294                 0xaa, 0x00, 0xaa,
1295                 0xaa, 0x55, 0x00,
1296                 0xaa, 0xaa, 0xaa,
1297                 0x55, 0x55, 0x55,
1298                 0x55, 0x55, 0xff,
1299                 0x55, 0xff, 0x55,
1300                 0x55, 0xff, 0xff,
1301                 0xff, 0x55, 0x55,
1302                 0xff, 0x55, 0xff,
1303                 0xff, 0xff, 0x55,
1304                 0xff, 0xff, 0xff
1305         };
1306         int i, result;
1307         prom_handle scrn = PROM_INVALID_HANDLE;
1308
1309         /* Try Apple's mac-boot screen ihandle */
1310         result = (int)call_prom_return("interpret", 1, 2,
1311                 "\" _screen-ihandle\" $find if execute else 0 then", &scrn);
1312         DEBUG_F("Trying to get screen ihandle, result: %d, scrn: %p\n", result, scrn);
1313
1314         if (scrn == 0 || scrn == PROM_INVALID_HANDLE) {
1315                 char type[32];
1316                 /* Hrm... check to see if stdout is a display */
1317                 scrn = call_prom ("instance-to-package", 1, 1, prom_stdout);
1318                 DEBUG_F("instance-to-package of stdout is: %p\n", scrn);
1319                 if (prom_getprop(scrn, "device_type", type, 32) > 0 && !strncmp(type, "display", 7)) {
1320                         DEBUG_F("got it ! stdout is a screen\n");
1321                         scrn = prom_stdout;
1322                 } else {
1323                         /* Else, we try to open the package */
1324                         scrn = (prom_handle)call_prom( "open", 1, 1, "screen" );
1325                         DEBUG_F("Open screen result: %p\n", scrn);
1326                 }
1327         }
1328         
1329         if (scrn == PROM_INVALID_HANDLE) {
1330                 prom_printf("No screen device found !/n");
1331                 return;
1332         }
1333         for(i=0;i<16;i++) {
1334                 prom_set_color(scrn, i, default_colors[i*3],
1335                         default_colors[i*3+1], default_colors[i*3+2]);
1336         }
1337         prom_printf("\x1b[1;37m\x1b[2;40m");    
1338 #ifdef COLOR_TEST
1339         for (i=0;i<16; i++) {
1340                 prom_printf("\x1b[%d;%dm\x1b[1;47m%s \x1b[2;40m %s\n",
1341                         ansi_color_table[i].index,
1342                         ansi_color_table[i].value,
1343                         ansi_color_table[i].name,
1344                         ansi_color_table[i].name);
1345                 prom_printf("\x1b[%d;%dm\x1b[1;37m%s \x1b[2;30m %s\n",
1346                         ansi_color_table[i].index,
1347                         ansi_color_table[i].value+10,
1348                         ansi_color_table[i].name,
1349                         ansi_color_table[i].name);
1350         }
1351         prom_printf("\x1b[1;37m\x1b[2;40m");    
1352 #endif /* COLOR_TEST */
1353
1354 #if !DEBUG
1355         prom_printf("\xc");
1356 #endif /* !DEBUG */
1357
1358 #endif /* CONFIG_SET_COLORMAP */
1359 }
1360
1361 int
1362 yaboot_main(void)
1363 {
1364         if (_machine == _MACH_Pmac)
1365                 setup_display();
1366         
1367         prom_get_chosen("bootpath", bootdevice, sizeof(bootdevice));
1368         DEBUG_F("/chosen/bootpath = %s\n", bootdevice);
1369         if (bootdevice[0] == 0)
1370                 prom_get_options("boot-device", bootdevice, sizeof(bootdevice));
1371         if (bootdevice[0] == 0) {
1372             prom_printf("Couldn't determine boot device\n");
1373             return -1;
1374         }
1375
1376         if (!parse_device_path(bootdevice, (_machine == _MACH_Pmac) ? "hd" : "disc",
1377                                -1, "", &boot)) {
1378              prom_printf("%s: Unable to parse\n", bootdevice);
1379              return -1;
1380         }
1381         DEBUG_F("After parse_device_path: dev=%s, part=%d, file=%s\n",
1382                 boot.dev, boot.part, boot.file);
1383
1384         if (strlen(boot.file)) {
1385              if (!strncmp(boot.file, "\\\\", 2))
1386                   boot.file = "\\\\";
1387              else {
1388                   char *p, *last;
1389                   p = last = boot.file;
1390                   while(*p) {
1391                        if (*p == '\\')
1392                             last = p;
1393                        p++;
1394                   }
1395                   if (p)
1396                        *(last) = 0;
1397                   else
1398                        boot.file = "";
1399                   if (strlen(boot.file))
1400                        strcat(boot.file, "\\");
1401              }
1402         }
1403         DEBUG_F("After path fixup: dev=%s, part=%d, file=%s\n",
1404                 boot.dev, boot.part, boot.file);
1405
1406         useconf = load_config_file(boot.dev, boot.file, boot.part);
1407
1408         prom_printf("Welcome to yaboot version " VERSION "\n");
1409         prom_printf("Enter \"help\" to get some basic usage information\n");
1410         
1411         yaboot_text_ui();
1412         
1413         prom_printf("Bye.\n");
1414         return 0;
1415 }
1416 /* 
1417  * Local variables:
1418  * c-file-style: "K&R"
1419  * c-basic-offset: 5
1420  * End:
1421  */