727c72525b3d657c2bcdda0a6ef63f3ca9daedb7
[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"
659                "Note that the comma (,) is only required if you specify an OpenFirmware\n"
660                "device, if you only specify a filename you should not start it with a \",\"\n\n"
661                "If you omit \"device:\" and \"partno\" yaboot will use the values of \n"
662                "\"device=\" and \"partition=\" in yaboot.conf, right now those are set to: \n"
663                "device=%s\n"
664                "partition=%d\n\n", defdevice, defpart);
665           return 0;
666      }
667
668      if (!strcmp (imagename, "halt")) {
669           if (password)
670                check_password ("P");
671           prom_pause();
672           return 0;
673      }
674      if (!strcmp (imagename, "bye")) {
675           if (password) {
676                check_password ("P");
677                return 1;
678           }
679           return 1; 
680      }
681
682      if (imagename[0] == '$') {
683           /* forth command string */
684           if (password)
685                check_password ("P");
686           prom_interpret(imagename+1);
687           return 0;
688      }
689
690      strncpy(imagepath, imagename, 1024);
691
692      if (!label && password)
693           check_password ("To boot a custom image you must enter the p");
694
695      if (!parse_device_path(imagepath, defdevice, defpart,
696                             "/vmlinux", &params->kernel)) {
697           prom_printf("%s: Unable to parse\n", imagepath);
698           return 0;
699      }
700      DEBUG_F("after parse_device_path: dev=%s part=%d file=%s\n", params->kernel.dev,
701              params->kernel.part, params->kernel.file);
702
703      if (useconf) {
704           p = cfg_get_strg(label, "initrd");
705           if (p && *p) {
706                DEBUG_F("Parsing initrd path <%s>\n", p);
707                strncpy(initrdpath, p, 1024);
708                if (!parse_device_path(initrdpath, defdevice, defpart,
709                                       "/root.bin", &params->rd)) {
710                     prom_printf("%s: Unable to parse\n", imagepath);
711                     return 0;
712                }
713           }
714           p = cfg_get_strg(label, "sysmap");
715           if (p && *p) {
716                DEBUG_F("Parsing sysmap path <%s>\n", p);
717                strncpy(sysmappath, p, 1024);
718                if (!parse_device_path(sysmappath, defdevice, defpart,
719                                       "/boot/System.map", &params->sysmap)) {
720                     prom_printf("%s: Unable to parse\n", imagepath);
721                     return 0;
722                }
723           }
724      }
725      return 0;
726 }
727
728 /* This is derived from quik core. To be changed to first parse the headers
729  * doing lazy-loading, and then claim the memory before loading the kernel
730  * to it
731  * We also need to add initrd support to this whole mecanism
732  */
733 void
734 yaboot_text_ui(void)
735 {
736 #define MAX_HEADERS     32
737
738      struct boot_file_t file;
739      int                        result;
740      static struct boot_param_t params;
741      void               *initrd_base;
742      unsigned long      initrd_size;
743      void                *sysmap_base;
744      unsigned long      sysmap_size;
745      kernel_entry_t      kernel_entry;
746      struct bi_record*  birec;
747      char*               loc=NULL;
748      loadinfo_t          loadinfo;
749      void                *initrd_more,*initrd_want;
750      unsigned long       initrd_read;
751     
752      loadinfo.load_loc = 0;
753
754      for (;;) {
755           initrd_size = 0;
756           initrd_base = 0;
757           sysmap_base = 0;
758           sysmap_size = 0;
759         
760           if (get_params(&params))
761                return;
762           if (!params.kernel.file)
763                continue;
764         
765           prom_printf("Please wait, loading kernel...\n");
766
767           memset(&file, 0, sizeof(file));
768
769           if (strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.kernel.file[0] != '/'
770               && params.kernel.file[0] != '\\') {
771                loc=(char*)malloc(strlen(params.kernel.file)+3);
772                if (!loc) {
773                     prom_printf ("malloc error\n");
774                     goto next;
775                }
776                strcpy(loc,boot.file);
777                strcat(loc,params.kernel.file);
778                free(params.kernel.file);
779                params.kernel.file=loc;
780           }
781           result = open_file(&params.kernel, &file);
782           if (result != FILE_ERR_OK) {
783                prom_printf("%s:%d,", params.kernel.dev, params.kernel.part);
784                prom_perror(result, params.kernel.file);
785                goto next;
786           }
787
788           /* Read the Elf e_ident, e_type and e_machine fields to
789            * determine Elf file type
790            */
791           if (file.fs->read(&file, sizeof(Elf_Ident), &loadinfo.elf) < sizeof(Elf_Ident)) {
792                prom_printf("\nCan't read Elf e_ident/e_type/e_machine info\n");
793                file.fs->close(&file);
794                memset(&file, 0, sizeof(file));
795                goto next;
796           }
797
798           if (is_elf32(&loadinfo)) {
799                if (!load_elf32(&file, &loadinfo)) {
800                     file.fs->close(&file);
801                     memset(&file, 0, sizeof(file));
802                     goto next;
803                }
804                prom_printf("   Elf32 kernel loaded...\n");
805           } else if (is_elf64(&loadinfo)) {
806                if (!load_elf64(&file, &loadinfo)) {
807                     file.fs->close(&file);
808                     memset(&file, 0, sizeof(file));
809                     goto next;
810                }
811                prom_printf("   Elf64 kernel loaded...\n");
812           } else {
813                prom_printf ("%s: Not a valid ELF image\n", params.kernel.file);
814                file.fs->close(&file);
815                memset(&file, 0, sizeof(file));
816                goto next;
817           }
818           file.fs->close(&file);
819           memset(&file, 0, sizeof(file));
820
821           /* If sysmap, load it. 
822            */
823           if (params.sysmap.file) {
824                prom_printf("Loading System.map ...\n");
825                if(strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.sysmap.file[0] != '/'
826                   && params.sysmap.file[0] != '\\') {
827                     if (loc) free(loc);
828                     loc=(char*)malloc(strlen(params.sysmap.file)+3);
829                     if (!loc) {
830                          prom_printf ("malloc error\n");
831                          goto next;
832                     }
833                     strcpy(loc,boot.file);
834                     strcat(loc,params.sysmap.file);
835                     free(params.sysmap.file);
836                     params.sysmap.file=loc;
837                }
838              
839                result = open_file(&params.sysmap, &file);
840                if (result != FILE_ERR_OK) {
841                     prom_printf("%s:%d,", params.sysmap.dev, params.sysmap.part);
842                     prom_perror(result, params.sysmap.file);
843                }
844                else {
845                     sysmap_base = prom_claim(loadinfo.base+loadinfo.memsize, 0x100000, 0);
846                     if (sysmap_base == (void *)-1) {
847                          prom_printf("Claim failed for sysmap memory\n");
848                          sysmap_base = 0;
849                     } else {
850                          sysmap_size = file.fs->read(&file, 0xfffff, sysmap_base);
851                          if (sysmap_size == 0)
852                               sysmap_base = 0;
853                          else
854                               ((char *)sysmap_base)[sysmap_size++] = 0;
855                     }
856                     file.fs->close(&file);
857                     memset(&file, 0, sizeof(file));
858                }
859                if (sysmap_base) {
860                     prom_printf("System.map loaded at %p, size: %lu Kbytes\n",
861                                 sysmap_base, sysmap_size >> 10);
862                     loadinfo.memsize += _ALIGN(0x100000, 0x1000);
863                } else {
864                     prom_printf("System.map load failed !\n");
865                     prom_pause();
866                }
867           }
868
869           /* If ramdisk, load it. For now, we can't tell the size it will be
870            * so we claim an arbitrary amount of 4Mb
871            */
872           if (params.rd.file) {
873                if(strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.rd.file[0] != '/'
874                   && params.kernel.file[0] != '\\')
875                {
876                     if (loc) free(loc);
877                     loc=(char*)malloc(strlen(params.rd.file)+3);
878                     if (!loc) {
879                          prom_printf ("Malloc error\n");
880                          goto next;
881                     }
882                     strcpy(loc,boot.file);
883                     strcat(loc,params.rd.file);
884                     free(params.rd.file);
885                     params.rd.file=loc;
886                }
887                prom_printf("Loading ramdisk...\n");
888                result = open_file(&params.rd, &file);
889                if (result != FILE_ERR_OK) {
890                     prom_printf("%s:%d,", params.rd.dev, params.rd.part);
891                     prom_perror(result, params.rd.file);
892                }
893                else {
894 #define INITRD_CHUNKSIZE 0x400000
895                     initrd_base = prom_claim(loadinfo.base+loadinfo.memsize, INITRD_CHUNKSIZE, 0);
896                     if (initrd_base == (void *)-1) {
897                          prom_printf("Claim failed for initrd memory\n");
898                          initrd_base = 0;
899                     } else {
900                          initrd_size = file.fs->read(&file, INITRD_CHUNKSIZE, initrd_base);
901                          if (initrd_size == 0)
902                               initrd_base = 0;
903                          initrd_read = initrd_size;
904                          initrd_more = initrd_base;
905                          while (initrd_read == INITRD_CHUNKSIZE ) { /* need to read more? */
906                               initrd_want = (void *)((unsigned long)initrd_more+INITRD_CHUNKSIZE);
907                               initrd_more = prom_claim(initrd_want, INITRD_CHUNKSIZE, 0);
908                               if (initrd_more != initrd_want) {
909                                    prom_printf("Claim failed for initrd memory at %p rc=%p\n",initrd_want,initrd_more);
910                                    break;
911                               }
912                               initrd_read = file.fs->read(&file, INITRD_CHUNKSIZE, initrd_more);
913                               DEBUG_F("  block at %p rc=%lu\n",initrd_more,initrd_read);
914                               initrd_size += initrd_read;
915                          }
916                     }
917                     file.fs->close(&file);
918                     memset(&file, 0, sizeof(file));
919                }
920                if (initrd_base)
921                     prom_printf("ramdisk loaded at %p, size: %lu Kbytes\n",
922                                 initrd_base, initrd_size >> 10);
923                else {
924                     prom_printf("ramdisk load failed !\n");
925                     prom_pause();
926                }
927           }
928
929           DEBUG_F("setting kernel args to: %s\n", params.args);
930           prom_setargs(params.args);
931           DEBUG_F("flushing icache...");
932           flush_icache_range ((long)loadinfo.base, (long)loadinfo.base+loadinfo.memsize);
933           DEBUG_F(" done\n");
934
935 /* 
936  * Fill mew boot infos
937  *
938  * The birec is low on memory, probably inside the malloc pool, so
939  * we don't write it earlier. At this point, we should not use anything
940  * coming from the malloc pool
941  */
942           birec = (struct bi_record *)_ALIGN(loadinfo.filesize+(1<<20)-1,(1<<20));
943
944 /* We make sure it's mapped. We map only 64k for now, it's plenty enough
945  * we don't claim since this precise memory range may already be claimed
946  * by the malloc pool
947  */
948           prom_map (birec, birec, 0x10000);
949           DEBUG_F("birec at %p\n", birec);
950           DEBUG_SLEEP;
951
952           birec->tag = BI_FIRST;
953           birec->size = sizeof(struct bi_record);
954           birec = (struct bi_record *)((unsigned long)birec + birec->size);
955         
956           birec->tag = BI_BOOTLOADER_ID;
957           sprintf( (char *)birec->data, "yaboot");
958           birec->size = sizeof(struct bi_record) + strlen("yaboot") + 1;
959           birec = (struct bi_record *)((unsigned long)birec + birec->size);
960         
961           birec->tag = BI_MACHTYPE;
962           birec->data[0] = _machine;
963           birec->size = sizeof(struct bi_record) + sizeof(unsigned long);
964           birec = (struct bi_record *)((unsigned long)birec + birec->size);
965
966           if (sysmap_base) {
967                birec->tag = BI_SYSMAP;
968                birec->data[0] = (unsigned long)sysmap_base;
969                birec->data[1] = sysmap_size;
970                birec->size = sizeof(struct bi_record) + sizeof(unsigned long)*2;
971                birec = (struct bi_record *)((unsigned long)birec + birec->size);
972           }
973           birec->tag = BI_LAST;
974           birec->size = sizeof(struct bi_record);
975           birec = (struct bi_record *)((unsigned long)birec + birec->size);
976
977           /* compute the kernel's entry point. */
978           kernel_entry = loadinfo.base + loadinfo.entry - loadinfo.load_loc;
979
980           DEBUG_F("Kernel entry point = %p\n", kernel_entry);
981           DEBUG_F("kernel: arg1 = %p,\n"
982                   "        arg2 = 0x%08lx,\n"
983                   "        prom = %p,\n"
984                   "        arg4 = %d,\n"
985                   "        arg5 = %d\n\n",
986                   initrd_base + loadinfo.load_loc, initrd_size, prom, 0, 0);
987
988           DEBUG_F("Entering kernel...\n");
989
990           /* call the kernel with our stack. */
991           kernel_entry(initrd_base + loadinfo.load_loc, initrd_size, prom, 0, 0);
992           continue;
993      next:
994           ; /* do nothing */
995      }
996 }
997
998 static int
999 load_elf32(struct boot_file_t *file, loadinfo_t *loadinfo)
1000 {
1001      int                        i;
1002      Elf32_Ehdr         *e = &(loadinfo->elf.elf32hdr);
1003      Elf32_Phdr         *p, *ph;
1004      int                        size = sizeof(Elf32_Ehdr) - sizeof(Elf_Ident);
1005      unsigned long      addr, loadaddr;
1006
1007      /* Read the rest of the Elf header... */
1008      if ((*(file->fs->read))(file, size, &e->e_version) < size) {
1009           prom_printf("\nCan't read Elf32 image header\n");
1010           return 0;
1011      }
1012
1013      DEBUG_F("Elf32 header:\n");
1014      DEBUG_F(" e.e_type      = %d\n", (int)e->e_type);
1015      DEBUG_F(" e.e_machine   = %d\n", (int)e->e_machine);
1016      DEBUG_F(" e.e_version   = %d\n", (int)e->e_version);
1017      DEBUG_F(" e.e_entry     = 0x%08x\n", (int)e->e_entry);
1018      DEBUG_F(" e.e_phoff     = 0x%08x\n", (int)e->e_phoff);
1019      DEBUG_F(" e.e_shoff     = 0x%08x\n", (int)e->e_shoff);
1020      DEBUG_F(" e.e_flags     = %d\n", (int)e->e_flags);
1021      DEBUG_F(" e.e_ehsize    = 0x%08x\n", (int)e->e_ehsize);
1022      DEBUG_F(" e.e_phentsize = 0x%08x\n", (int)e->e_phentsize);
1023      DEBUG_F(" e.e_phnum     = %d\n", (int)e->e_phnum);
1024
1025      loadinfo->entry = e->e_entry;
1026
1027      if (e->e_phnum > MAX_HEADERS) {
1028           prom_printf ("Can only load kernels with one program header\n");
1029           return 0;
1030      }
1031
1032      ph = (Elf32_Phdr *)malloc(sizeof(Elf32_Phdr) * e->e_phnum);
1033      if (!ph) {
1034           prom_printf ("Malloc error\n");
1035           return 0;
1036      }
1037
1038      /* Now, we read the section header */
1039      if ((*(file->fs->seek))(file, e->e_phoff) != FILE_ERR_OK) {
1040           prom_printf ("seek error\n");
1041           return 0;
1042      }
1043      if ((*(file->fs->read))(file, sizeof(Elf32_Phdr) * e->e_phnum, ph) !=
1044          sizeof(Elf32_Phdr) * e->e_phnum) {
1045           prom_printf ("read error\n");
1046           return 0;
1047      }
1048
1049      /* Scan through the program header
1050       * HACK:  We must return the _memory size of the kernel image, not the
1051       *        file size (because we have to leave room before other boot
1052       *   infos. This code works as a side effect of the fact that
1053       *   we have one section and vaddr == p_paddr
1054       */
1055      loadinfo->memsize = loadinfo->filesize = loadinfo->offset = 0;
1056      p = ph;
1057      for (i = 0; i < e->e_phnum; ++i, ++p) {
1058           if (p->p_type != PT_LOAD || p->p_offset == 0)
1059                continue;
1060           if (loadinfo->memsize == 0) {
1061                loadinfo->offset = p->p_offset;
1062                loadinfo->memsize = p->p_memsz;
1063                loadinfo->filesize = p->p_filesz;
1064                loadinfo->load_loc = p->p_vaddr;
1065           } else {
1066                loadinfo->memsize = p->p_offset + p->p_memsz - loadinfo->offset; /* XXX Bogus */
1067                loadinfo->filesize = p->p_offset + p->p_filesz - loadinfo->offset;
1068           }
1069      }
1070
1071      if (loadinfo->memsize == 0) {
1072           prom_printf("Can't find a loadable segment !\n");
1073           return 0;
1074      }
1075
1076      /* leave some room (1Mb) for boot infos */
1077      loadinfo->memsize = _ALIGN(loadinfo->memsize,(1<<20)) + 0x100000;
1078      /* Claim OF memory */
1079      DEBUG_F("Before prom_claim, mem_sz: 0x%08lx\n", loadinfo->memsize);
1080
1081      /* On some systems, loadaddr may already be claimed, so try some
1082       * other nearby addresses before giving up.
1083       */
1084      loadaddr = (e->e_entry == KERNEL_LINK_ADDR_PPC32 ||
1085                  e->e_entry == 0) ? KERNELADDR : e->e_entry;
1086      for(addr=loadaddr; addr <= loadaddr * 8 ;addr+=0x100000) {
1087           loadinfo->base = prom_claim((void *)addr, loadinfo->memsize, 0);
1088           if (loadinfo->base != (void *)-1) break;
1089      }
1090      if (loadinfo->base == (void *)-1) {
1091           prom_printf("Claim error, can't allocate kernel memory\n");
1092           return 0;
1093      }  
1094
1095      DEBUG_F("After ELF parsing, load base: %p, mem_sz: 0x%08lx\n",
1096              loadinfo->base, loadinfo->memsize);
1097      DEBUG_F("    wanted load base: 0x%08lx, mem_sz: 0x%08lx\n",
1098              loadaddr, loadinfo->memsize);
1099
1100      /* Load the program segments... */
1101      p = ph;
1102      for (i = 0; i < e->e_phnum; ++i, ++p) {
1103           unsigned long offset;
1104           if (p->p_type != PT_LOAD || p->p_offset == 0)
1105                continue;
1106
1107           /* Now, we skip to the image itself */
1108           if ((*(file->fs->seek))(file, p->p_offset) != FILE_ERR_OK) {
1109                prom_printf ("Seek error\n");
1110                prom_release(loadinfo->base, loadinfo->memsize);
1111                return 0;
1112           }
1113           offset = p->p_vaddr - loadinfo->load_loc;
1114           if ((*(file->fs->read))(file, p->p_filesz, loadinfo->base+offset) != p->p_filesz) {
1115                prom_printf ("Read failed\n");
1116                prom_release(loadinfo->base, loadinfo->memsize);
1117                return 0;
1118           }
1119      }
1120
1121      free(ph);
1122     
1123      /* Return success at loading the Elf32 kernel */
1124      return 1;
1125 }
1126
1127 static int
1128 load_elf64(struct boot_file_t *file, loadinfo_t *loadinfo)
1129 {
1130      int                        i;
1131      Elf64_Ehdr         *e = &(loadinfo->elf.elf64hdr);
1132      Elf64_Phdr         *p, *ph;
1133      int                        size = sizeof(Elf64_Ehdr) - sizeof(Elf_Ident);
1134      unsigned long      addr, loadaddr;
1135
1136      /* Read the rest of the Elf header... */
1137      if ((*(file->fs->read))(file, size, &e->e_version) < size) {
1138           prom_printf("\nCan't read Elf64 image header\n");
1139           return 0;
1140      }
1141
1142      DEBUG_F("Elf64 header:\n");
1143      DEBUG_F(" e.e_type      = %d\n", (int)e->e_type);
1144      DEBUG_F(" e.e_machine   = %d\n", (int)e->e_machine);
1145      DEBUG_F(" e.e_version   = %d\n", (int)e->e_version);
1146      DEBUG_F(" e.e_entry     = 0x%016lx\n", (long)e->e_entry);
1147      DEBUG_F(" e.e_phoff     = 0x%016lx\n", (long)e->e_phoff);
1148      DEBUG_F(" e.e_shoff     = 0x%016lx\n", (long)e->e_shoff);
1149      DEBUG_F(" e.e_flags     = %d\n", (int)e->e_flags);
1150      DEBUG_F(" e.e_ehsize    = 0x%08x\n", (int)e->e_ehsize);
1151      DEBUG_F(" e.e_phentsize = 0x%08x\n", (int)e->e_phentsize);
1152      DEBUG_F(" e.e_phnum     = %d\n", (int)e->e_phnum);
1153
1154      loadinfo->entry = e->e_entry;
1155
1156      if (e->e_phnum > MAX_HEADERS) {
1157           prom_printf ("Can only load kernels with one program header\n");
1158           return 0;
1159      }
1160
1161      ph = (Elf64_Phdr *)malloc(sizeof(Elf64_Phdr) * e->e_phnum);
1162      if (!ph) {
1163           prom_printf ("Malloc error\n");
1164           return 0;
1165      }
1166
1167      /* Now, we read the section header */
1168      if ((*(file->fs->seek))(file, e->e_phoff) != FILE_ERR_OK) {
1169           prom_printf ("Seek error\n");
1170           return 0;
1171      }
1172      if ((*(file->fs->read))(file, sizeof(Elf64_Phdr) * e->e_phnum, ph) !=
1173          sizeof(Elf64_Phdr) * e->e_phnum) {
1174           prom_printf ("Read error\n");
1175           return 0;
1176      }
1177
1178      /* Scan through the program header
1179       * HACK:  We must return the _memory size of the kernel image, not the
1180       *        file size (because we have to leave room before other boot
1181       *   infos. This code works as a side effect of the fact that
1182       *   we have one section and vaddr == p_paddr
1183       */
1184      loadinfo->memsize = loadinfo->filesize = loadinfo->offset = 0;
1185      p = ph;
1186      for (i = 0; i < e->e_phnum; ++i, ++p) {
1187           if (p->p_type != PT_LOAD || p->p_offset == 0)
1188                continue;
1189           if (loadinfo->memsize == 0) {
1190                loadinfo->offset = p->p_offset;
1191                loadinfo->memsize = p->p_memsz;
1192                loadinfo->filesize = p->p_filesz;
1193                loadinfo->load_loc = p->p_vaddr;
1194           } else {
1195                loadinfo->memsize = p->p_offset + p->p_memsz - loadinfo->offset; /* XXX Bogus */
1196                loadinfo->filesize = p->p_offset + p->p_filesz - loadinfo->offset;
1197           }
1198      }
1199
1200      if (loadinfo->memsize == 0) {
1201           prom_printf("Can't find a loadable segment !\n");
1202           return 0;
1203      }
1204
1205      /* leave some room (1Mb) for boot infos */
1206      loadinfo->memsize = _ALIGN(loadinfo->memsize,(1<<20)) + 0x100000;
1207      /* Claim OF memory */
1208      DEBUG_F("Before prom_claim, mem_sz: 0x%08lx\n", loadinfo->memsize);
1209
1210      /* On some systems, loadaddr may already be claimed, so try some
1211       * other nearby addresses before giving up.
1212       */
1213      loadaddr = (e->e_entry == KERNEL_LINK_ADDR_PPC64) ? KERNELADDR : e->e_entry;
1214      for(addr=loadaddr; addr <= loadaddr * 8 ;addr+=0x100000) {
1215           loadinfo->base = prom_claim((void *)addr, loadinfo->memsize, 0);
1216           if (loadinfo->base != (void *)-1) break;
1217      }
1218      if (loadinfo->base == (void *)-1) {
1219           prom_printf("Claim error, can't allocate kernel memory\n");
1220           return 0;
1221      }  
1222
1223      DEBUG_F("After ELF parsing, load base: %p, mem_sz: 0x%08lx\n",
1224              loadinfo->base, loadinfo->memsize);
1225      DEBUG_F("    wanted load base: 0x%08lx, mem_sz: 0x%08lx\n",
1226              loadaddr, loadinfo->memsize);
1227
1228      /* Load the program segments... */
1229      p = ph;
1230      for (i = 0; i < e->e_phnum; ++i, ++p) {
1231           unsigned long offset;
1232           if (p->p_type != PT_LOAD || p->p_offset == 0)
1233                continue;
1234
1235           /* Now, we skip to the image itself */
1236           if ((*(file->fs->seek))(file, p->p_offset) != FILE_ERR_OK) {
1237                prom_printf ("Seek error\n");
1238                prom_release(loadinfo->base, loadinfo->memsize);
1239                return 0;
1240           }
1241           offset = p->p_vaddr - loadinfo->load_loc;
1242           if ((*(file->fs->read))(file, p->p_filesz, loadinfo->base+offset) != p->p_filesz) {
1243                prom_printf ("Read failed\n");
1244                prom_release(loadinfo->base, loadinfo->memsize);
1245                return 0;
1246           }
1247      }
1248
1249      free(ph);
1250     
1251      /* Return success at loading the Elf64 kernel */
1252      return 1;
1253 }
1254
1255 static int
1256 is_elf32(loadinfo_t *loadinfo)
1257 {
1258      Elf32_Ehdr *e = &(loadinfo->elf.elf32hdr);
1259
1260      return (e->e_ident[EI_MAG0]  == ELFMAG0        &&
1261              e->e_ident[EI_MAG1]  == ELFMAG1        &&
1262              e->e_ident[EI_MAG2]  == ELFMAG2        &&
1263              e->e_ident[EI_MAG3]  == ELFMAG3        &&
1264              e->e_ident[EI_CLASS] == ELFCLASS32  &&
1265              e->e_ident[EI_DATA]  == ELFDATA2MSB &&
1266              e->e_type            == ET_EXEC        &&
1267              e->e_machine         == EM_PPC);
1268 }
1269
1270 static int
1271 is_elf64(loadinfo_t *loadinfo)
1272 {
1273      Elf64_Ehdr *e = &(loadinfo->elf.elf64hdr);
1274
1275      return (e->e_ident[EI_MAG0]  == ELFMAG0        &&
1276              e->e_ident[EI_MAG1]  == ELFMAG1        &&
1277              e->e_ident[EI_MAG2]  == ELFMAG2        &&
1278              e->e_ident[EI_MAG3]  == ELFMAG3        &&
1279              e->e_ident[EI_CLASS] == ELFCLASS64  &&
1280              e->e_ident[EI_DATA]  == ELFDATA2MSB &&
1281              e->e_type            == ET_EXEC        &&
1282              e->e_machine         == EM_PPC64);
1283 }
1284
1285 static void
1286 setup_display(void)
1287 {
1288 #ifdef CONFIG_SET_COLORMAP
1289      static unsigned char default_colors[] = {
1290           0x00, 0x00, 0x00,
1291           0x00, 0x00, 0xaa,
1292           0x00, 0xaa, 0x00,
1293           0x00, 0xaa, 0xaa,
1294           0xaa, 0x00, 0x00,
1295           0xaa, 0x00, 0xaa,
1296           0xaa, 0x55, 0x00,
1297           0xaa, 0xaa, 0xaa,
1298           0x55, 0x55, 0x55,
1299           0x55, 0x55, 0xff,
1300           0x55, 0xff, 0x55,
1301           0x55, 0xff, 0xff,
1302           0xff, 0x55, 0x55,
1303           0xff, 0x55, 0xff,
1304           0xff, 0xff, 0x55,
1305           0xff, 0xff, 0xff
1306      };
1307      int i, result;
1308      prom_handle scrn = PROM_INVALID_HANDLE;
1309
1310      /* Try Apple's mac-boot screen ihandle */
1311      result = (int)call_prom_return("interpret", 1, 2,
1312                                     "\" _screen-ihandle\" $find if execute else 0 then", &scrn);
1313      DEBUG_F("Trying to get screen ihandle, result: %d, scrn: %p\n", result, scrn);
1314
1315      if (scrn == 0 || scrn == PROM_INVALID_HANDLE) {
1316           char type[32];
1317           /* Hrm... check to see if stdout is a display */
1318           scrn = call_prom ("instance-to-package", 1, 1, prom_stdout);
1319           DEBUG_F("instance-to-package of stdout is: %p\n", scrn);
1320           if (prom_getprop(scrn, "device_type", type, 32) > 0 && !strncmp(type, "display", 7)) {
1321                DEBUG_F("got it ! stdout is a screen\n");
1322                scrn = prom_stdout;
1323           } else {
1324                /* Else, we try to open the package */
1325                scrn = (prom_handle)call_prom( "open", 1, 1, "screen" );
1326                DEBUG_F("Open screen result: %p\n", scrn);
1327           }
1328      }
1329         
1330      if (scrn == PROM_INVALID_HANDLE) {
1331           prom_printf("No screen device found !/n");
1332           return;
1333      }
1334      for(i=0;i<16;i++) {
1335           prom_set_color(scrn, i, default_colors[i*3],
1336                          default_colors[i*3+1], default_colors[i*3+2]);
1337      }
1338      prom_printf("\x1b[1;37m\x1b[2;40m");       
1339 #ifdef COLOR_TEST
1340      for (i=0;i<16; i++) {
1341           prom_printf("\x1b[%d;%dm\x1b[1;47m%s \x1b[2;40m %s\n",
1342                       ansi_color_table[i].index,
1343                       ansi_color_table[i].value,
1344                       ansi_color_table[i].name,
1345                       ansi_color_table[i].name);
1346           prom_printf("\x1b[%d;%dm\x1b[1;37m%s \x1b[2;30m %s\n",
1347                       ansi_color_table[i].index,
1348                       ansi_color_table[i].value+10,
1349                       ansi_color_table[i].name,
1350                       ansi_color_table[i].name);
1351      }
1352      prom_printf("\x1b[1;37m\x1b[2;40m");       
1353 #endif /* COLOR_TEST */
1354
1355 #if !DEBUG
1356      prom_printf("\xc");
1357 #endif /* !DEBUG */
1358
1359 #endif /* CONFIG_SET_COLORMAP */
1360 }
1361
1362 int
1363 yaboot_main(void)
1364 {
1365      char *ptype;
1366
1367      if (_machine == _MACH_Pmac)
1368           setup_display();
1369         
1370      prom_get_chosen("bootpath", bootdevice, sizeof(bootdevice));
1371      DEBUG_F("/chosen/bootpath = %s\n", bootdevice);
1372      if (bootdevice[0] == 0)
1373           prom_get_options("boot-device", bootdevice, sizeof(bootdevice));
1374      if (bootdevice[0] == 0) {
1375           prom_printf("Couldn't determine boot device\n");
1376           return -1;
1377      }
1378
1379      if (!parse_device_path(bootdevice, (_machine == _MACH_Pmac) ? "hd" : "disc",
1380                             -1, "", &boot)) {
1381           prom_printf("%s: Unable to parse\n", bootdevice);
1382           return -1;
1383      }
1384      DEBUG_F("After parse_device_path: dev=%s, part=%d, file=%s\n",
1385              boot.dev, boot.part, boot.file);
1386
1387      if (strlen(boot.file)) {
1388           if (!strncmp(boot.file, "\\\\", 2))
1389                boot.file = "\\\\";
1390           else {
1391                char *p, *last;
1392                p = last = boot.file;
1393                while(*p) {
1394                     if (*p == '\\')
1395                          last = p;
1396                     p++;
1397                }
1398                if (p)
1399                     *(last) = 0;
1400                else
1401                     boot.file = "";
1402                if (strlen(boot.file))
1403                     strcat(boot.file, "\\");
1404           }
1405      }
1406      DEBUG_F("After path fixup: dev=%s, part=%d, file=%s\n",
1407              boot.dev, boot.part, boot.file);
1408
1409      useconf = load_config_file(boot.dev, boot.file, boot.part);
1410
1411      prom_printf("Welcome to yaboot version " VERSION "\n");
1412      prom_printf("Enter \"help\" to get some basic usage information\n");
1413
1414      /* I am fed up with lusers using the wrong partition type and
1415         mailing me *when* it breaks */
1416
1417      if (_machine == _MACH_Pmac) {
1418           char *entry = cfg_get_strg(0, "ptypewarning");
1419           int warn = 1;
1420           if (entry)
1421                warn = strcmp(entry,
1422                              "I_know_the_partition_type_is_wrong_and_will_NOT_send_mail_when_booting_breaks");
1423           if (warn) {
1424                ptype = get_part_type(boot.dev, boot.part);
1425                if ((ptype != NULL) && (strcmp(ptype, "Apple_Bootstrap")))
1426                     prom_printf("\nWARNING: Bootstrap partition type is wrong: \"%s\"\n"
1427                                 "         type should be: \"Apple_Bootstrap\"\n\n", ptype);
1428           }
1429      }
1430
1431      yaboot_text_ui();
1432         
1433      prom_printf("Bye.\n");
1434      return 0;
1435 }
1436
1437 /* 
1438  * Local variables:
1439  * c-file-style: "K&R"
1440  * c-basic-offset: 5
1441  * End:
1442  */