Importing mkelfimage from
[coreboot.git] / util / mkelfImage / linux-i386 / convert_params.c
1 #include <stdarg.h>
2 #include <limits.h>
3 #include "arch/io.h"
4 #include "stdint.h"
5 #include "uniform_boot.h"
6 #include "linuxbios_tables.h"
7 #include "elf_boot.h"
8 #include "convert.h"
9 #define STACK_SIZE (4096)
10
11 #define __unused __attribute__ ((unused))
12
13 long user_stack [STACK_SIZE] = { 0 };
14
15 unsigned long * stack_start = & user_stack[STACK_SIZE];
16
17 /* FIXME expand on drive_info_)struct... */
18 struct drive_info_struct { 
19         uint8_t dummy[32]; 
20 }; 
21 struct sys_desc_table {
22         uint16_t length;
23         uint8_t  table[318];
24 };
25
26 /*
27  * These are set up by the setup-routine at boot-time:
28  */
29
30 struct screen_info {
31         uint8_t  orig_x;                /* 0x00 */
32         uint8_t  orig_y;                /* 0x01 */
33         uint16_t dontuse1;              /* 0x02 -- EXT_MEM_K sits here */
34         uint16_t orig_video_page;       /* 0x04 */
35         uint8_t  orig_video_mode;       /* 0x06 */
36         uint8_t  orig_video_cols;       /* 0x07 */
37         uint16_t unused2;               /* 0x08 */
38         uint16_t orig_video_ega_bx;     /* 0x0a */
39         uint16_t unused3;               /* 0x0c */
40         uint8_t  orig_video_lines;      /* 0x0e */
41         uint8_t  orig_video_isVGA;      /* 0x0f */
42         uint16_t orig_video_points;     /* 0x10 */
43
44         /* VESA graphic mode -- linear frame buffer */
45         uint16_t lfb_width;             /* 0x12 */
46         uint16_t lfb_height;            /* 0x14 */
47         uint16_t lfb_depth;             /* 0x16 */
48         uint32_t lfb_base;              /* 0x18 */
49         uint32_t lfb_size;              /* 0x1c */
50         uint16_t dontuse2, dontuse3;    /* 0x20 -- CL_MAGIC and CL_OFFSET here */
51         uint16_t lfb_linelength;        /* 0x24 */
52         uint8_t  red_size;              /* 0x26 */
53         uint8_t  red_pos;               /* 0x27 */
54         uint8_t  green_size;            /* 0x28 */
55         uint8_t  green_pos;             /* 0x29 */
56         uint8_t  blue_size;             /* 0x2a */
57         uint8_t  blue_pos;              /* 0x2b */
58         uint8_t  rsvd_size;             /* 0x2c */
59         uint8_t  rsvd_pos;              /* 0x2d */
60         uint16_t vesapm_seg;            /* 0x2e */
61         uint16_t vesapm_off;            /* 0x30 */
62         uint16_t pages;                 /* 0x32 */
63 };
64
65
66 #define PAGE_SIZE 4096
67
68
69 #define E820MAP 0x2d0           /* our map */
70 #define E820MAX 32              /* number of entries in E820MAP */
71 #define E820NR  0x1e8           /* # entries in E820MAP */
72
73
74 struct e820entry {
75         unsigned long long addr;        /* start of memory segment */
76         unsigned long long size;        /* size of memory segment */
77         unsigned long type;             /* type of memory segment */
78 #define E820_RAM        1
79 #define E820_RESERVED   2
80 #define E820_ACPI       3 /* usable as RAM once ACPI tables have been read */
81 #define E820_NVS        4
82 };
83
84 struct e820map {
85     int nr_map;
86         struct e820entry map[E820MAX];
87 };
88
89
90 struct apm_bios_info {
91         uint16_t version;       /* 0x40 */
92         uint16_t cseg;          /* 0x42 */
93         uint32_t offset;        /* 0x44 */
94         uint16_t cseg_16;       /* 0x48 */
95         uint16_t dseg;          /* 0x4a */
96         uint16_t flags;         /* 0x4c */
97         uint16_t cseg_len;      /* 0x4e */
98         uint16_t cseg_16_len;   /* 0x50 */
99         uint16_t dseg_len;      /* 0x52 */
100         uint8_t  reserved[44];  /* 0x54 */
101 };
102
103
104 struct parameters {
105         uint8_t  orig_x;                        /* 0x00 */
106         uint8_t  orig_y;                        /* 0x01 */
107         uint16_t ext_mem_k;                     /* 0x02 -- EXT_MEM_K sits here */
108         uint16_t orig_video_page;               /* 0x04 */
109         uint8_t  orig_video_mode;               /* 0x06 */
110         uint8_t  orig_video_cols;               /* 0x07 */
111         uint16_t unused2;                       /* 0x08 */
112         uint16_t orig_video_ega_bx;             /* 0x0a */
113         uint16_t unused3;                       /* 0x0c */
114         uint8_t  orig_video_lines;              /* 0x0e */
115         uint8_t  orig_video_isVGA;              /* 0x0f */
116         uint16_t orig_video_points;             /* 0x10 */
117
118         /* VESA graphic mode -- linear frame buffer */
119         uint16_t lfb_width;                     /* 0x12 */
120         uint16_t lfb_height;                    /* 0x14 */
121         uint16_t lfb_depth;                     /* 0x16 */
122         uint32_t lfb_base;                      /* 0x18 */
123         uint32_t lfb_size;                      /* 0x1c */
124         uint16_t cl_magic;                      /* 0x20 */
125 #define CL_MAGIC_VALUE 0xA33F
126         uint16_t cl_offset;                     /* 0x22 */
127         uint16_t lfb_linelength;                /* 0x24 */
128         uint8_t  red_size;                      /* 0x26 */
129         uint8_t  red_pos;                       /* 0x27 */
130         uint8_t  green_size;                    /* 0x28 */
131         uint8_t  green_pos;                     /* 0x29 */
132         uint8_t  blue_size;                     /* 0x2a */
133         uint8_t  blue_pos;                      /* 0x2b */
134         uint8_t  rsvd_size;                     /* 0x2c */
135         uint8_t  rsvd_pos;                      /* 0x2d */
136         uint16_t vesapm_seg;                    /* 0x2e */
137         uint16_t vesapm_off;                    /* 0x30 */
138         uint16_t pages;                         /* 0x32 */
139         uint8_t  reserved4[12];                 /* 0x34 -- 0x3f reserved for future expansion */
140
141         struct apm_bios_info apm_bios_info;     /* 0x40 */
142         struct drive_info_struct drive_info;    /* 0x80 */
143         struct sys_desc_table sys_desc_table;   /* 0xa0 */
144         uint32_t alt_mem_k;                     /* 0x1e0 */
145         uint8_t  reserved5[4];                  /* 0x1e4 */
146         uint8_t  e820_map_nr;                   /* 0x1e8 */
147         uint8_t  reserved6[9];                  /* 0x1e9 */
148         uint16_t mount_root_rdonly;             /* 0x1f2 */
149         uint8_t  reserved7[4];                  /* 0x1f4 */
150         uint16_t ramdisk_flags;                 /* 0x1f8 */
151 #define RAMDISK_IMAGE_START_MASK        0x07FF
152 #define RAMDISK_PROMPT_FLAG             0x8000
153 #define RAMDISK_LOAD_FLAG               0x4000  
154         uint8_t  reserved8[2];                  /* 0x1fa */
155         uint16_t orig_root_dev;                 /* 0x1fc */
156         uint8_t  reserved9[1];                  /* 0x1fe */
157         uint8_t  aux_device_info;               /* 0x1ff */
158         uint8_t  reserved10[2];                 /* 0x200 */
159         uint8_t  param_block_signature[4];      /* 0x202 */
160         uint16_t param_block_version;           /* 0x206 */
161         uint8_t  reserved11[8];                 /* 0x208 */
162         uint8_t  loader_type;                   /* 0x210 */
163 #define LOADER_TYPE_LOADLIN         1
164 #define LOADER_TYPE_BOOTSECT_LOADER 2
165 #define LOADER_TYPE_SYSLINUX        3
166 #define LOADER_TYPE_ETHERBOOT       4
167 #define LOADER_TYPE_KERNEL          5
168         uint8_t  loader_flags;                  /* 0x211 */
169         uint8_t  reserved12[2];                 /* 0x212 */
170         uint32_t kernel_start;                  /* 0x214 */
171         uint32_t initrd_start;                  /* 0x218 */
172         uint32_t initrd_size;                   /* 0x21c */
173         uint8_t  reserved13[4];                 /* 0x220 */
174         /* 2.01+ */
175         uint16_t heap_end_ptr;                  /* 0x224 */
176         uint8_t  reserved14[2];                 /* 0x226 */
177         /* 2.02+ */
178         uint32_t cmd_line_ptr;                  /* 0x228 */
179         /* 2.03+ */
180         uint32_t initrd_addr_max;               /* 0x22c */
181         uint8_t  reserved15[0x2d0 - 0x230];     /* 0x230 */
182
183         struct e820entry e820_map[E820MAX];     /* 0x2d0 */
184         uint8_t  reserved16[688];               /* 0x550 */
185 #define COMMAND_LINE_SIZE 256
186         uint8_t  command_line[COMMAND_LINE_SIZE]; /* 0x800 */
187         uint8_t  reserved17[1792];              /* 0x900 - 0x1000 */
188 };
189
190 /* Keep track of which information I need to acquire. */
191 struct param_info {
192         unsigned type;
193         void *data;
194         Elf_Bhdr *param;
195         struct image_parameters *image;
196         struct parameters *real_mode;
197         /* bootloader type */
198         int has_multiboot;
199         int has_uniform_boot;
200         int has_elf_boot;
201         /* firmware type */
202         int has_pcbios;
203         int has_linuxbios;
204         struct lb_header *lb_table;
205         /* machine information needed */
206         int need_mem_sizes;
207 };
208 /*
209  * This is set up by the setup-routine at boot-time
210  */
211
212
213 #undef memcmp
214 #undef memset
215 #undef memcpy
216 #define memzero(s, n)     memset ((s), 0, (n))
217
218
219 /* FIXME handle systems with large EBDA's */
220 static struct parameters *faked_real_mode = (void *)REAL_MODE_DATA_LOC;
221
222
223
224 /*
225  * Output
226  * =============================================================================
227  */
228
229 /* Base Address */
230 #define TTYS0 0x3f8
231 #define TTYS0_LSR (TTYS0+0x05)
232 #define TTYS0_TBR (TTYS0+0x00)
233
234 static void ttys0_tx_byte(unsigned byte)
235 {
236         /* Wait until I can send a byte */
237         while((inb(TTYS0_LSR) & 0x20) == 0)
238                 ;
239         outb(byte, TTYS0_TBR);
240         /* Wait until the byte is transmitted */
241         while(!(inb(TTYS0_LSR) & 0x40))
242                 ;
243 }
244 static void put_char_serial(int c)
245 {
246         if (c == '\n') {
247                 ttys0_tx_byte('\r');
248         }
249         ttys0_tx_byte(c);
250 }
251
252 static void putchar(int c)
253 {
254 #if 0
255         put_char_video(c);
256 #endif
257         put_char_serial(c);
258 }
259
260 #define LONG_LONG_SHIFT  ((int)((sizeof(unsigned long long)*CHAR_BIT) - 4))
261 #define LONG_SHIFT  ((int)((sizeof(unsigned long)*CHAR_BIT) - 4))
262 #define INT_SHIFT   ((int)((sizeof(unsigned int)*CHAR_BIT) - 4))
263 #define SHRT_SHIFT  ((int)((sizeof(unsigned short)*CHAR_BIT) - 4))
264 #define CHAR_SHIFT  ((int)((sizeof(unsigned char)*CHAR_BIT) - 4))
265
266 /**************************************************************************
267 PRINTF and friends
268
269         Formats:
270                 %x      - 4 bytes int (8 hex digits, lower case)
271                 %X      - 4 bytes int (8 hex digits, upper case)
272                 %lx     - 8 bytes long (16 hex digits, lower case)
273                 %lX     - 8 bytes long (16 hex digits, upper case)
274                 %hx     - 2 bytes int (4 hex digits, lower case)
275                 %hX     - 2 bytes int (4 hex digits, upper case)
276                 %hhx    - 1 byte int (2 hex digits, lower case)
277                 %hhX    - 1 byte int (2 hex digits, upper case)
278                         - optional # prefixes 0x or 0X
279                 %d      - decimal int
280                 %c      - char
281                 %s      - string
282         Note: width specification not supported
283 **************************************************************************/
284 static void printf(const char *fmt, ...)
285 {
286         va_list args;
287         char *p;
288         va_start(args, fmt);
289         for ( ; *fmt != '\0'; ++fmt) {
290                 if (*fmt != '%') {
291                         putchar(*fmt);
292                         continue;
293                 }
294                 if (*++fmt == 's') {
295                         for(p = va_arg(args, char *); *p != '\0'; p++) 
296                                 putchar(*p);
297                 }
298                 else {  /* Length of item is bounded */
299                         char tmp[40], *q = tmp;
300                         int shift = INT_SHIFT;
301                         if (*fmt == 'L') {
302                                 shift = LONG_LONG_SHIFT;
303                                 fmt++;
304                         }
305                         else if (*fmt == 'l') {
306                                 shift = LONG_SHIFT;
307                                 fmt++;
308                         }
309                         else if (*fmt == 'h') {
310                                 shift = SHRT_SHIFT;
311                                 fmt++;
312                                 if (*fmt == 'h') {
313                                         shift = CHAR_SHIFT;
314                                         fmt++;
315                                 }
316                         }
317                         
318                         /*
319                          * Before each format q points to tmp buffer
320                          * After each format q points past end of item
321                          */
322                         if ((*fmt | 0x20) == 'x') {
323                                 /* With x86 gcc, sizeof(long) == sizeof(int) */
324                                 unsigned long long h;
325                                 int ncase;
326                                 if (shift > LONG_SHIFT) {
327                                         h = va_arg(args, unsigned long long);
328                                 }
329                                 else if (shift > INT_SHIFT) {
330                                         h = va_arg(args, unsigned long);
331                                 } else {
332                                         h = va_arg(args, unsigned int);
333                                 }
334                                 ncase = (*fmt & 0x20);
335                                 for ( ; shift >= 0; shift -= 4)
336                                         *q++ = "0123456789ABCDEF"[(h >> shift) & 0xF] | ncase;
337                         }
338                         else if (*fmt == 'd') {
339                                 char *r;
340                                 long i;
341                                 if (shift > LONG_SHIFT) {
342                                         i = va_arg(args, long long);
343                                 }
344                                 else if (shift > INT_SHIFT) {
345                                         i = va_arg(args, long);
346                                 } else {
347                                         i = va_arg(args, int);
348                                 }
349                                 if (i < 0) {
350                                         *q++ = '-';
351                                         i = -i;
352                                 }
353                                 p = q;          /* save beginning of digits */
354                                 do {
355                                         *q++ = '0' + (i % 10);
356                                         i /= 10;
357                                 } while (i);
358                                 /* reverse digits, stop in middle */
359                                 r = q;          /* don't alter q */
360                                 while (--r > p) {
361                                         i = *r;
362                                         *r = *p;
363                                         *p++ = i;
364                                 }
365                         }
366                         else if (*fmt == 'c')
367                                 *q++ = va_arg(args, int);
368                         else
369                                 *q++ = *fmt;
370                         /* now output the saved string */
371                         for (p = tmp; p < q; ++p)
372                                 putchar(*p);
373                 }
374         }
375         va_end(args);
376 }
377
378 /*
379  * String Functions 
380  * =============================================================================
381  */
382
383
384 size_t strnlen(const char *s, size_t max)
385 {
386         size_t len = 0;
387         while(len < max && *s) {
388                 len++;
389                 s++;
390         }
391         return len;
392 }
393
394 void* memset(void* s, int c, size_t n)
395 {
396         size_t i;
397         char *ss = (char*)s;
398
399         for (i=0;i<n;i++) ss[i] = c;
400         return s;
401 }
402
403 void* memcpy(void *dest, const void *src, size_t len)
404 {
405         size_t i;
406         unsigned char *d;
407         const unsigned char *s;
408         d = dest;
409         s = src;
410
411         for (i=0; i < len; i++) 
412                 d[i] = s[i];
413
414         return dest;
415 }
416
417 int memcmp(void *src1, void *src2, size_t len)
418 {
419         unsigned char *s1, *s2;
420         size_t i;
421         s1 = src1;
422         s2 = src2;
423         for(i = 0; i < len; i++) {
424                 if (*s1 != *s2) {
425                         return *s2 - *s1;
426                 }
427         }
428         return 0;
429         
430 }
431
432 /*
433  * Checksum functions
434  * =============================================================================
435  */
436
437
438 static unsigned long checksum_partial(unsigned long sum,
439         void *addr, unsigned long length)
440 {
441         uint8_t *ptr;
442         volatile union {
443                 uint8_t  byte[2];
444                 uint16_t word;
445         } value;
446         unsigned long i;
447         /* In the most straight forward way possible,
448          * compute an ip style checksum.
449          */
450         sum = 0;
451         ptr = addr;
452         for(i = 0; i < length; i++) {
453                 unsigned long value;
454                 value = ptr[i];
455                 if (i & 1) {
456                         value <<= 8;
457                 }
458                 /* Add the new value */
459                 sum += value;
460                 /* Wrap around the carry */
461                 if (sum > 0xFFFF) {
462                         sum = (sum + (sum >> 16)) & 0xFFFF;
463                 }
464         }
465         value.byte[0] = sum & 0xff;
466         value.byte[1] = (sum >> 8) & 0xff;
467         return value.word & 0xFFFF;
468
469 }
470
471 static unsigned long checksum_final(unsigned long partial)
472 {
473         return (~partial) & 0xFFFF;
474 }
475
476 static unsigned long compute_checksum(void *vaddr, unsigned long length)
477 {
478         return checksum_final(checksum_partial(0, vaddr, length));
479 }
480
481 /*
482  * Helper functions
483  * =============================================================================
484  */
485
486
487 void append_command_line(struct parameters *real_mode, char *arg, int arg_bytes)
488 {
489         int len, max;
490         char *dest;
491         /* skip over what has already been set */
492         len = strnlen(real_mode->command_line, sizeof(real_mode->command_line));
493         dest = real_mode->command_line + len;
494         max = sizeof(real_mode->command_line) - 1;
495         if (max < 1) {
496                 /* No room to append anything :( */
497                 return;
498         }
499         /* Add a space in between strings */
500         *dest++ = ' ';
501         /* Append the added command line */
502         max = sizeof(real_mode->command_line) - 1;
503         if (max > arg_bytes) {
504                 max = arg_bytes;
505         }
506         len = strnlen(arg, max);
507         memcpy(dest, arg, len);
508         dest += len;
509         /* Null terminate the string */
510         *dest++ = '\0';
511 }
512
513 static void set_memsize_k(struct parameters *real_mode, unsigned long mem_k) 
514 {
515         /* ALT_MEM_K maxes out at 4GB */
516         if (mem_k > 0x3fffff) {
517                 mem_k = 0x3fffff;
518         }
519         if (mem_k > (real_mode->alt_mem_k + (1 << 10))) {
520                 /* Use our memory size less 1M */
521                 real_mode->alt_mem_k = mem_k - (1 << 10);
522                 real_mode->ext_mem_k = mem_k - (1 << 10);
523                 if ((mem_k - (1 << 10)) > 0xFFFF) {
524                         real_mode->ext_mem_k = 0xFC00; /* 64 M */
525                 }
526         }
527 }
528
529 static void add_e820_map(struct parameters *real_mode,
530         unsigned long long addr, unsigned long long size, 
531         unsigned long type)
532 {
533         unsigned long long high;
534         unsigned long mem_k;
535         int i;
536         i = real_mode->e820_map_nr;
537         if (i < E820MAX) {
538                 real_mode->e820_map[i].addr = addr;
539                 real_mode->e820_map[i].size = size;
540                 real_mode->e820_map[i].type = type;
541                 real_mode->e820_map_nr++;
542         }
543         /* policy I assume that for the legacy memory
544          * variables memory is contiguous.
545          */
546         if (type == E820_RAM) {
547                 high = addr + size;
548                 if (high >= 0x40000000000ULL) {
549                         mem_k = 0xFFFFFFFF;
550                 } else {
551                         mem_k = high >> 10;
552                 }
553                 set_memsize_k(real_mode, mem_k);
554         }
555 }
556
557 /*
558  * Multiboot
559  * =============================================================================
560  */
561
562 #define MULTI_MEM_DEBUG 0
563 #if MULTI_MEM_DEBUG
564 #define multi_puts(x) printf("%s", x)
565 #define multi_put_hex(x) printf("%x", x)
566 #define multi_put_lhex(x) printf("%Lx", x)
567 #else
568 #define multi_puts(x)
569 #define multi_put_hex(x)
570 #define multi_put_lhex(x)
571 #endif /* MULTI_MEM_DEBUG */
572
573 /* Multiboot Specification */
574 struct multiboot_mods {
575         unsigned mod_start;
576         unsigned mod_end;
577         unsigned char *string;
578         unsigned reserved;
579 };
580
581 struct memory_segment {
582         unsigned long long addr;
583         unsigned long long size;
584         unsigned type;
585 };
586
587 struct multiboot_info {
588         unsigned flags;
589 #define MULTIBOOT_MEM_VALID       0x01
590 #define MULTIBOOT_BOOT_DEV_VALID  0x02
591 #define MULTIBOOT_CMDLINE_VALID   0x04
592 #define MULTIBOOT_MODS_VALID      0x08
593 #define MULTIBOOT_AOUT_SYMS_VALID 0x10
594 #define MULTIBOOT_ELF_SYMS_VALID  0x20
595 #define MULTIBOOT_MMAP_VALID      0x40
596         unsigned mem_lower;
597         unsigned mem_upper;
598         unsigned char boot_device[4];
599         void *command_line;
600         unsigned mods_count;
601         struct multiboot_mods *mods_addr;
602         unsigned syms_num;
603         unsigned syms_size;
604         unsigned syms_addr;
605         unsigned syms_shndx;
606         unsigned mmap_length;
607         struct memory_segment *mmap_addr;
608 };
609
610 #define MULTIBOOT_MAX_COMMAND_LINE 0xFFFFFFFF
611
612 static void convert_multiboot_memmap(
613         struct parameters *real_mode,
614         struct multiboot_info *info)
615 {
616         unsigned size;
617         unsigned *size_addr;
618 #define next_seg(seg, size) ((struct memory_segment *)((char *)(seg) + (size)))
619         struct memory_segment *seg, *end;
620
621         seg = info->mmap_addr;
622         end  = (void *)(((char *)seg) + info->mmap_length);
623         size_addr = (unsigned *)(((char *)seg) - 4);
624         size = *size_addr;
625         multi_puts("mmap_addr: "); multi_put_hex((unsigned)info->mmap_addr); multi_puts("\n");
626         multi_puts("mmap_length: "); multi_put_hex(info->mmap_length); multi_puts("\n");
627         multi_puts("size_addr: "); multi_put_hex((unsigned)size_addr); multi_puts("\n");
628         multi_puts("size: "); multi_put_hex(size); multi_puts("\n");
629         multi_puts("end: "); multi_put_hex((unsigned)end); multi_puts("\n");
630         for(seg = info->mmap_addr; (seg < end); seg = next_seg(seg,size)) {
631                 multi_puts("multi-mem: "); 
632                 multi_put_lhex(seg->size); 
633                 multi_puts(" @ ");
634                 multi_put_lhex(seg->addr);
635                 multi_puts(" (");
636                 switch(seg->type) {
637                 case E820_RAM:
638                         multi_puts("ram");
639                         break;
640                 case E820_ACPI:
641                         multi_puts("ACPI data");
642                         break;
643                 case E820_NVS:
644                         multi_puts("ACPI NVS");
645                         break;
646                 case E820_RESERVED:
647                 default:
648                         multi_puts("reserved");
649                         break;
650                 }
651                 multi_puts(")\n");
652                 add_e820_map(real_mode, seg->addr, seg->size, seg->type);
653         }
654 #undef next_seg
655 }
656
657 static void convert_multiboot(
658         struct param_info *info, struct multiboot_info *mb_info)
659 {
660         if (info->need_mem_sizes && (mb_info->flags & MULTIBOOT_MEM_VALID)) {
661                 /* info->memory is short 1M */
662                 set_memsize_k(info->real_mode, mb_info->mem_upper + (1 << 10));
663         }
664         if (mb_info->flags & MULTIBOOT_CMDLINE_VALID) {
665                 append_command_line(info->real_mode, mb_info->command_line, 
666                         MULTIBOOT_MAX_COMMAND_LINE);
667         }
668         if (info->need_mem_sizes && (mb_info->flags & MULTIBOOT_MMAP_VALID)) {
669                 convert_multiboot_memmap(info->real_mode, mb_info);
670         }
671         if (mb_info->flags & (MULTIBOOT_MEM_VALID | MULTIBOOT_MMAP_VALID)) {
672                 info->need_mem_sizes = 0;
673         }
674 }
675
676
677 /*
678  * Uniform Boot Environment
679  * =============================================================================
680  */
681
682 #define UBE_MEM_DEBUG 0
683 #if UBE_MEM_DEBUG
684 #define ube_puts(x) printf("%s", x)
685 #define ube_put_hex(x) printf("%x", x)
686 #define ube_put_lhex(x) printf("%Lx", x)
687 #else
688 #define ube_puts(x)
689 #define ube_put_hex(x)
690 #define ube_put_lhex(x)
691 #endif /* UBE_MEM_DEBUG */
692 static void convert_uniform_boot_memory(
693         struct parameters *real_mode, struct ube_memory *mem)
694 {
695         int i;
696         int entries;
697         unsigned long mem_k;
698         mem_k = 0;
699         entries = (mem->size - sizeof(*mem))/sizeof(mem->map[0]);
700         for(i = 0; (i < entries) && (i < E820MAX); i++) {
701                 unsigned long type;
702                 ube_puts("ube-mem: "); 
703                 ube_put_lhex(mem->map[i].size); 
704                 ube_puts(" @ ");
705                 ube_put_lhex(mem->map[i].start);
706                 ube_puts(" (");
707                 switch(mem->map[i].type) {
708                 case UBE_MEM_RAM:
709                         type = E820_RAM;
710                         ube_puts("ram");
711                         break;
712                 case UBE_MEM_ACPI:
713                         type = E820_ACPI;
714                         ube_puts("ACPI data");
715                         break;
716                 case UBE_MEM_NVS:
717                         type = E820_NVS;
718                         ube_puts("ACPI NVS");
719                         break;
720                 case UBE_MEM_RESERVED:
721                 default:
722                         type = E820_RESERVED;
723                         ube_puts("reserved");
724                         break;
725                 }
726                 ube_puts(")\n");
727                 add_e820_map(real_mode, 
728                         mem->map[i].start, mem->map[i].size, type);
729         }
730 }
731
732 static void convert_uniform_boot(struct param_info *info,
733         struct uniform_boot_header *header)
734 {
735         /* Uniform boot environment */
736         unsigned long env_bytes;
737         char *env;
738         if (header->arg_bytes) {
739                 append_command_line(info->real_mode, (void *)(header->arg), header->arg_bytes);
740         }
741         env = (void *)(header->env);
742         env_bytes = header->env_bytes;
743         while(env_bytes) {
744                 struct ube_record *record;
745                 record = (void *)env;
746                 if (record->tag == UBE_TAG_MEMORY) {
747                         if (info->need_mem_sizes) {
748                                 convert_uniform_boot_memory(info->real_mode, (void *)record);
749                                 info->need_mem_sizes = 0;
750                         }
751                 }
752                 env += record->size;
753                 env_bytes -= record->size;
754         }
755 }
756
757
758
759
760 /*
761  * Hardware
762  * =============================================================================
763  */
764
765 /* we're getting screwed again and again by this problem of the 8259. 
766  * so we're going to leave this lying around for inclusion into 
767  * crt0.S on an as-needed basis. 
768  * well, that went ok, I hope. Now we have to reprogram the interrupts :-(
769  * we put them right after the intel-reserved hardware interrupts, at
770  * int 0x20-0x2F. There they won't mess up anything. Sadly IBM really
771  * messed this up with the original PC, and they haven't been able to
772  * rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,
773  * which is used for the internal hardware interrupts as well. We just
774  * have to reprogram the 8259's, and it isn't fun.
775  */
776
777 static void setup_i8259(void)
778 {
779         outb(0x11, 0x20);               /*! initialization sequence to 8259A-1*/
780         outb(0x11, 0xA0);               /*! and to 8259A-2*/
781
782         outb(0x20, 0x21);               /*! start of hardware int's (0x20)*/
783         outb(0x28, 0xA1);               /*! start of hardware int's 2 (0x28)*/
784
785         outb(0x04, 0x21);               /*! 8259-1 is master*/
786         outb(0x02, 0xA1);               /*! 8259-2 is slave*/
787
788         outb(0x01, 0x21);               /*! 8086 mode for both*/
789         outb(0x01, 0xA1);               
790
791         outb(0xFF, 0xA1);               /*! mask off all interrupts for now*/
792         outb(0xFB, 0x21);               /*! mask all irq's but irq2 which is cascaded*/
793 }
794
795 static void hardware_setup(struct param_info *info __unused)
796 {
797         /* Disable nmi */
798         outb(0x80, 0x70);
799
800         /* Make sure any coprocessor is properly reset.. */
801         outb(0, 0xf0);
802         outb(0, 0xf1);
803
804         setup_i8259();
805 }
806
807
808 /*
809  * ELF Boot loader
810  * =============================================================================
811  */
812
813 static int count_elf_notes(Elf_Bhdr *bhdr)
814 {
815         unsigned char *note, *end;
816         int count;
817         count = 0;
818         note = ((char *)bhdr) + sizeof(*bhdr);
819         end = ((char *)bhdr) + bhdr->b_size;
820 #if 0
821         printf("count_elf_notes %lx\n", (unsigned long)bhdr);
822 #endif
823         while (note < end) {
824                 Elf_Nhdr *hdr;
825                 unsigned char *n_name, *n_desc, *next;
826                 hdr = (Elf_Nhdr *)note;
827                 n_name = note + sizeof(*hdr);
828                 n_desc = n_name + ((hdr->n_namesz + 3) & ~3);
829                 next = n_desc + ((hdr->n_descsz + 3) & ~3);
830 #if 0
831                 printf("elf_note = %lx\n", (unsigned long)note);
832                 printf("elf_namesz = %x\n", hdr->n_namesz);
833                 printf("elf_descsz = %x\n", hdr->n_descsz);
834                 printf("elf_type   = %x\n", hdr->n_type); 
835                 printf("elf_name = %lx\n", (unsigned long)n_name);
836                 printf("elf_desc = %lx\n", (unsigned long)n_desc);
837 #endif
838                 if (next > end) 
839                         break;
840                 count++;
841                 note = next;
842         }
843         return count;
844 }
845
846 static Elf_Nhdr *find_elf_note(Elf_Bhdr *bhdr, 
847         Elf_Word namesz, unsigned char *name, Elf_Word type)
848 {
849         unsigned char *note, *end;
850         note = ((char *)bhdr) + sizeof(*bhdr);
851         end = ((char *)bhdr) + bhdr->b_size;
852         while(note < end) {
853                 Elf_Nhdr *hdr;
854                 unsigned char *n_name, *n_desc, *next;
855                 hdr = (Elf_Nhdr *)note;
856                 n_name = note + sizeof(*hdr);
857                 n_desc = n_name + ((hdr->n_namesz + 3) & ~3);
858                 next = n_desc + ((hdr->n_descsz + 3) & ~3);
859                 if (next > end) 
860                         break;
861                 if ((hdr->n_type == type) &&
862                         (hdr->n_namesz == namesz) &&
863                         (memcmp(n_name, name, namesz) == 0)) {
864                         return hdr;
865                 }
866                 note = next;
867         }
868         return 0;
869 }
870
871 static void convert_elf_command_line(struct param_info *info,
872         Elf_Word descsz, unsigned char *desc)
873 {
874         append_command_line(info->real_mode, desc, descsz);
875 }
876
877 struct {
878         Elf_Word namesz;
879         unsigned char *name;
880         Elf_Word type;
881         void (*convert)(struct param_info *info, Elf_Word descsz, unsigned char *desc);
882 } elf_notes[] =
883 {
884         { 0, "", EBN_COMMAND_LINE, convert_elf_command_line },
885 };
886
887 static void convert_elf_boot(struct param_info *info, Elf_Bhdr *bhdr)
888 {
889         unsigned char *note, *end;
890         note = ((char *)bhdr) + sizeof(*bhdr);
891         end = ((char *)bhdr) + bhdr->b_size;
892         while(note < end) {
893                 Elf_Nhdr *hdr;
894                 unsigned char *n_name, *n_desc, *next;
895                 size_t i;
896                 hdr = (Elf_Nhdr *)note;
897                 n_name = note + sizeof(*hdr);
898                 n_desc = n_name + ((hdr->n_namesz + 3) & ~3);
899                 next = n_desc + ((hdr->n_descsz + 3) & ~3);
900                 if (next > end) 
901                         break;
902                 for(i = 0; i < sizeof(elf_notes)/sizeof(elf_notes[0]); i++) {
903                         if ((hdr->n_type == elf_notes[i].type) &&
904                                 (hdr->n_namesz == elf_notes[i].namesz) &&
905                                 (memcmp(n_name, elf_notes[i].name, elf_notes[i].namesz) == 0)) {
906                                 elf_notes[i].convert(info, hdr->n_descsz, n_desc);
907                                 break;
908                         }
909                 }
910                 note = next;
911         }
912 }
913
914 /*
915  * LinuxBIOS
916  * =============================================================================
917  */
918
919 #define LB_MEM_DEBUG 0
920 #if LB_MEM_DEBUG
921 #define lb_puts(x) printf("%s", x)
922 #define lb_put_hex(x) printf("%x", x)
923 #define lb_put_lhex(x) printf("%Lx", x)
924 #else
925 #define lb_puts(x)
926 #define lb_put_hex(x)
927 #define lb_put_lhex(x)
928 #endif /* LB_MEM_DEBUG */
929
930 static unsigned count_lb_records(void *start, unsigned long length)
931 {
932         struct lb_record *rec;
933         void *end;
934         unsigned count;
935         count = 0;
936         end = ((char *)start) + length;
937         for(rec = start; ((void *)rec < end) &&
938                 (rec->size <= (unsigned long)(end - (void *)rec)); 
939                 rec = (void *)(((char *)rec) + rec->size)) {
940                 count++;
941         }
942         return count;
943 }
944
945 static struct lb_header *__find_lb_table(void *start, void *end)
946 {
947         unsigned char *ptr;
948         /* For now be stupid.... */
949         for(ptr = start; (void *)ptr < end; ptr += 16) {
950                 struct lb_header *head = (void *)ptr;
951                 if ((head->signature[0] == 'L') && 
952                         (head->signature[1] == 'B') &&
953                         (head->signature[2] == 'I') &&
954                         (head->signature[3] == 'O') &&
955                         (head->header_bytes == sizeof(*head)) &&
956                         (compute_checksum(head, sizeof(*head)) == 0) &&
957                         (compute_checksum(ptr + sizeof(*head), head->table_bytes) ==
958                                 head->table_checksum) &&
959                         (count_lb_records(ptr + sizeof(*head), head->table_bytes) ==
960                                 head->table_entries)
961                         ) {
962                         return head;
963                 }
964         };
965         return 0;
966 }
967
968 static int find_lb_table(struct param_info *info)
969 {
970         struct lb_header *head;
971         head = 0;
972         if (!head) {
973                 /* First try at address 0 */
974                 head = __find_lb_table((void *)0x00000, (void *)0x1000);
975         }
976         if (!head) {
977                 /* Then try at address 0xf0000 */
978                 head = __find_lb_table((void *)0xf0000, (void *)0x100000);
979         }
980         if (head) {
981                 info->has_linuxbios = 1;
982                 info->lb_table = head;
983                 return 1;
984         }
985         return 0;
986 }
987
988 static void convert_lb_memory(struct param_info *info, struct lb_memory *mem)
989 {
990         int i;
991         int entries;
992         entries = (mem->size - sizeof(*mem))/sizeof(mem->map[0]);
993         for(i = 0; (i < entries) && (i < E820MAX); i++) {
994                 unsigned long type;
995                 unsigned long long end;
996                 end = mem->map[i].start + mem->map[i].size;
997                 lb_puts("lb-mem: "); 
998                 lb_put_lhex(mem->map[i].start);
999                 lb_puts(" - ");
1000                 lb_put_lhex(end); 
1001                 lb_puts(" (");
1002                 switch(mem->map[i].type) {
1003                 case LB_MEM_RAM:
1004                         type = E820_RAM;
1005                         lb_puts("ram");
1006                         break;
1007                 default:
1008                         type = E820_RESERVED;
1009                         lb_puts("reserved");
1010                         break;
1011                 }
1012                 lb_puts(")\n");
1013                 add_e820_map(info->real_mode, 
1014                         mem->map[i].start, mem->map[i].size, type);
1015         }
1016         info->need_mem_sizes = 0;
1017 }
1018         
1019 static void query_lb_values(struct param_info *info)
1020 {
1021         struct lb_header *head;
1022         struct lb_record *rec;
1023         void *start, *end;
1024         head = info->lb_table;
1025         start = ((unsigned char *)head) + sizeof(*head);
1026         end = ((char *)start) + head->table_bytes;
1027         for(rec = start; ((void *)rec < end) &&
1028                 (rec->size <= (unsigned long)(end - (void *)rec)); 
1029                 rec = (void *)(((char *)rec) + rec->size)) {
1030                 switch(rec->tag) {
1031                 case LB_TAG_MEMORY:
1032                 {
1033                         struct lb_memory *mem;
1034                         mem = (struct lb_memory *) rec;
1035                         convert_lb_memory(info, mem); 
1036                         break;
1037                 }
1038                 default: 
1039                         break;
1040                 };
1041         }
1042 }
1043
1044 /*
1045  * PCBIOS
1046  * =============================================================================
1047  */
1048 #define PC_MEM_DEBUG 0
1049 #if PC_MEM_DEBUG
1050 #define pc_puts(x) printf("%s", x)
1051 #define pc_put_hex(x) printf("%x", x)
1052 #define pc_put_lhex(x) printf("%Lx", x)
1053 #else
1054 #define pc_puts(x)
1055 #define pc_put_hex(x)
1056 #define pc_put_lhex(x)
1057 #endif /* PC_MEM_DEBUG */
1058
1059 /* functions for querying the pcbios */
1060 extern void noop(void); /* for testing purposes only */
1061 extern int meme820(struct e820entry *buf, int count);
1062 extern unsigned int meme801(void);
1063 extern unsigned short mem88(void);
1064 extern unsigned short basememsize(void);
1065
1066 struct meminfo {
1067         int map_count;
1068         struct e820entry map[E820MAX];
1069 };
1070
1071 static struct meminfo meminfo;
1072 static void get_meminfo(struct param_info *info)
1073 {
1074         int i;
1075         pc_puts("getting meminfo...\n");
1076         meminfo.map_count = meme820(meminfo.map, E820MAX);
1077         pc_puts("got meminfo count="); pc_put_hex(meminfo.map_count); pc_puts("\n");
1078         for(i = 0; i < meminfo.map_count; i++) {
1079                 unsigned long long end;
1080                 struct e820entry *seg = meminfo.map + i;
1081                 end = seg->addr + seg->size;
1082                 pc_puts("BIOS-e820: ");
1083                 pc_put_lhex(seg->addr); 
1084                 pc_puts(" - ");
1085                 pc_put_lhex(end);
1086                 pc_puts(" (");
1087                 switch(seg->type) {
1088                 case E820_RAM:
1089                         pc_puts("ram");
1090                         info->need_mem_sizes = 0;
1091                         break;
1092                 case E820_ACPI:
1093                         pc_puts("ACPI data");
1094                         break;
1095                 case E820_NVS:
1096                         pc_puts("ACPI NVS");
1097                         break;
1098                 case E820_RESERVED:
1099                 default:
1100                         pc_puts("reserved");
1101                         break;
1102                 }
1103                 pc_puts(")\n");
1104                 add_e820_map(info->real_mode, 
1105                         seg->addr, seg->size, seg->type);
1106         }
1107         info->real_mode->alt_mem_k = meme801();
1108         info->real_mode->ext_mem_k = mem88();
1109         if (info->real_mode->alt_mem_k || info->real_mode->ext_mem_k) {
1110                 info->need_mem_sizes = 0;
1111         }
1112 }
1113
1114 static void query_pcbios_values(struct param_info *info)
1115 {
1116         get_meminfo(info);
1117 }
1118
1119 /*
1120  * Bootloaders
1121  * =============================================================================
1122  */
1123
1124
1125 static void query_bootloader_param_class(struct param_info *info)
1126 {
1127         int has_bootloader_type = 0;
1128         Elf_Bhdr *hdr = 0;
1129         if (!has_bootloader_type && (info->type == 0x2BADB002)) {
1130                 /* Orignal multiboot specification */
1131                 info->has_multiboot = 1;
1132                 has_bootloader_type = 1;
1133         }
1134         if (!has_bootloader_type && (info->type == 0x0A11B007)) {
1135                 /* Uniform boot proposal */
1136                 unsigned long checksum;
1137                 struct uniform_boot_header *header;
1138                 header = info->data;
1139                 checksum = compute_checksum(header, header->header_bytes);
1140                 if (checksum == 0) {
1141                         info->has_uniform_boot = 1;
1142                         has_bootloader_type = 1;
1143                 } else{
1144                         printf("Bad uniform boot header checksum!\n");
1145                 }
1146         }
1147         if (info->type == ELF_BHDR_MAGIC) {
1148                 hdr = info->data;
1149         }
1150         if (info->param && (info->param->b_signature == ELF_BHDR_MAGIC)) {
1151                 hdr = info->param;
1152         }
1153         if (!has_bootloader_type && hdr) {
1154                 /* Good ELF boot proposal... */
1155                 unsigned long checksum;
1156                 int count;
1157                 checksum = 0;
1158                 if (hdr->b_checksum != 0) {
1159                         checksum = compute_checksum(hdr, hdr->b_size);
1160                 }
1161                 count = count_elf_notes(hdr);
1162                 if ((hdr->b_signature == ELF_BHDR_MAGIC) &&
1163                         (checksum == 0) &&
1164                         hdr->b_records == count) {
1165                         info->has_elf_boot = 1;
1166                         info->param = hdr;
1167                         has_bootloader_type = 1;
1168                 }
1169                 else {
1170                         printf("Bad ELF parameter table!\n");
1171                         printf("   checksum = %x\n", checksum);
1172                         printf("      count = %x\n", count);
1173                         printf("        hdr = %x\n", (unsigned long)hdr);
1174                         printf("     b_size = %x\n", hdr->b_size);
1175                         printf("b_signature = %x\n", hdr->b_signature);
1176                         printf("  b_records = %x\n", hdr->b_records);
1177                 }
1178         }
1179         if (!has_bootloader_type) {
1180                 printf("Unknown bootloader class!\n");
1181                 printf("type=%x\n", info->type);
1182                 printf("data=%x\n", (unsigned)info->data);
1183                 printf("param=%x\n", (unsigned)info->param);
1184         }
1185 }
1186
1187 static void query_bootloader_values(struct param_info *info) 
1188 {
1189         if (info->has_multiboot) {
1190                 convert_multiboot(info, info->data);
1191         }
1192         else if (info->has_uniform_boot) {
1193                 convert_uniform_boot(info, info->data);
1194         }
1195         else if (info->has_elf_boot) {
1196                 convert_elf_boot(info, info->param);
1197         }
1198 }
1199
1200 /*
1201  * Firmware
1202  * =============================================================================
1203  */
1204
1205 static int bootloader_query_firmware_class(struct param_info *info)
1206 {
1207         Elf_Nhdr *hdr;
1208         unsigned char *note, *n_name, *n_desc;
1209         int detected_firmware_type;
1210         if (!info->has_elf_boot) {
1211                 /* Only the elf boot tables gives us a firmware type */
1212                 return 0;
1213         }
1214         detected_firmware_type = 0;
1215         n_desc = 0;
1216
1217         hdr = find_elf_note(info->param, 0, 0, EBN_FIRMWARE_TYPE);
1218         if (!hdr) {
1219                 /* If I'm not explicitly told the firmware type
1220                  * do my best to guess it for myself.
1221                  */
1222                 detected_firmware_type = 0;
1223         } else {
1224                 note = (char *)hdr;
1225                 n_name = note + sizeof(*hdr);
1226                 n_desc = n_name + ((hdr->n_namesz + 3) & ~3);
1227         }
1228         if (!detected_firmware_type && hdr &&
1229                 (hdr->n_descsz == 7) &&
1230                 (memcmp(n_desc, "PCBIOS", 7) == 0)) {
1231                 info->has_pcbios = 1;
1232                 detected_firmware_type = 1;
1233         }
1234         if (!detected_firmware_type && hdr &&
1235                 (hdr->n_descsz == 10) &&
1236                 (memcmp(n_desc, "LinuxBIOS", 10) == 0)) {
1237                 /* Don't believe I'm linuxBIOS unless I can
1238                  * find the linuxBIOS table..
1239                  */
1240                 detected_firmware_type = find_lb_table(info);
1241         }
1242         if (!detected_firmware_type && hdr &&
1243                 (hdr->n_descsz == 0)) {
1244                 /* No firmware is present */
1245                 detected_firmware_type = 1;
1246         }
1247         if (!detected_firmware_type && hdr &&
1248                 (hdr->n_descsz == 1) && 
1249                 (memcmp(n_desc, "", 1) == 0)) {
1250                 /* No firmware is present */
1251                 detected_firmware_type = 1;
1252         }
1253         if (!detected_firmware_type && hdr) {
1254                 printf("Unknown firmware type: %s\n", n_desc);
1255         }
1256         return detected_firmware_type;
1257 }
1258
1259 static void query_firmware_class(struct param_info *info)
1260 {
1261         int detected_firmware_type = 0;
1262
1263         /* First say I have no firmware at all... */
1264         info->has_pcbios = 0;
1265         info->has_linuxbios = 0;
1266
1267         /* See if the bootloader has told us what
1268          * kind of firmware we are running on.
1269          */
1270         detected_firmware_type = bootloader_query_firmware_class(info);
1271
1272         /* See if we can detect linuxbios. */
1273         if (!detected_firmware_type) {
1274                 detected_firmware_type = find_lb_table(info);
1275         }
1276
1277         if (!detected_firmware_type) {
1278                 /* if all else fails assume a standard pcbios... */
1279                 info->has_pcbios = 1;
1280         }
1281
1282         /* Now print out the firmware type... */
1283         printf("Firmware type:");
1284         if (info->has_linuxbios) {
1285                 printf(" LinuxBIOS");
1286         }
1287         if (info->has_pcbios) {
1288                 printf(" PCBIOS");
1289         }
1290         printf("\n");
1291 }
1292
1293 static void query_firmware_values(struct param_info *info)
1294 {
1295         if (info->has_linuxbios) {
1296                 query_lb_values(info);
1297         }
1298         if (info->has_pcbios) {
1299                 query_pcbios_values(info);
1300         }
1301         
1302 }
1303
1304 /*
1305  * Debug
1306  * =============================================================================
1307  */
1308
1309 #if 0
1310 static void print_offsets(void)
1311 {
1312         struct parameters *real_mode = 0;
1313         printf("print_offsets\n");
1314
1315         printf("orig_x               =%x\n", (uint32_t)&real_mode->orig_x);
1316         printf("orig_y               =%x\n", (uint32_t)&real_mode->orig_y);
1317         printf("ext_mem_k            =%x\n", (uint32_t)&real_mode->ext_mem_k);
1318         printf("orig_video_page      =%x\n", (uint32_t)&real_mode->orig_video_page);
1319         printf("orig_video_mode      =%x\n", (uint32_t)&real_mode->orig_video_mode);
1320         printf("orig_video_cols      =%x\n", (uint32_t)&real_mode->orig_video_cols);
1321         printf("unused2              =%x\n", (uint32_t)&real_mode->unused2); 
1322         printf("orig_video_ega_bx    =%x\n", (uint32_t)&real_mode->orig_video_ega_bx); 
1323         printf("unused3              =%x\n", (uint32_t)&real_mode->unused3);
1324         printf("orig_video_lines     =%x\n", (uint32_t)&real_mode->orig_video_lines); 
1325         printf("orig_video_isVGA     =%x\n", (uint32_t)&real_mode->orig_video_isVGA); 
1326         printf("orig_video_points    =%x\n", (uint32_t)&real_mode->orig_video_points);
1327         printf("lfb_width            =%x\n", (uint32_t)&real_mode->lfb_width);
1328         printf("lfb_height           =%x\n", (uint32_t)&real_mode->lfb_height);
1329         printf("lfb_depth            =%x\n", (uint32_t)&real_mode->lfb_depth); 
1330         printf("lfb_base             =%x\n", (uint32_t)&real_mode->lfb_base); 
1331         printf("lfb_size             =%x\n", (uint32_t)&real_mode->lfb_size); 
1332         printf("cl_magic             =%x\n", (uint32_t)&real_mode->cl_magic); 
1333         printf("cl_offset            =%x\n", (uint32_t)&real_mode->cl_offset);
1334         printf("lfb_linelength       =%x\n", (uint32_t)&real_mode->lfb_linelength);
1335         printf("red_size             =%x\n", (uint32_t)&real_mode->red_size);
1336         printf("red_pos              =%x\n", (uint32_t)&real_mode->red_pos); 
1337         printf("green_size           =%x\n", (uint32_t)&real_mode->green_size);
1338         printf("green_pos            =%x\n", (uint32_t)&real_mode->green_pos); 
1339         printf("blue_size            =%x\n", (uint32_t)&real_mode->blue_size); 
1340         printf("blue_pos             =%x\n", (uint32_t)&real_mode->blue_pos); 
1341         printf("rsvd_size            =%x\n", (uint32_t)&real_mode->rsvd_size);
1342         printf("rsvd_pos             =%x\n", (uint32_t)&real_mode->rsvd_pos); 
1343         printf("vesapm_seg           =%x\n", (uint32_t)&real_mode->vesapm_seg);
1344         printf("vesapm_off           =%x\n", (uint32_t)&real_mode->vesapm_off);
1345         printf("pages                =%x\n", (uint32_t)&real_mode->pages); 
1346         printf("reserved4            =%x\n", (uint32_t)&real_mode->reserved4); 
1347         printf("apm_bios_info        =%x\n", (uint32_t)&real_mode->apm_bios_info);
1348         printf("drive_info           =%x\n", (uint32_t)&real_mode->drive_info); 
1349         printf("sys_desc_table       =%x\n", (uint32_t)&real_mode->sys_desc_table);
1350         printf("alt_mem_k            =%x\n", (uint32_t)&real_mode->alt_mem_k); 
1351         printf("reserved5            =%x\n", (uint32_t)&real_mode->reserved5); 
1352         printf("e820_map_nr          =%x\n", (uint32_t)&real_mode->e820_map_nr); 
1353         printf("reserved6            =%x\n", (uint32_t)&real_mode->reserved6); 
1354         printf("mount_root_rdonly    =%x\n", (uint32_t)&real_mode->mount_root_rdonly); 
1355         printf("reserved7            =%x\n", (uint32_t)&real_mode->reserved7);
1356         printf("ramdisk_flags        =%x\n", (uint32_t)&real_mode->ramdisk_flags);
1357         printf("reserved8            =%x\n", (uint32_t)&real_mode->reserved8); 
1358         printf("orig_root_dev        =%x\n", (uint32_t)&real_mode->orig_root_dev);
1359         printf("reserved9            =%x\n", (uint32_t)&real_mode->reserved9); 
1360         printf("aux_device_info      =%x\n", (uint32_t)&real_mode->aux_device_info);
1361         printf("reserved10           =%x\n", (uint32_t)&real_mode->reserved10); 
1362         printf("param_block_signature=%x\n", (uint32_t)&real_mode->param_block_signature);
1363         printf("param_block_version  =%x\n", (uint32_t)&real_mode->param_block_version); 
1364         printf("reserved11           =%x\n", (uint32_t)&real_mode->reserved11); 
1365         printf("loader_type          =%x\n", (uint32_t)&real_mode->loader_type);
1366         printf("loader_flags         =%x\n", (uint32_t)&real_mode->loader_flags);
1367         printf("reserved12           =%x\n", (uint32_t)&real_mode->reserved12); 
1368         printf("kernel_start         =%x\n", (uint32_t)&real_mode->kernel_start);
1369         printf("initrd_start         =%x\n", (uint32_t)&real_mode->initrd_start);
1370         printf("initrd_size          =%x\n", (uint32_t)&real_mode->initrd_size);
1371         printf("reserved13           =%x\n", (uint32_t)&real_mode->reserved13);
1372         printf("e820_map             =%x\n", (uint32_t)&real_mode->e820_map); 
1373         printf("reserved16           =%x\n", (uint32_t)&real_mode->reserved16); 
1374         printf("command_line         =%x\n", (uint32_t)&real_mode->command_line);
1375         printf("reserved17           =%x\n", (uint32_t)&real_mode->reserved17);
1376 }
1377
1378 static void print_linux_params(struct param_info *info)
1379 {
1380         int i;
1381
1382         printf("print_linux_params\n");
1383         /* Default screen size */
1384         printf("orig_x           =%x\n", info->real_mode->orig_x);
1385         printf("orig_y           =%x\n", info->real_mode->orig_y);
1386         printf("orig_video_page  =%x\n", info->real_mode->orig_video_page);
1387         printf("orig_video_mode  =%x\n", info->real_mode->orig_video_mode);
1388         printf("orig_video_cols  =%x\n", info->real_mode->orig_video_cols);
1389         printf("orig_video_lines =%x\n", info->real_mode->orig_video_lines);
1390         printf("orig_video_ega_bx=%x\n", info->real_mode->orig_video_ega_bx);
1391         printf("orig_video_isVGA =%x\n", info->real_mode->orig_video_isVGA);
1392         printf("orig_video_points=%x\n", info->real_mode->orig_video_points);
1393         
1394
1395         /* System descriptor table... */
1396         printf("sys_dest_table_len=%x\n", info->real_mode->sys_desc_table.length);
1397
1398         /* Memory sizes */
1399         printf("ext_mem_k        =%x\n", info->real_mode->ext_mem_k);
1400         printf("alt_mem_k        =%x\n", info->real_mode->alt_mem_k);
1401         printf("e820_map_nr      =%x\n", info->real_mode->e820_map_nr);
1402         for(i = 0; i < E820MAX; i++) {
1403                 printf("addr[%x]         =%Lx\n", 
1404                         i,  info->real_mode->e820_map[i].addr);
1405                 printf("size[%x]         =%Lx\n", 
1406                         i, info->real_mode->e820_map[i].size);
1407                 printf("type[%x]         =%Lx\n", 
1408                         i, info->real_mode->e820_map[i].type);
1409         }
1410         printf("mount_root_rdonly=%x\n", info->real_mode->mount_root_rdonly); 
1411         printf("ramdisk_flags    =%x\n", info->real_mode->ramdisk_flags); 
1412         printf("orig_root_dev    =%x\n", info->real_mode->orig_root_dev); 
1413         printf("aux_device_info  =%x\n", info->real_mode->aux_device_info); 
1414         printf("param_block_signature=%x\n", *((uint32_t *)info->real_mode->param_block_signature));
1415         printf("loader_type      =%x\n", info->real_mode->loader_type); 
1416         printf("loader_flags     =%x\n", info->real_mode->loader_flags);
1417         printf("initrd_start     =%x\n", info->real_mode->initrd_start);
1418         printf("initrd_size      =%x\n", info->real_mode->initrd_size); 
1419
1420         /* Where I'm putting the command line */
1421         printf("cl_magic         =%x\n", info->real_mode->cl_magic); 
1422         printf("cl_offset        =%x\n", info->real_mode->cl_offset);
1423         
1424         /* Now print the command line */
1425         printf("command_line     =%s\n", info->real_mode->command_line);
1426 }
1427
1428
1429 #endif
1430
1431 /*
1432  * main
1433  * =============================================================================
1434  */
1435
1436 void initialize_linux_params(struct param_info *info)
1437 {
1438         int len;
1439         /* First the defaults */
1440         memset(info->real_mode, 0, PAGE_SIZE);
1441         
1442         /* Default screen size */
1443         info->real_mode->orig_x = 0;
1444         info->real_mode->orig_y = 25;
1445         info->real_mode->orig_video_page = 0;
1446         info->real_mode->orig_video_mode = 0;
1447         info->real_mode->orig_video_cols = 80;
1448         info->real_mode->orig_video_lines = 25;
1449         info->real_mode->orig_video_ega_bx = 0;
1450         info->real_mode->orig_video_isVGA = 1;
1451         info->real_mode->orig_video_points = 16;
1452         
1453         /* Fill this in later */
1454         info->real_mode->ext_mem_k = 0;
1455                 
1456         /* Fill in later... */
1457         info->real_mode->e820_map_nr = 0;
1458
1459         /* Where I'm putting the command line */
1460         info->real_mode->cl_magic = CL_MAGIC_VALUE;
1461         info->real_mode->cl_offset = 2048;
1462
1463         info->real_mode->cmd_line_ptr = info->real_mode->cl_offset + (unsigned long) info->real_mode;
1464         
1465         /* Now set the command line */
1466         len = strnlen(info->image->cmdline, sizeof(info->real_mode->command_line) -1);
1467         memcpy(info->real_mode->command_line, info->image->cmdline, len);
1468         info->real_mode->command_line[len] = '\0';
1469
1470         /* from the bios initially */
1471         memset(&info->real_mode->apm_bios_info, 0, sizeof(info->real_mode->apm_bios_info));
1472         
1473         memset(&info->real_mode->drive_info, 0, sizeof(info->real_mode->drive_info));
1474
1475         /* forget it for now... */
1476         info->real_mode->sys_desc_table.length = 0; 
1477         
1478         /* Fill this in later */
1479         info->real_mode->alt_mem_k = 0;
1480         info->real_mode->ext_mem_k = 0;
1481                 
1482         /* default yes: this can be overridden on the command line */
1483         info->real_mode->mount_root_rdonly = 0xFFFF;
1484         
1485         /* old ramdisk options, These really should be command line
1486          * things...
1487          */
1488         info->real_mode->ramdisk_flags = info->image->ramdisk_flags;
1489
1490         /* default to /dev/hda.
1491          * Override this on the command line if necessary 
1492          */
1493         info->real_mode->orig_root_dev = info->image->root_dev;
1494         
1495         /* Originally from the bios? */
1496         info->real_mode->aux_device_info = 0;
1497         
1498         /* Boot block magic */
1499         memcpy(info->real_mode->param_block_signature, "HdrS", 4);
1500         info->real_mode->param_block_version = 0x0201;
1501         
1502         /* Say I'm a kernel boot loader */
1503         info->real_mode->loader_type = (LOADER_TYPE_KERNEL << 4) + 0 /* version */;
1504         
1505         /* No loader flags */
1506         info->real_mode->loader_flags = 0;
1507         
1508         /* Ramdisk address and size ... */
1509         info->real_mode->initrd_start = 0;
1510         info->real_mode->initrd_size = 0;
1511         if (info->image->initrd_size) {
1512                 info->real_mode->initrd_start = info->image->initrd_start;
1513                 info->real_mode->initrd_size = info->image->initrd_size;
1514         }       
1515
1516         /* Now remember those things that I need */
1517         info->need_mem_sizes = 1;
1518 }
1519
1520 void *convert_params(unsigned type, void *data, void *param, void *image)
1521 {
1522         struct param_info info;
1523 #if 0
1524         printf("hello world\n");
1525 #endif
1526         info.real_mode = faked_real_mode;
1527         info.type  = type;
1528         info.data  = data;
1529         info.param = param;
1530         info.image = image;
1531         initialize_linux_params(&info);
1532         query_bootloader_param_class(&info);
1533         query_firmware_class(&info);
1534         query_firmware_values(&info);
1535         query_bootloader_values(&info);
1536
1537         /* Do the hardware setup that linux might forget... */
1538         hardware_setup(&info);
1539
1540         /* Print some debugging information */
1541 #if 0
1542         printf("EXT_MEM_K=%x\n", info.real_mode->ext_mem_k);
1543         printf("ALT_MEM_K=%x\n", info.real_mode->alt_mem_k);
1544 #endif
1545 #if 0
1546         print_offsets();
1547         print_linux_params(&info);
1548 #endif
1549 #if 0
1550         printf("info.real_mode = 0x%x\n", info.real_mode );
1551         printf("Jumping to Linux\n");
1552 #endif  
1553         return info.real_mode;
1554 }
1555