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