5 #include "uniform_boot.h"
6 #include "linuxbios_tables.h"
9 #define STACK_SIZE (4096)
11 #define __unused __attribute__ ((unused))
13 long user_stack [STACK_SIZE] = { 0 };
15 unsigned long * stack_start = & user_stack[STACK_SIZE];
17 /* FIXME expand on drive_info_)struct... */
18 struct drive_info_struct {
21 struct sys_desc_table {
27 * These are set up by the setup-routine at boot-time:
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 */
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 */
66 #define PAGE_SIZE 4096
69 #define E820MAP 0x2d0 /* our map */
70 #define E820MAX 32 /* number of entries in E820MAP */
71 #define E820NR 0x1e8 /* # entries in E820MAP */
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 */
79 #define E820_RESERVED 2
80 #define E820_ACPI 3 /* usable as RAM once ACPI tables have been read */
86 struct e820entry map[E820MAX];
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 */
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 */
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 */
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 */
175 uint16_t heap_end_ptr; /* 0x224 */
176 uint8_t reserved14[2]; /* 0x226 */
178 uint32_t cmd_line_ptr; /* 0x228 */
180 uint32_t initrd_addr_max; /* 0x22c */
182 uint32_t kernel_alignment; /* 0x230 */
183 uint8_t relocateable_kernel; /* 0x234 */
184 uint8_t reserved15[0x2d0 - 0x235]; /* 0x235 */
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 */
193 /* Keep track of which information I need to acquire. */
198 struct image_parameters *image;
199 struct parameters *real_mode;
200 /* bootloader type */
202 int has_uniform_boot;
207 struct lb_header *lb_table;
208 /* machine information needed */
212 * This is set up by the setup-routine at boot-time
219 #define memzero(s, n) memset ((s), 0, (n))
222 /* FIXME handle systems with large EBDA's */
223 static struct parameters *faked_real_mode = (void *)REAL_MODE_DATA_LOC;
229 * =============================================================================
234 #define TTYS0_LSR (TTYS0+0x05)
235 #define TTYS0_TBR (TTYS0+0x00)
237 static void ttys0_tx_byte(unsigned byte)
239 /* Wait until I can send a byte */
240 while((inb(TTYS0_LSR) & 0x20) == 0)
242 outb(byte, TTYS0_TBR);
243 /* Wait until the byte is transmitted */
244 while(!(inb(TTYS0_LSR) & 0x40))
247 static void put_char_serial(int c)
255 static void putchar(int c)
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))
269 /**************************************************************************
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
285 Note: width specification not supported
286 **************************************************************************/
287 static void printf(const char *fmt, ...)
292 for ( ; *fmt != '\0'; ++fmt) {
298 for(p = va_arg(args, char *); *p != '\0'; p++)
301 else { /* Length of item is bounded */
302 char tmp[40], *q = tmp;
303 int shift = INT_SHIFT;
305 shift = LONG_LONG_SHIFT;
308 else if (*fmt == 'l') {
312 else if (*fmt == 'h') {
322 * Before each format q points to tmp buffer
323 * After each format q points past end of item
325 if ((*fmt | 0x20) == 'x') {
326 /* With x86 gcc, sizeof(long) == sizeof(int) */
327 unsigned long long h;
329 if (shift > LONG_SHIFT) {
330 h = va_arg(args, unsigned long long);
332 else if (shift > INT_SHIFT) {
333 h = va_arg(args, unsigned long);
335 h = va_arg(args, unsigned int);
337 ncase = (*fmt & 0x20);
338 for ( ; shift >= 0; shift -= 4)
339 *q++ = "0123456789ABCDEF"[(h >> shift) & 0xF] | ncase;
341 else if (*fmt == 'd') {
344 if (shift > LONG_SHIFT) {
345 i = va_arg(args, long long);
347 else if (shift > INT_SHIFT) {
348 i = va_arg(args, long);
350 i = va_arg(args, int);
356 p = q; /* save beginning of digits */
358 *q++ = '0' + (i % 10);
361 /* reverse digits, stop in middle */
362 r = q; /* don't alter q */
369 else if (*fmt == 'c')
370 *q++ = va_arg(args, int);
373 /* now output the saved string */
374 for (p = tmp; p < q; ++p)
383 * =============================================================================
387 size_t strnlen(const char *s, size_t max)
390 while(len < max && *s) {
397 void* memset(void* s, int c, size_t n)
402 for (i=0;i<n;i++) ss[i] = c;
406 void* memcpy(void *dest, const void *src, size_t len)
410 const unsigned char *s;
414 for (i=0; i < len; i++)
420 int memcmp(void *src1, void *src2, size_t len)
422 unsigned char *s1, *s2;
426 for(i = 0; i < len; i++) {
437 * =============================================================================
441 static unsigned long checksum_partial(unsigned long sum,
442 void *addr, unsigned long length)
450 /* In the most straight forward way possible,
451 * compute an ip style checksum.
455 for(i = 0; i < length; i++) {
461 /* Add the new value */
463 /* Wrap around the carry */
465 sum = (sum + (sum >> 16)) & 0xFFFF;
468 value.byte[0] = sum & 0xff;
469 value.byte[1] = (sum >> 8) & 0xff;
470 return value.word & 0xFFFF;
474 static unsigned long checksum_final(unsigned long partial)
476 return (~partial) & 0xFFFF;
479 static unsigned long compute_checksum(void *vaddr, unsigned long length)
481 return checksum_final(checksum_partial(0, vaddr, length));
486 * =============================================================================
490 void append_command_line(struct parameters *real_mode, char *arg, int arg_bytes)
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;
499 /* No room to append anything :( */
502 /* Add a space in between strings */
504 /* Append the added command line */
505 max = sizeof(real_mode->command_line) - 1;
506 if (max > arg_bytes) {
509 len = strnlen(arg, max);
510 memcpy(dest, arg, len);
512 /* Null terminate the string */
516 static void set_memsize_k(struct parameters *real_mode, unsigned long mem_k)
518 /* ALT_MEM_K maxes out at 4GB */
519 if (mem_k > 0x3fffff) {
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 */
532 static void add_e820_map(struct parameters *real_mode,
533 unsigned long long addr, unsigned long long size,
536 unsigned long long high;
539 i = real_mode->e820_map_nr;
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++;
546 /* policy I assume that for the legacy memory
547 * variables memory is contiguous.
549 if (type == E820_RAM) {
551 if (high >= 0x40000000000ULL) {
556 set_memsize_k(real_mode, mem_k);
562 * =============================================================================
565 #define MULTI_MEM_DEBUG 0
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)
571 #define multi_puts(x)
572 #define multi_put_hex(x)
573 #define multi_put_lhex(x)
574 #endif /* MULTI_MEM_DEBUG */
576 /* Multiboot Specification */
577 struct multiboot_mods {
580 unsigned char *string;
584 struct memory_segment {
585 unsigned long long addr;
586 unsigned long long size;
590 struct multiboot_info {
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
601 unsigned char boot_device[4];
604 struct multiboot_mods *mods_addr;
609 unsigned mmap_length;
610 struct memory_segment *mmap_addr;
613 #define MULTIBOOT_MAX_COMMAND_LINE 0xFFFFFFFF
615 static void convert_multiboot_memmap(
616 struct parameters *real_mode,
617 struct multiboot_info *info)
621 #define next_seg(seg, size) ((struct memory_segment *)((char *)(seg) + (size)))
622 struct memory_segment *seg, *end;
624 seg = info->mmap_addr;
625 end = (void *)(((char *)seg) + info->mmap_length);
626 size_addr = (unsigned *)(((char *)seg) - 4);
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);
637 multi_put_lhex(seg->addr);
644 multi_puts("ACPI data");
647 multi_puts("ACPI NVS");
651 multi_puts("reserved");
655 add_e820_map(real_mode, seg->addr, seg->size, seg->type);
660 static void convert_multiboot(
661 struct param_info *info, struct multiboot_info *mb_info)
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));
667 if (mb_info->flags & MULTIBOOT_CMDLINE_VALID) {
668 append_command_line(info->real_mode, mb_info->command_line,
669 MULTIBOOT_MAX_COMMAND_LINE);
671 if (info->need_mem_sizes && (mb_info->flags & MULTIBOOT_MMAP_VALID)) {
672 convert_multiboot_memmap(info->real_mode, mb_info);
674 if (mb_info->flags & (MULTIBOOT_MEM_VALID | MULTIBOOT_MMAP_VALID)) {
675 info->need_mem_sizes = 0;
681 * Uniform Boot Environment
682 * =============================================================================
685 #define UBE_MEM_DEBUG 0
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)
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)
702 entries = (mem->size - sizeof(*mem))/sizeof(mem->map[0]);
703 for(i = 0; (i < entries) && (i < E820MAX); i++) {
705 ube_puts("ube-mem: ");
706 ube_put_lhex(mem->map[i].size);
708 ube_put_lhex(mem->map[i].start);
710 switch(mem->map[i].type) {
717 ube_puts("ACPI data");
721 ube_puts("ACPI NVS");
723 case UBE_MEM_RESERVED:
725 type = E820_RESERVED;
726 ube_puts("reserved");
730 add_e820_map(real_mode,
731 mem->map[i].start, mem->map[i].size, type);
735 static void convert_uniform_boot(struct param_info *info,
736 struct uniform_boot_header *header)
738 /* Uniform boot environment */
739 unsigned long env_bytes;
741 if (header->arg_bytes) {
742 append_command_line(info->real_mode, (void *)(header->arg), header->arg_bytes);
744 env = (void *)(header->env);
745 env_bytes = header->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;
756 env_bytes -= record->size;
765 * =============================================================================
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.
780 static void setup_i8259(void)
782 outb(0x11, 0x20); /*! initialization sequence to 8259A-1*/
783 outb(0x11, 0xA0); /*! and to 8259A-2*/
785 outb(0x20, 0x21); /*! start of hardware int's (0x20)*/
786 outb(0x28, 0xA1); /*! start of hardware int's 2 (0x28)*/
788 outb(0x04, 0x21); /*! 8259-1 is master*/
789 outb(0x02, 0xA1); /*! 8259-2 is slave*/
791 outb(0x01, 0x21); /*! 8086 mode for both*/
794 outb(0xFF, 0xA1); /*! mask off all interrupts for now*/
795 outb(0xFB, 0x21); /*! mask all irq's but irq2 which is cascaded*/
798 static void hardware_setup(struct param_info *info __unused)
803 /* Make sure any coprocessor is properly reset.. */
813 * =============================================================================
816 static int count_elf_notes(Elf_Bhdr *bhdr)
818 unsigned char *note, *end;
821 note = ((char *)bhdr) + sizeof(*bhdr);
822 end = ((char *)bhdr) + bhdr->b_size;
824 printf("count_elf_notes %lx\n", (unsigned long)bhdr);
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);
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);
849 static Elf_Nhdr *find_elf_note(Elf_Bhdr *bhdr,
850 Elf_Word namesz, unsigned char *name, Elf_Word type)
852 unsigned char *note, *end;
853 note = ((char *)bhdr) + sizeof(*bhdr);
854 end = ((char *)bhdr) + bhdr->b_size;
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);
864 if ((hdr->n_type == type) &&
865 (hdr->n_namesz == namesz) &&
866 (memcmp(n_name, name, namesz) == 0)) {
874 static void convert_elf_command_line(struct param_info *info,
875 Elf_Word descsz, unsigned char *desc)
877 append_command_line(info->real_mode, desc, descsz);
884 void (*convert)(struct param_info *info, Elf_Word descsz, unsigned char *desc);
887 { 0, "", EBN_COMMAND_LINE, convert_elf_command_line },
890 static void convert_elf_boot(struct param_info *info, Elf_Bhdr *bhdr)
892 unsigned char *note, *end;
893 note = ((char *)bhdr) + sizeof(*bhdr);
894 end = ((char *)bhdr) + bhdr->b_size;
897 unsigned char *n_name, *n_desc, *next;
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);
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);
919 * =============================================================================
922 #define LB_MEM_DEBUG 0
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)
929 #define lb_put_hex(x)
930 #define lb_put_lhex(x)
931 #endif /* LB_MEM_DEBUG */
933 static unsigned count_lb_records(void *start, unsigned long length)
935 struct lb_record *rec;
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)) {
948 static struct lb_header *__find_lb_table(void *start, void *end)
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) ==
971 static int find_lb_table(struct param_info *info)
973 struct lb_header *head;
976 /* First try at address 0 */
977 head = __find_lb_table((void *)0x00000, (void *)0x1000);
980 /* Then try at address 0xf0000 */
981 head = __find_lb_table((void *)0xf0000, (void *)0x100000);
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);
991 info->has_linuxbios = 1;
992 info->lb_table = head;
998 static void convert_lb_memory(struct param_info *info, struct lb_memory *mem)
1002 entries = (mem->size - sizeof(*mem))/sizeof(mem->map[0]);
1003 for(i = 0; (i < entries) && (i < E820MAX); i++) {
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);
1012 switch(mem->map[i].type) {
1018 type = E820_RESERVED;
1019 lb_puts("reserved");
1023 add_e820_map(info->real_mode,
1024 mem->map[i].start, mem->map[i].size, type);
1026 info->need_mem_sizes = 0;
1029 static void query_lb_values(struct param_info *info)
1031 struct lb_header *head;
1032 struct lb_record *rec;
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)) {
1043 struct lb_memory *mem;
1044 mem = (struct lb_memory *) rec;
1045 convert_lb_memory(info, mem);
1056 * =============================================================================
1058 #define PC_MEM_DEBUG 0
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)
1065 #define pc_put_hex(x)
1066 #define pc_put_lhex(x)
1067 #endif /* PC_MEM_DEBUG */
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);
1078 struct e820entry map[E820MAX];
1081 static struct meminfo meminfo;
1082 static void get_meminfo(struct param_info *info)
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);
1100 info->need_mem_sizes = 0;
1103 pc_puts("ACPI data");
1106 pc_puts("ACPI NVS");
1110 pc_puts("reserved");
1114 add_e820_map(info->real_mode,
1115 seg->addr, seg->size, seg->type);
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;
1124 static void query_pcbios_values(struct param_info *info)
1131 * =============================================================================
1135 static void query_bootloader_param_class(struct param_info *info)
1137 int has_bootloader_type = 0;
1139 if (!has_bootloader_type && (info->type == 0x2BADB002)) {
1140 /* Orignal multiboot specification */
1141 info->has_multiboot = 1;
1142 has_bootloader_type = 1;
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;
1154 printf("Bad uniform boot header checksum!\n");
1157 if (info->type == ELF_BHDR_MAGIC) {
1160 if (info->param && (info->param->b_signature == ELF_BHDR_MAGIC)) {
1163 if (!has_bootloader_type && hdr) {
1164 /* Good ELF boot proposal... */
1165 unsigned long checksum;
1168 if (hdr->b_checksum != 0) {
1169 checksum = compute_checksum(hdr, hdr->b_size);
1171 count = count_elf_notes(hdr);
1172 if ((hdr->b_signature == ELF_BHDR_MAGIC) &&
1174 hdr->b_records == count) {
1175 info->has_elf_boot = 1;
1177 has_bootloader_type = 1;
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);
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);
1197 static void query_bootloader_values(struct param_info *info)
1199 if (info->has_multiboot) {
1200 convert_multiboot(info, info->data);
1202 else if (info->has_uniform_boot) {
1203 convert_uniform_boot(info, info->data);
1205 else if (info->has_elf_boot) {
1206 convert_elf_boot(info, info->param);
1212 * =============================================================================
1215 static int bootloader_query_firmware_class(struct param_info *info)
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 */
1224 detected_firmware_type = 0;
1227 hdr = find_elf_note(info->param, 0, 0, EBN_FIRMWARE_TYPE);
1229 /* If I'm not explicitly told the firmware type
1230 * do my best to guess it for myself.
1232 detected_firmware_type = 0;
1235 n_name = note + sizeof(*hdr);
1236 n_desc = n_name + ((hdr->n_namesz + 3) & ~3);
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;
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..
1250 detected_firmware_type = find_lb_table(info);
1252 if (!detected_firmware_type && hdr &&
1253 (hdr->n_descsz == 0)) {
1254 /* No firmware is present */
1255 detected_firmware_type = 1;
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;
1263 if (!detected_firmware_type && hdr) {
1264 printf("Unknown firmware type: %s\n", n_desc);
1266 return detected_firmware_type;
1269 static void query_firmware_class(struct param_info *info)
1271 int detected_firmware_type = 0;
1273 /* First say I have no firmware at all... */
1274 info->has_pcbios = 0;
1275 info->has_linuxbios = 0;
1277 /* See if the bootloader has told us what
1278 * kind of firmware we are running on.
1280 detected_firmware_type = bootloader_query_firmware_class(info);
1282 /* See if we can detect linuxbios. */
1283 if (!detected_firmware_type) {
1284 detected_firmware_type = find_lb_table(info);
1287 if (!detected_firmware_type) {
1288 /* if all else fails assume a standard pcbios... */
1289 info->has_pcbios = 1;
1292 /* Now print out the firmware type... */
1293 printf("Firmware type:");
1294 if (info->has_linuxbios) {
1295 printf(" LinuxBIOS");
1297 if (info->has_pcbios) {
1303 static void query_firmware_values(struct param_info *info)
1305 if (info->has_linuxbios) {
1306 query_lb_values(info);
1308 if (info->has_pcbios) {
1309 query_pcbios_values(info);
1316 * =============================================================================
1320 static void print_offsets(void)
1322 struct parameters *real_mode = 0;
1323 printf("print_offsets\n");
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);
1388 static void print_linux_params(struct param_info *info)
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);
1405 /* System descriptor table... */
1406 printf("sys_dest_table_len=%x\n", info->real_mode->sys_desc_table.length);
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);
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);
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);
1434 /* Now print the command line */
1435 printf("command_line =%s\n", info->real_mode->command_line);
1443 * =============================================================================
1446 void initialize_linux_params(struct param_info *info)
1449 /* First the defaults */
1450 memset(info->real_mode, 0, PAGE_SIZE);
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;
1463 /* Fill this in later */
1464 info->real_mode->ext_mem_k = 0;
1466 /* Fill in later... */
1467 info->real_mode->e820_map_nr = 0;
1469 /* Where I'm putting the command line */
1470 info->real_mode->cl_magic = CL_MAGIC_VALUE;
1471 info->real_mode->cl_offset = 2048;
1473 info->real_mode->cmd_line_ptr = info->real_mode->cl_offset + (unsigned long) info->real_mode;
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';
1480 /* from the bios initially */
1481 memset(&info->real_mode->apm_bios_info, 0, sizeof(info->real_mode->apm_bios_info));
1483 memset(&info->real_mode->drive_info, 0, sizeof(info->real_mode->drive_info));
1485 /* forget it for now... */
1486 info->real_mode->sys_desc_table.length = 0;
1488 /* Fill this in later */
1489 info->real_mode->alt_mem_k = 0;
1490 info->real_mode->ext_mem_k = 0;
1492 /* default yes: this can be overridden on the command line */
1493 info->real_mode->mount_root_rdonly = 0xFFFF;
1495 /* old ramdisk options, These really should be command line
1498 info->real_mode->ramdisk_flags = info->image->ramdisk_flags;
1500 /* default to /dev/hda.
1501 * Override this on the command line if necessary
1503 info->real_mode->orig_root_dev = info->image->root_dev;
1505 /* Originally from the bios? */
1506 info->real_mode->aux_device_info = 0;
1508 /* Boot block magic */
1509 memcpy(info->real_mode->param_block_signature, "HdrS", 4);
1510 info->real_mode->param_block_version = 0x0201;
1512 /* Say I'm a kernel boot loader */
1513 info->real_mode->loader_type = (LOADER_TYPE_KERNEL << 4) + 0 /* version */;
1515 /* No loader flags */
1516 info->real_mode->loader_flags = 0;
1518 /* Set it to 16M, instead of 0 which means 4G */
1519 info->real_mode->kernel_alignment = 16*1024*1024;
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;
1529 /* Now remember those things that I need */
1530 info->need_mem_sizes = 1;
1533 void *convert_params(unsigned type, void *data, void *param, void *image)
1535 struct param_info info;
1537 printf("hello world\n");
1539 info.real_mode = faked_real_mode;
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);
1550 /* Do the hardware setup that linux might forget... */
1551 hardware_setup(&info);
1553 /* Print some debugging information */
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);
1560 print_linux_params(&info);
1563 printf("info.real_mode = 0x%x\n", info.real_mode );
1564 printf("Jumping to Linux\n");
1566 return info.real_mode;