Since some people disapprove of white space cleanups mixed in regular commits
[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                 struct lb_forward *forward = (struct lb_forward *)(((char *)head) + head->header_bytes);
982                 if (forward->tag == LB_TAG_FORWARD) {
983                         head = __find_lb_table(forward->forward,
984                                         forward->forward + 0x1000);
985                 }
986         }
987         if (head) {
988                 info->has_linuxbios = 1;
989                 info->lb_table = head;
990                 return 1;
991         }
992         return 0;
993 }
994
995 static void convert_lb_memory(struct param_info *info, struct lb_memory *mem)
996 {
997         int i;
998         int entries;
999         entries = (mem->size - sizeof(*mem))/sizeof(mem->map[0]);
1000         for(i = 0; (i < entries) && (i < E820MAX); i++) {
1001                 unsigned long type;
1002                 unsigned long long end;
1003                 end = mem->map[i].start + mem->map[i].size;
1004                 lb_puts("lb-mem: ");
1005                 lb_put_lhex(mem->map[i].start);
1006                 lb_puts(" - ");
1007                 lb_put_lhex(end);
1008                 lb_puts(" (");
1009                 switch(mem->map[i].type) {
1010                 case LB_MEM_RAM:
1011                         type = E820_RAM;
1012                         lb_puts("ram");
1013                         break;
1014                 default:
1015                         type = E820_RESERVED;
1016                         lb_puts("reserved");
1017                         break;
1018                 }
1019                 lb_puts(")\n");
1020                 add_e820_map(info->real_mode,
1021                         mem->map[i].start, mem->map[i].size, type);
1022         }
1023         info->need_mem_sizes = 0;
1024 }
1025
1026 static void query_lb_values(struct param_info *info)
1027 {
1028         struct lb_header *head;
1029         struct lb_record *rec;
1030         void *start, *end;
1031         head = info->lb_table;
1032         start = ((unsigned char *)head) + sizeof(*head);
1033         end = ((char *)start) + head->table_bytes;
1034         for(rec = start; ((void *)rec < end) &&
1035                 (rec->size <= (unsigned long)(end - (void *)rec));
1036                 rec = (void *)(((char *)rec) + rec->size)) {
1037                 switch(rec->tag) {
1038                 case LB_TAG_MEMORY:
1039                 {
1040                         struct lb_memory *mem;
1041                         mem = (struct lb_memory *) rec;
1042                         convert_lb_memory(info, mem);
1043                         break;
1044                 }
1045                 default:
1046                         break;
1047                 };
1048         }
1049 }
1050
1051 /*
1052  * PCBIOS
1053  * =============================================================================
1054  */
1055 #define PC_MEM_DEBUG 0
1056 #if PC_MEM_DEBUG
1057 #define pc_puts(x) printf("%s", x)
1058 #define pc_put_hex(x) printf("%x", x)
1059 #define pc_put_lhex(x) printf("%Lx", x)
1060 #else
1061 #define pc_puts(x)
1062 #define pc_put_hex(x)
1063 #define pc_put_lhex(x)
1064 #endif /* PC_MEM_DEBUG */
1065
1066 /* functions for querying the pcbios */
1067 extern void noop(void); /* for testing purposes only */
1068 extern int meme820(struct e820entry *buf, int count);
1069 extern unsigned int meme801(void);
1070 extern unsigned short mem88(void);
1071 extern unsigned short basememsize(void);
1072
1073 struct meminfo {
1074         int map_count;
1075         struct e820entry map[E820MAX];
1076 };
1077
1078 static struct meminfo meminfo;
1079 static void get_meminfo(struct param_info *info)
1080 {
1081         int i;
1082         pc_puts("getting meminfo...\n");
1083         meminfo.map_count = meme820(meminfo.map, E820MAX);
1084         pc_puts("got meminfo count="); pc_put_hex(meminfo.map_count); pc_puts("\n");
1085         for(i = 0; i < meminfo.map_count; i++) {
1086                 unsigned long long end;
1087                 struct e820entry *seg = meminfo.map + i;
1088                 end = seg->addr + seg->size;
1089                 pc_puts("BIOS-e820: ");
1090                 pc_put_lhex(seg->addr);
1091                 pc_puts(" - ");
1092                 pc_put_lhex(end);
1093                 pc_puts(" (");
1094                 switch(seg->type) {
1095                 case E820_RAM:
1096                         pc_puts("ram");
1097                         info->need_mem_sizes = 0;
1098                         break;
1099                 case E820_ACPI:
1100                         pc_puts("ACPI data");
1101                         break;
1102                 case E820_NVS:
1103                         pc_puts("ACPI NVS");
1104                         break;
1105                 case E820_RESERVED:
1106                 default:
1107                         pc_puts("reserved");
1108                         break;
1109                 }
1110                 pc_puts(")\n");
1111                 add_e820_map(info->real_mode,
1112                         seg->addr, seg->size, seg->type);
1113         }
1114         info->real_mode->alt_mem_k = meme801();
1115         info->real_mode->ext_mem_k = mem88();
1116         if (info->real_mode->alt_mem_k || info->real_mode->ext_mem_k) {
1117                 info->need_mem_sizes = 0;
1118         }
1119 }
1120
1121 static void query_pcbios_values(struct param_info *info)
1122 {
1123         get_meminfo(info);
1124 }
1125
1126 /*
1127  * Bootloaders
1128  * =============================================================================
1129  */
1130
1131
1132 static void query_bootloader_param_class(struct param_info *info)
1133 {
1134         int has_bootloader_type = 0;
1135         Elf_Bhdr *hdr = 0;
1136         if (!has_bootloader_type && (info->type == 0x2BADB002)) {
1137                 /* Orignal multiboot specification */
1138                 info->has_multiboot = 1;
1139                 has_bootloader_type = 1;
1140         }
1141         if (!has_bootloader_type && (info->type == 0x0A11B007)) {
1142                 /* Uniform boot proposal */
1143                 unsigned long checksum;
1144                 struct uniform_boot_header *header;
1145                 header = info->data;
1146                 checksum = compute_checksum(header, header->header_bytes);
1147                 if (checksum == 0) {
1148                         info->has_uniform_boot = 1;
1149                         has_bootloader_type = 1;
1150                 } else{
1151                         printf("Bad uniform boot header checksum!\n");
1152                 }
1153         }
1154         if (info->type == ELF_BHDR_MAGIC) {
1155                 hdr = info->data;
1156         }
1157         if (info->param && (info->param->b_signature == ELF_BHDR_MAGIC)) {
1158                 hdr = info->param;
1159         }
1160         if (!has_bootloader_type && hdr) {
1161                 /* Good ELF boot proposal... */
1162                 unsigned long checksum;
1163                 int count;
1164                 checksum = 0;
1165                 if (hdr->b_checksum != 0) {
1166                         checksum = compute_checksum(hdr, hdr->b_size);
1167                 }
1168                 count = count_elf_notes(hdr);
1169                 if ((hdr->b_signature == ELF_BHDR_MAGIC) &&
1170                         (checksum == 0) &&
1171                         hdr->b_records == count) {
1172                         info->has_elf_boot = 1;
1173                         info->param = hdr;
1174                         has_bootloader_type = 1;
1175                 }
1176                 else {
1177                         printf("Bad ELF parameter table!\n");
1178                         printf("   checksum = %x\n", checksum);
1179                         printf("      count = %x\n", count);
1180                         printf("        hdr = %x\n", (unsigned long)hdr);
1181                         printf("     b_size = %x\n", hdr->b_size);
1182                         printf("b_signature = %x\n", hdr->b_signature);
1183                         printf("  b_records = %x\n", hdr->b_records);
1184                 }
1185         }
1186         if (!has_bootloader_type) {
1187                 printf("Unknown bootloader class!\n");
1188                 printf("type=%x\n", info->type);
1189                 printf("data=%x\n", (unsigned)info->data);
1190                 printf("param=%x\n", (unsigned)info->param);
1191         }
1192 }
1193
1194 static void query_bootloader_values(struct param_info *info)
1195 {
1196         if (info->has_multiboot) {
1197                 convert_multiboot(info, info->data);
1198         }
1199         else if (info->has_uniform_boot) {
1200                 convert_uniform_boot(info, info->data);
1201         }
1202         else if (info->has_elf_boot) {
1203                 convert_elf_boot(info, info->param);
1204         }
1205 }
1206
1207 /*
1208  * Firmware
1209  * =============================================================================
1210  */
1211
1212 static int bootloader_query_firmware_class(struct param_info *info)
1213 {
1214         Elf_Nhdr *hdr;
1215         unsigned char *note, *n_name, *n_desc;
1216         int detected_firmware_type;
1217         if (!info->has_elf_boot) {
1218                 /* Only the elf boot tables gives us a firmware type */
1219                 return 0;
1220         }
1221         detected_firmware_type = 0;
1222         n_desc = 0;
1223
1224         hdr = find_elf_note(info->param, 0, 0, EBN_FIRMWARE_TYPE);
1225         if (!hdr) {
1226                 /* If I'm not explicitly told the firmware type
1227                  * do my best to guess it for myself.
1228                  */
1229                 detected_firmware_type = 0;
1230         } else {
1231                 note = (char *)hdr;
1232                 n_name = note + sizeof(*hdr);
1233                 n_desc = n_name + ((hdr->n_namesz + 3) & ~3);
1234         }
1235         if (!detected_firmware_type && hdr &&
1236                 (hdr->n_descsz == 7) &&
1237                 (memcmp(n_desc, "PCBIOS", 7) == 0)) {
1238                 info->has_pcbios = 1;
1239                 detected_firmware_type = 1;
1240         }
1241         if (!detected_firmware_type && hdr &&
1242                 (hdr->n_descsz == 10) &&
1243                 (memcmp(n_desc, "LinuxBIOS", 10) == 0)) {
1244                 /* Don't believe I'm linuxBIOS unless I can
1245                  * find the linuxBIOS table..
1246                  */
1247                 detected_firmware_type = find_lb_table(info);
1248         }
1249         if (!detected_firmware_type && hdr &&
1250                 (hdr->n_descsz == 0)) {
1251                 /* No firmware is present */
1252                 detected_firmware_type = 1;
1253         }
1254         if (!detected_firmware_type && hdr &&
1255                 (hdr->n_descsz == 1) &&
1256                 (memcmp(n_desc, "", 1) == 0)) {
1257                 /* No firmware is present */
1258                 detected_firmware_type = 1;
1259         }
1260         if (!detected_firmware_type && hdr) {
1261                 printf("Unknown firmware type: %s\n", n_desc);
1262         }
1263         return detected_firmware_type;
1264 }
1265
1266 static void query_firmware_class(struct param_info *info)
1267 {
1268         int detected_firmware_type = 0;
1269
1270         /* First say I have no firmware at all... */
1271         info->has_pcbios = 0;
1272         info->has_linuxbios = 0;
1273
1274         /* See if the bootloader has told us what
1275          * kind of firmware we are running on.
1276          */
1277         detected_firmware_type = bootloader_query_firmware_class(info);
1278
1279         /* See if we can detect linuxbios. */
1280         if (!detected_firmware_type) {
1281                 detected_firmware_type = find_lb_table(info);
1282         }
1283
1284         if (!detected_firmware_type) {
1285                 /* if all else fails assume a standard pcbios... */
1286                 info->has_pcbios = 1;
1287         }
1288
1289         /* Now print out the firmware type... */
1290         printf("Firmware type:");
1291         if (info->has_linuxbios) {
1292                 printf(" LinuxBIOS");
1293         }
1294         if (info->has_pcbios) {
1295                 printf(" PCBIOS");
1296         }
1297         printf("\n");
1298 }
1299
1300 static void query_firmware_values(struct param_info *info)
1301 {
1302         if (info->has_linuxbios) {
1303                 query_lb_values(info);
1304         }
1305         if (info->has_pcbios) {
1306                 query_pcbios_values(info);
1307         }
1308
1309 }
1310
1311 /*
1312  * Debug
1313  * =============================================================================
1314  */
1315
1316 #if 0
1317 static void print_offsets(void)
1318 {
1319         struct parameters *real_mode = 0;
1320         printf("print_offsets\n");
1321
1322         printf("orig_x               =%x\n", (uint32_t)&real_mode->orig_x);
1323         printf("orig_y               =%x\n", (uint32_t)&real_mode->orig_y);
1324         printf("ext_mem_k            =%x\n", (uint32_t)&real_mode->ext_mem_k);
1325         printf("orig_video_page      =%x\n", (uint32_t)&real_mode->orig_video_page);
1326         printf("orig_video_mode      =%x\n", (uint32_t)&real_mode->orig_video_mode);
1327         printf("orig_video_cols      =%x\n", (uint32_t)&real_mode->orig_video_cols);
1328         printf("unused2              =%x\n", (uint32_t)&real_mode->unused2);
1329         printf("orig_video_ega_bx    =%x\n", (uint32_t)&real_mode->orig_video_ega_bx);
1330         printf("unused3              =%x\n", (uint32_t)&real_mode->unused3);
1331         printf("orig_video_lines     =%x\n", (uint32_t)&real_mode->orig_video_lines);
1332         printf("orig_video_isVGA     =%x\n", (uint32_t)&real_mode->orig_video_isVGA);
1333         printf("orig_video_points    =%x\n", (uint32_t)&real_mode->orig_video_points);
1334         printf("lfb_width            =%x\n", (uint32_t)&real_mode->lfb_width);
1335         printf("lfb_height           =%x\n", (uint32_t)&real_mode->lfb_height);
1336         printf("lfb_depth            =%x\n", (uint32_t)&real_mode->lfb_depth);
1337         printf("lfb_base             =%x\n", (uint32_t)&real_mode->lfb_base);
1338         printf("lfb_size             =%x\n", (uint32_t)&real_mode->lfb_size);
1339         printf("cl_magic             =%x\n", (uint32_t)&real_mode->cl_magic);
1340         printf("cl_offset            =%x\n", (uint32_t)&real_mode->cl_offset);
1341         printf("lfb_linelength       =%x\n", (uint32_t)&real_mode->lfb_linelength);
1342         printf("red_size             =%x\n", (uint32_t)&real_mode->red_size);
1343         printf("red_pos              =%x\n", (uint32_t)&real_mode->red_pos);
1344         printf("green_size           =%x\n", (uint32_t)&real_mode->green_size);
1345         printf("green_pos            =%x\n", (uint32_t)&real_mode->green_pos);
1346         printf("blue_size            =%x\n", (uint32_t)&real_mode->blue_size);
1347         printf("blue_pos             =%x\n", (uint32_t)&real_mode->blue_pos);
1348         printf("rsvd_size            =%x\n", (uint32_t)&real_mode->rsvd_size);
1349         printf("rsvd_pos             =%x\n", (uint32_t)&real_mode->rsvd_pos);
1350         printf("vesapm_seg           =%x\n", (uint32_t)&real_mode->vesapm_seg);
1351         printf("vesapm_off           =%x\n", (uint32_t)&real_mode->vesapm_off);
1352         printf("pages                =%x\n", (uint32_t)&real_mode->pages);
1353         printf("reserved4            =%x\n", (uint32_t)&real_mode->reserved4);
1354         printf("apm_bios_info        =%x\n", (uint32_t)&real_mode->apm_bios_info);
1355         printf("drive_info           =%x\n", (uint32_t)&real_mode->drive_info);
1356         printf("sys_desc_table       =%x\n", (uint32_t)&real_mode->sys_desc_table);
1357         printf("alt_mem_k            =%x\n", (uint32_t)&real_mode->alt_mem_k);
1358         printf("reserved5            =%x\n", (uint32_t)&real_mode->reserved5);
1359         printf("e820_map_nr          =%x\n", (uint32_t)&real_mode->e820_map_nr);
1360         printf("reserved6            =%x\n", (uint32_t)&real_mode->reserved6);
1361         printf("mount_root_rdonly    =%x\n", (uint32_t)&real_mode->mount_root_rdonly);
1362         printf("reserved7            =%x\n", (uint32_t)&real_mode->reserved7);
1363         printf("ramdisk_flags        =%x\n", (uint32_t)&real_mode->ramdisk_flags);
1364         printf("reserved8            =%x\n", (uint32_t)&real_mode->reserved8);
1365         printf("orig_root_dev        =%x\n", (uint32_t)&real_mode->orig_root_dev);
1366         printf("reserved9            =%x\n", (uint32_t)&real_mode->reserved9);
1367         printf("aux_device_info      =%x\n", (uint32_t)&real_mode->aux_device_info);
1368         printf("reserved10           =%x\n", (uint32_t)&real_mode->reserved10);
1369         printf("param_block_signature=%x\n", (uint32_t)&real_mode->param_block_signature);
1370         printf("param_block_version  =%x\n", (uint32_t)&real_mode->param_block_version);
1371         printf("reserved11           =%x\n", (uint32_t)&real_mode->reserved11);
1372         printf("loader_type          =%x\n", (uint32_t)&real_mode->loader_type);
1373         printf("loader_flags         =%x\n", (uint32_t)&real_mode->loader_flags);
1374         printf("reserved12           =%x\n", (uint32_t)&real_mode->reserved12);
1375         printf("kernel_start         =%x\n", (uint32_t)&real_mode->kernel_start);
1376         printf("initrd_start         =%x\n", (uint32_t)&real_mode->initrd_start);
1377         printf("initrd_size          =%x\n", (uint32_t)&real_mode->initrd_size);
1378         printf("reserved13           =%x\n", (uint32_t)&real_mode->reserved13);
1379         printf("e820_map             =%x\n", (uint32_t)&real_mode->e820_map);
1380         printf("reserved16           =%x\n", (uint32_t)&real_mode->reserved16);
1381         printf("command_line         =%x\n", (uint32_t)&real_mode->command_line);
1382         printf("reserved17           =%x\n", (uint32_t)&real_mode->reserved17);
1383 }
1384
1385 static void print_linux_params(struct param_info *info)
1386 {
1387         int i;
1388
1389         printf("print_linux_params\n");
1390         /* Default screen size */
1391         printf("orig_x           =%x\n", info->real_mode->orig_x);
1392         printf("orig_y           =%x\n", info->real_mode->orig_y);
1393         printf("orig_video_page  =%x\n", info->real_mode->orig_video_page);
1394         printf("orig_video_mode  =%x\n", info->real_mode->orig_video_mode);
1395         printf("orig_video_cols  =%x\n", info->real_mode->orig_video_cols);
1396         printf("orig_video_lines =%x\n", info->real_mode->orig_video_lines);
1397         printf("orig_video_ega_bx=%x\n", info->real_mode->orig_video_ega_bx);
1398         printf("orig_video_isVGA =%x\n", info->real_mode->orig_video_isVGA);
1399         printf("orig_video_points=%x\n", info->real_mode->orig_video_points);
1400
1401
1402         /* System descriptor table... */
1403         printf("sys_dest_table_len=%x\n", info->real_mode->sys_desc_table.length);
1404
1405         /* Memory sizes */
1406         printf("ext_mem_k        =%x\n", info->real_mode->ext_mem_k);
1407         printf("alt_mem_k        =%x\n", info->real_mode->alt_mem_k);
1408         printf("e820_map_nr      =%x\n", info->real_mode->e820_map_nr);
1409         for(i = 0; i < E820MAX; i++) {
1410                 printf("addr[%x]         =%Lx\n",
1411                         i,  info->real_mode->e820_map[i].addr);
1412                 printf("size[%x]         =%Lx\n",
1413                         i, info->real_mode->e820_map[i].size);
1414                 printf("type[%x]         =%Lx\n",
1415                         i, info->real_mode->e820_map[i].type);
1416         }
1417         printf("mount_root_rdonly=%x\n", info->real_mode->mount_root_rdonly);
1418         printf("ramdisk_flags    =%x\n", info->real_mode->ramdisk_flags);
1419         printf("orig_root_dev    =%x\n", info->real_mode->orig_root_dev);
1420         printf("aux_device_info  =%x\n", info->real_mode->aux_device_info);
1421         printf("param_block_signature=%x\n", *((uint32_t *)info->real_mode->param_block_signature));
1422         printf("loader_type      =%x\n", info->real_mode->loader_type);
1423         printf("loader_flags     =%x\n", info->real_mode->loader_flags);
1424         printf("initrd_start     =%x\n", info->real_mode->initrd_start);
1425         printf("initrd_size      =%x\n", info->real_mode->initrd_size);
1426
1427         /* Where I'm putting the command line */
1428         printf("cl_magic         =%x\n", info->real_mode->cl_magic);
1429         printf("cl_offset        =%x\n", info->real_mode->cl_offset);
1430
1431         /* Now print the command line */
1432         printf("command_line     =%s\n", info->real_mode->command_line);
1433 }
1434
1435
1436 #endif
1437
1438 /*
1439  * main
1440  * =============================================================================
1441  */
1442
1443 void initialize_linux_params(struct param_info *info)
1444 {
1445         int len;
1446         /* First the defaults */
1447         memset(info->real_mode, 0, PAGE_SIZE);
1448
1449         /* Default screen size */
1450         info->real_mode->orig_x = 0;
1451         info->real_mode->orig_y = 25;
1452         info->real_mode->orig_video_page = 0;
1453         info->real_mode->orig_video_mode = 0;
1454         info->real_mode->orig_video_cols = 80;
1455         info->real_mode->orig_video_lines = 25;
1456         info->real_mode->orig_video_ega_bx = 0;
1457         info->real_mode->orig_video_isVGA = 1;
1458         info->real_mode->orig_video_points = 16;
1459
1460         /* Fill this in later */
1461         info->real_mode->ext_mem_k = 0;
1462
1463         /* Fill in later... */
1464         info->real_mode->e820_map_nr = 0;
1465
1466         /* Where I'm putting the command line */
1467         info->real_mode->cl_magic = CL_MAGIC_VALUE;
1468         info->real_mode->cl_offset = 2048;
1469
1470         info->real_mode->cmd_line_ptr = info->real_mode->cl_offset + (unsigned long) info->real_mode;
1471
1472         /* Now set the command line */
1473         len = strnlen(info->image->cmdline, sizeof(info->real_mode->command_line) -1);
1474         memcpy(info->real_mode->command_line, info->image->cmdline, len);
1475         info->real_mode->command_line[len] = '\0';
1476
1477         /* from the bios initially */
1478         memset(&info->real_mode->apm_bios_info, 0, sizeof(info->real_mode->apm_bios_info));
1479
1480         memset(&info->real_mode->drive_info, 0, sizeof(info->real_mode->drive_info));
1481
1482         /* forget it for now... */
1483         info->real_mode->sys_desc_table.length = 0;
1484
1485         /* Fill this in later */
1486         info->real_mode->alt_mem_k = 0;
1487         info->real_mode->ext_mem_k = 0;
1488
1489         /* default yes: this can be overridden on the command line */
1490         info->real_mode->mount_root_rdonly = 0xFFFF;
1491
1492         /* old ramdisk options, These really should be command line
1493          * things...
1494          */
1495         info->real_mode->ramdisk_flags = info->image->ramdisk_flags;
1496
1497         /* default to /dev/hda.
1498          * Override this on the command line if necessary
1499          */
1500         info->real_mode->orig_root_dev = info->image->root_dev;
1501
1502         /* Originally from the bios? */
1503         info->real_mode->aux_device_info = 0;
1504
1505         /* Boot block magic */
1506         memcpy(info->real_mode->param_block_signature, "HdrS", 4);
1507         info->real_mode->param_block_version = 0x0201;
1508
1509         /* Say I'm a kernel boot loader */
1510         info->real_mode->loader_type = (LOADER_TYPE_KERNEL << 4) + 0 /* version */;
1511
1512         /* No loader flags */
1513         info->real_mode->loader_flags = 0;
1514
1515         /* Ramdisk address and size ... */
1516         info->real_mode->initrd_start = 0;
1517         info->real_mode->initrd_size = 0;
1518         if (info->image->initrd_size) {
1519                 info->real_mode->initrd_start = info->image->initrd_start;
1520                 info->real_mode->initrd_size = info->image->initrd_size;
1521         }
1522
1523         /* Now remember those things that I need */
1524         info->need_mem_sizes = 1;
1525 }
1526
1527 void *convert_params(unsigned type, void *data, void *param, void *image)
1528 {
1529         struct param_info info;
1530 #if 0
1531         printf("hello world\n");
1532 #endif
1533         info.real_mode = faked_real_mode;
1534         info.type  = type;
1535         info.data  = data;
1536         info.param = param;
1537         info.image = image;
1538         initialize_linux_params(&info);
1539         query_bootloader_param_class(&info);
1540         query_firmware_class(&info);
1541         query_firmware_values(&info);
1542         query_bootloader_values(&info);
1543
1544         /* Do the hardware setup that linux might forget... */
1545         hardware_setup(&info);
1546
1547         /* Print some debugging information */
1548 #if 0
1549         printf("EXT_MEM_K=%x\n", info.real_mode->ext_mem_k);
1550         printf("ALT_MEM_K=%x\n", info.real_mode->alt_mem_k);
1551 #endif
1552 #if 0
1553         print_offsets();
1554         print_linux_params(&info);
1555 #endif
1556 #if 0
1557         printf("info.real_mode = 0x%x\n", info.real_mode );
1558         printf("Jumping to Linux\n");
1559 #endif
1560         return info.real_mode;
1561 }
1562