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