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