aboutsummaryrefslogtreecommitdiff
path: root/util/mkelfImage/linux-i386/convert_params.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/mkelfImage/linux-i386/convert_params.c')
-rw-r--r--util/mkelfImage/linux-i386/convert_params.c1555
1 files changed, 1555 insertions, 0 deletions
diff --git a/util/mkelfImage/linux-i386/convert_params.c b/util/mkelfImage/linux-i386/convert_params.c
new file mode 100644
index 0000000000..501adfbb11
--- /dev/null
+++ b/util/mkelfImage/linux-i386/convert_params.c
@@ -0,0 +1,1555 @@
+#include <stdarg.h>
+#include <limits.h>
+#include "arch/io.h"
+#include "stdint.h"
+#include "uniform_boot.h"
+#include "linuxbios_tables.h"
+#include "elf_boot.h"
+#include "convert.h"
+#define STACK_SIZE (4096)
+
+#define __unused __attribute__ ((unused))
+
+long user_stack [STACK_SIZE] = { 0 };
+
+unsigned long * stack_start = & user_stack[STACK_SIZE];
+
+/* FIXME expand on drive_info_)struct... */
+struct drive_info_struct {
+ uint8_t dummy[32];
+};
+struct sys_desc_table {
+ uint16_t length;
+ uint8_t table[318];
+};
+
+/*
+ * These are set up by the setup-routine at boot-time:
+ */
+
+struct screen_info {
+ uint8_t orig_x; /* 0x00 */
+ uint8_t orig_y; /* 0x01 */
+ uint16_t dontuse1; /* 0x02 -- EXT_MEM_K sits here */
+ uint16_t orig_video_page; /* 0x04 */
+ uint8_t orig_video_mode; /* 0x06 */
+ uint8_t orig_video_cols; /* 0x07 */
+ uint16_t unused2; /* 0x08 */
+ uint16_t orig_video_ega_bx; /* 0x0a */
+ uint16_t unused3; /* 0x0c */
+ uint8_t orig_video_lines; /* 0x0e */
+ uint8_t orig_video_isVGA; /* 0x0f */
+ uint16_t orig_video_points; /* 0x10 */
+
+ /* VESA graphic mode -- linear frame buffer */
+ uint16_t lfb_width; /* 0x12 */
+ uint16_t lfb_height; /* 0x14 */
+ uint16_t lfb_depth; /* 0x16 */
+ uint32_t lfb_base; /* 0x18 */
+ uint32_t lfb_size; /* 0x1c */
+ uint16_t dontuse2, dontuse3; /* 0x20 -- CL_MAGIC and CL_OFFSET here */
+ uint16_t lfb_linelength; /* 0x24 */
+ uint8_t red_size; /* 0x26 */
+ uint8_t red_pos; /* 0x27 */
+ uint8_t green_size; /* 0x28 */
+ uint8_t green_pos; /* 0x29 */
+ uint8_t blue_size; /* 0x2a */
+ uint8_t blue_pos; /* 0x2b */
+ uint8_t rsvd_size; /* 0x2c */
+ uint8_t rsvd_pos; /* 0x2d */
+ uint16_t vesapm_seg; /* 0x2e */
+ uint16_t vesapm_off; /* 0x30 */
+ uint16_t pages; /* 0x32 */
+};
+
+
+#define PAGE_SIZE 4096
+
+
+#define E820MAP 0x2d0 /* our map */
+#define E820MAX 32 /* number of entries in E820MAP */
+#define E820NR 0x1e8 /* # entries in E820MAP */
+
+
+struct e820entry {
+ unsigned long long addr; /* start of memory segment */
+ unsigned long long size; /* size of memory segment */
+ unsigned long type; /* type of memory segment */
+#define E820_RAM 1
+#define E820_RESERVED 2
+#define E820_ACPI 3 /* usable as RAM once ACPI tables have been read */
+#define E820_NVS 4
+};
+
+struct e820map {
+ int nr_map;
+ struct e820entry map[E820MAX];
+};
+
+
+struct apm_bios_info {
+ uint16_t version; /* 0x40 */
+ uint16_t cseg; /* 0x42 */
+ uint32_t offset; /* 0x44 */
+ uint16_t cseg_16; /* 0x48 */
+ uint16_t dseg; /* 0x4a */
+ uint16_t flags; /* 0x4c */
+ uint16_t cseg_len; /* 0x4e */
+ uint16_t cseg_16_len; /* 0x50 */
+ uint16_t dseg_len; /* 0x52 */
+ uint8_t reserved[44]; /* 0x54 */
+};
+
+
+struct parameters {
+ uint8_t orig_x; /* 0x00 */
+ uint8_t orig_y; /* 0x01 */
+ uint16_t ext_mem_k; /* 0x02 -- EXT_MEM_K sits here */
+ uint16_t orig_video_page; /* 0x04 */
+ uint8_t orig_video_mode; /* 0x06 */
+ uint8_t orig_video_cols; /* 0x07 */
+ uint16_t unused2; /* 0x08 */
+ uint16_t orig_video_ega_bx; /* 0x0a */
+ uint16_t unused3; /* 0x0c */
+ uint8_t orig_video_lines; /* 0x0e */
+ uint8_t orig_video_isVGA; /* 0x0f */
+ uint16_t orig_video_points; /* 0x10 */
+
+ /* VESA graphic mode -- linear frame buffer */
+ uint16_t lfb_width; /* 0x12 */
+ uint16_t lfb_height; /* 0x14 */
+ uint16_t lfb_depth; /* 0x16 */
+ uint32_t lfb_base; /* 0x18 */
+ uint32_t lfb_size; /* 0x1c */
+ uint16_t cl_magic; /* 0x20 */
+#define CL_MAGIC_VALUE 0xA33F
+ uint16_t cl_offset; /* 0x22 */
+ uint16_t lfb_linelength; /* 0x24 */
+ uint8_t red_size; /* 0x26 */
+ uint8_t red_pos; /* 0x27 */
+ uint8_t green_size; /* 0x28 */
+ uint8_t green_pos; /* 0x29 */
+ uint8_t blue_size; /* 0x2a */
+ uint8_t blue_pos; /* 0x2b */
+ uint8_t rsvd_size; /* 0x2c */
+ uint8_t rsvd_pos; /* 0x2d */
+ uint16_t vesapm_seg; /* 0x2e */
+ uint16_t vesapm_off; /* 0x30 */
+ uint16_t pages; /* 0x32 */
+ uint8_t reserved4[12]; /* 0x34 -- 0x3f reserved for future expansion */
+
+ struct apm_bios_info apm_bios_info; /* 0x40 */
+ struct drive_info_struct drive_info; /* 0x80 */
+ struct sys_desc_table sys_desc_table; /* 0xa0 */
+ uint32_t alt_mem_k; /* 0x1e0 */
+ uint8_t reserved5[4]; /* 0x1e4 */
+ uint8_t e820_map_nr; /* 0x1e8 */
+ uint8_t reserved6[9]; /* 0x1e9 */
+ uint16_t mount_root_rdonly; /* 0x1f2 */
+ uint8_t reserved7[4]; /* 0x1f4 */
+ uint16_t ramdisk_flags; /* 0x1f8 */
+#define RAMDISK_IMAGE_START_MASK 0x07FF
+#define RAMDISK_PROMPT_FLAG 0x8000
+#define RAMDISK_LOAD_FLAG 0x4000
+ uint8_t reserved8[2]; /* 0x1fa */
+ uint16_t orig_root_dev; /* 0x1fc */
+ uint8_t reserved9[1]; /* 0x1fe */
+ uint8_t aux_device_info; /* 0x1ff */
+ uint8_t reserved10[2]; /* 0x200 */
+ uint8_t param_block_signature[4]; /* 0x202 */
+ uint16_t param_block_version; /* 0x206 */
+ uint8_t reserved11[8]; /* 0x208 */
+ uint8_t loader_type; /* 0x210 */
+#define LOADER_TYPE_LOADLIN 1
+#define LOADER_TYPE_BOOTSECT_LOADER 2
+#define LOADER_TYPE_SYSLINUX 3
+#define LOADER_TYPE_ETHERBOOT 4
+#define LOADER_TYPE_KERNEL 5
+ uint8_t loader_flags; /* 0x211 */
+ uint8_t reserved12[2]; /* 0x212 */
+ uint32_t kernel_start; /* 0x214 */
+ uint32_t initrd_start; /* 0x218 */
+ uint32_t initrd_size; /* 0x21c */
+ uint8_t reserved13[4]; /* 0x220 */
+ /* 2.01+ */
+ uint16_t heap_end_ptr; /* 0x224 */
+ uint8_t reserved14[2]; /* 0x226 */
+ /* 2.02+ */
+ uint32_t cmd_line_ptr; /* 0x228 */
+ /* 2.03+ */
+ uint32_t initrd_addr_max; /* 0x22c */
+ uint8_t reserved15[0x2d0 - 0x230]; /* 0x230 */
+
+ struct e820entry e820_map[E820MAX]; /* 0x2d0 */
+ uint8_t reserved16[688]; /* 0x550 */
+#define COMMAND_LINE_SIZE 256
+ uint8_t command_line[COMMAND_LINE_SIZE]; /* 0x800 */
+ uint8_t reserved17[1792]; /* 0x900 - 0x1000 */
+};
+
+/* Keep track of which information I need to acquire. */
+struct param_info {
+ unsigned type;
+ void *data;
+ Elf_Bhdr *param;
+ struct image_parameters *image;
+ struct parameters *real_mode;
+ /* bootloader type */
+ int has_multiboot;
+ int has_uniform_boot;
+ int has_elf_boot;
+ /* firmware type */
+ int has_pcbios;
+ int has_linuxbios;
+ struct lb_header *lb_table;
+ /* machine information needed */
+ int need_mem_sizes;
+};
+/*
+ * This is set up by the setup-routine at boot-time
+ */
+
+
+#undef memcmp
+#undef memset
+#undef memcpy
+#define memzero(s, n) memset ((s), 0, (n))
+
+
+/* FIXME handle systems with large EBDA's */
+static struct parameters *faked_real_mode = (void *)REAL_MODE_DATA_LOC;
+
+
+
+/*
+ * Output
+ * =============================================================================
+ */
+
+/* Base Address */
+#define TTYS0 0x3f8
+#define TTYS0_LSR (TTYS0+0x05)
+#define TTYS0_TBR (TTYS0+0x00)
+
+static void ttys0_tx_byte(unsigned byte)
+{
+ /* Wait until I can send a byte */
+ while((inb(TTYS0_LSR) & 0x20) == 0)
+ ;
+ outb(byte, TTYS0_TBR);
+ /* Wait until the byte is transmitted */
+ while(!(inb(TTYS0_LSR) & 0x40))
+ ;
+}
+static void put_char_serial(int c)
+{
+ if (c == '\n') {
+ ttys0_tx_byte('\r');
+ }
+ ttys0_tx_byte(c);
+}
+
+static void putchar(int c)
+{
+#if 0
+ put_char_video(c);
+#endif
+ put_char_serial(c);
+}
+
+#define LONG_LONG_SHIFT ((int)((sizeof(unsigned long long)*CHAR_BIT) - 4))
+#define LONG_SHIFT ((int)((sizeof(unsigned long)*CHAR_BIT) - 4))
+#define INT_SHIFT ((int)((sizeof(unsigned int)*CHAR_BIT) - 4))
+#define SHRT_SHIFT ((int)((sizeof(unsigned short)*CHAR_BIT) - 4))
+#define CHAR_SHIFT ((int)((sizeof(unsigned char)*CHAR_BIT) - 4))
+
+/**************************************************************************
+PRINTF and friends
+
+ Formats:
+ %x - 4 bytes int (8 hex digits, lower case)
+ %X - 4 bytes int (8 hex digits, upper case)
+ %lx - 8 bytes long (16 hex digits, lower case)
+ %lX - 8 bytes long (16 hex digits, upper case)
+ %hx - 2 bytes int (4 hex digits, lower case)
+ %hX - 2 bytes int (4 hex digits, upper case)
+ %hhx - 1 byte int (2 hex digits, lower case)
+ %hhX - 1 byte int (2 hex digits, upper case)
+ - optional # prefixes 0x or 0X
+ %d - decimal int
+ %c - char
+ %s - string
+ Note: width specification not supported
+**************************************************************************/
+static void printf(const char *fmt, ...)
+{
+ va_list args;
+ char *p;
+ va_start(args, fmt);
+ for ( ; *fmt != '\0'; ++fmt) {
+ if (*fmt != '%') {
+ putchar(*fmt);
+ continue;
+ }
+ if (*++fmt == 's') {
+ for(p = va_arg(args, char *); *p != '\0'; p++)
+ putchar(*p);
+ }
+ else { /* Length of item is bounded */
+ char tmp[40], *q = tmp;
+ int shift = INT_SHIFT;
+ if (*fmt == 'L') {
+ shift = LONG_LONG_SHIFT;
+ fmt++;
+ }
+ else if (*fmt == 'l') {
+ shift = LONG_SHIFT;
+ fmt++;
+ }
+ else if (*fmt == 'h') {
+ shift = SHRT_SHIFT;
+ fmt++;
+ if (*fmt == 'h') {
+ shift = CHAR_SHIFT;
+ fmt++;
+ }
+ }
+
+ /*
+ * Before each format q points to tmp buffer
+ * After each format q points past end of item
+ */
+ if ((*fmt | 0x20) == 'x') {
+ /* With x86 gcc, sizeof(long) == sizeof(int) */
+ unsigned long long h;
+ int ncase;
+ if (shift > LONG_SHIFT) {
+ h = va_arg(args, unsigned long long);
+ }
+ else if (shift > INT_SHIFT) {
+ h = va_arg(args, unsigned long);
+ } else {
+ h = va_arg(args, unsigned int);
+ }
+ ncase = (*fmt & 0x20);
+ for ( ; shift >= 0; shift -= 4)
+ *q++ = "0123456789ABCDEF"[(h >> shift) & 0xF] | ncase;
+ }
+ else if (*fmt == 'd') {
+ char *r;
+ long i;
+ if (shift > LONG_SHIFT) {
+ i = va_arg(args, long long);
+ }
+ else if (shift > INT_SHIFT) {
+ i = va_arg(args, long);
+ } else {
+ i = va_arg(args, int);
+ }
+ if (i < 0) {
+ *q++ = '-';
+ i = -i;
+ }
+ p = q; /* save beginning of digits */
+ do {
+ *q++ = '0' + (i % 10);
+ i /= 10;
+ } while (i);
+ /* reverse digits, stop in middle */
+ r = q; /* don't alter q */
+ while (--r > p) {
+ i = *r;
+ *r = *p;
+ *p++ = i;
+ }
+ }
+ else if (*fmt == 'c')
+ *q++ = va_arg(args, int);
+ else
+ *q++ = *fmt;
+ /* now output the saved string */
+ for (p = tmp; p < q; ++p)
+ putchar(*p);
+ }
+ }
+ va_end(args);
+}
+
+/*
+ * String Functions
+ * =============================================================================
+ */
+
+
+size_t strnlen(const char *s, size_t max)
+{
+ size_t len = 0;
+ while(len < max && *s) {
+ len++;
+ s++;
+ }
+ return len;
+}
+
+void* memset(void* s, int c, size_t n)
+{
+ size_t i;
+ char *ss = (char*)s;
+
+ for (i=0;i<n;i++) ss[i] = c;
+ return s;
+}
+
+void* memcpy(void *dest, const void *src, size_t len)
+{
+ size_t i;
+ unsigned char *d;
+ const unsigned char *s;
+ d = dest;
+ s = src;
+
+ for (i=0; i < len; i++)
+ d[i] = s[i];
+
+ return dest;
+}
+
+int memcmp(void *src1, void *src2, size_t len)
+{
+ unsigned char *s1, *s2;
+ size_t i;
+ s1 = src1;
+ s2 = src2;
+ for(i = 0; i < len; i++) {
+ if (*s1 != *s2) {
+ return *s2 - *s1;
+ }
+ }
+ return 0;
+
+}
+
+/*
+ * Checksum functions
+ * =============================================================================
+ */
+
+
+static unsigned long checksum_partial(unsigned long sum,
+ void *addr, unsigned long length)
+{
+ uint8_t *ptr;
+ volatile union {
+ uint8_t byte[2];
+ uint16_t word;
+ } value;
+ unsigned long i;
+ /* In the most straight forward way possible,
+ * compute an ip style checksum.
+ */
+ sum = 0;
+ ptr = addr;
+ for(i = 0; i < length; i++) {
+ unsigned long value;
+ value = ptr[i];
+ if (i & 1) {
+ value <<= 8;
+ }
+ /* Add the new value */
+ sum += value;
+ /* Wrap around the carry */
+ if (sum > 0xFFFF) {
+ sum = (sum + (sum >> 16)) & 0xFFFF;
+ }
+ }
+ value.byte[0] = sum & 0xff;
+ value.byte[1] = (sum >> 8) & 0xff;
+ return value.word & 0xFFFF;
+
+}
+
+static unsigned long checksum_final(unsigned long partial)
+{
+ return (~partial) & 0xFFFF;
+}
+
+static unsigned long compute_checksum(void *vaddr, unsigned long length)
+{
+ return checksum_final(checksum_partial(0, vaddr, length));
+}
+
+/*
+ * Helper functions
+ * =============================================================================
+ */
+
+
+void append_command_line(struct parameters *real_mode, char *arg, int arg_bytes)
+{
+ int len, max;
+ char *dest;
+ /* skip over what has already been set */
+ len = strnlen(real_mode->command_line, sizeof(real_mode->command_line));
+ dest = real_mode->command_line + len;
+ max = sizeof(real_mode->command_line) - 1;
+ if (max < 1) {
+ /* No room to append anything :( */
+ return;
+ }
+ /* Add a space in between strings */
+ *dest++ = ' ';
+ /* Append the added command line */
+ max = sizeof(real_mode->command_line) - 1;
+ if (max > arg_bytes) {
+ max = arg_bytes;
+ }
+ len = strnlen(arg, max);
+ memcpy(dest, arg, len);
+ dest += len;
+ /* Null terminate the string */
+ *dest++ = '\0';
+}
+
+static void set_memsize_k(struct parameters *real_mode, unsigned long mem_k)
+{
+ /* ALT_MEM_K maxes out at 4GB */
+ if (mem_k > 0x3fffff) {
+ mem_k = 0x3fffff;
+ }
+ if (mem_k > (real_mode->alt_mem_k + (1 << 10))) {
+ /* Use our memory size less 1M */
+ real_mode->alt_mem_k = mem_k - (1 << 10);
+ real_mode->ext_mem_k = mem_k - (1 << 10);
+ if ((mem_k - (1 << 10)) > 0xFFFF) {
+ real_mode->ext_mem_k = 0xFC00; /* 64 M */
+ }
+ }
+}
+
+static void add_e820_map(struct parameters *real_mode,
+ unsigned long long addr, unsigned long long size,
+ unsigned long type)
+{
+ unsigned long long high;
+ unsigned long mem_k;
+ int i;
+ i = real_mode->e820_map_nr;
+ if (i < E820MAX) {
+ real_mode->e820_map[i].addr = addr;
+ real_mode->e820_map[i].size = size;
+ real_mode->e820_map[i].type = type;
+ real_mode->e820_map_nr++;
+ }
+ /* policy I assume that for the legacy memory
+ * variables memory is contiguous.
+ */
+ if (type == E820_RAM) {
+ high = addr + size;
+ if (high >= 0x40000000000ULL) {
+ mem_k = 0xFFFFFFFF;
+ } else {
+ mem_k = high >> 10;
+ }
+ set_memsize_k(real_mode, mem_k);
+ }
+}
+
+/*
+ * Multiboot
+ * =============================================================================
+ */
+
+#define MULTI_MEM_DEBUG 0
+#if MULTI_MEM_DEBUG
+#define multi_puts(x) printf("%s", x)
+#define multi_put_hex(x) printf("%x", x)
+#define multi_put_lhex(x) printf("%Lx", x)
+#else
+#define multi_puts(x)
+#define multi_put_hex(x)
+#define multi_put_lhex(x)
+#endif /* MULTI_MEM_DEBUG */
+
+/* Multiboot Specification */
+struct multiboot_mods {
+ unsigned mod_start;
+ unsigned mod_end;
+ unsigned char *string;
+ unsigned reserved;
+};
+
+struct memory_segment {
+ unsigned long long addr;
+ unsigned long long size;
+ unsigned type;
+};
+
+struct multiboot_info {
+ unsigned flags;
+#define MULTIBOOT_MEM_VALID 0x01
+#define MULTIBOOT_BOOT_DEV_VALID 0x02
+#define MULTIBOOT_CMDLINE_VALID 0x04
+#define MULTIBOOT_MODS_VALID 0x08
+#define MULTIBOOT_AOUT_SYMS_VALID 0x10
+#define MULTIBOOT_ELF_SYMS_VALID 0x20
+#define MULTIBOOT_MMAP_VALID 0x40
+ unsigned mem_lower;
+ unsigned mem_upper;
+ unsigned char boot_device[4];
+ void *command_line;
+ unsigned mods_count;
+ struct multiboot_mods *mods_addr;
+ unsigned syms_num;
+ unsigned syms_size;
+ unsigned syms_addr;
+ unsigned syms_shndx;
+ unsigned mmap_length;
+ struct memory_segment *mmap_addr;
+};
+
+#define MULTIBOOT_MAX_COMMAND_LINE 0xFFFFFFFF
+
+static void convert_multiboot_memmap(
+ struct parameters *real_mode,
+ struct multiboot_info *info)
+{
+ unsigned size;
+ unsigned *size_addr;
+#define next_seg(seg, size) ((struct memory_segment *)((char *)(seg) + (size)))
+ struct memory_segment *seg, *end;
+
+ seg = info->mmap_addr;
+ end = (void *)(((char *)seg) + info->mmap_length);
+ size_addr = (unsigned *)(((char *)seg) - 4);
+ size = *size_addr;
+ multi_puts("mmap_addr: "); multi_put_hex((unsigned)info->mmap_addr); multi_puts("\n");
+ multi_puts("mmap_length: "); multi_put_hex(info->mmap_length); multi_puts("\n");
+ multi_puts("size_addr: "); multi_put_hex((unsigned)size_addr); multi_puts("\n");
+ multi_puts("size: "); multi_put_hex(size); multi_puts("\n");
+ multi_puts("end: "); multi_put_hex((unsigned)end); multi_puts("\n");
+ for(seg = info->mmap_addr; (seg < end); seg = next_seg(seg,size)) {
+ multi_puts("multi-mem: ");
+ multi_put_lhex(seg->size);
+ multi_puts(" @ ");
+ multi_put_lhex(seg->addr);
+ multi_puts(" (");
+ switch(seg->type) {
+ case E820_RAM:
+ multi_puts("ram");
+ break;
+ case E820_ACPI:
+ multi_puts("ACPI data");
+ break;
+ case E820_NVS:
+ multi_puts("ACPI NVS");
+ break;
+ case E820_RESERVED:
+ default:
+ multi_puts("reserved");
+ break;
+ }
+ multi_puts(")\n");
+ add_e820_map(real_mode, seg->addr, seg->size, seg->type);
+ }
+#undef next_seg
+}
+
+static void convert_multiboot(
+ struct param_info *info, struct multiboot_info *mb_info)
+{
+ if (info->need_mem_sizes && (mb_info->flags & MULTIBOOT_MEM_VALID)) {
+ /* info->memory is short 1M */
+ set_memsize_k(info->real_mode, mb_info->mem_upper + (1 << 10));
+ }
+ if (mb_info->flags & MULTIBOOT_CMDLINE_VALID) {
+ append_command_line(info->real_mode, mb_info->command_line,
+ MULTIBOOT_MAX_COMMAND_LINE);
+ }
+ if (info->need_mem_sizes && (mb_info->flags & MULTIBOOT_MMAP_VALID)) {
+ convert_multiboot_memmap(info->real_mode, mb_info);
+ }
+ if (mb_info->flags & (MULTIBOOT_MEM_VALID | MULTIBOOT_MMAP_VALID)) {
+ info->need_mem_sizes = 0;
+ }
+}
+
+
+/*
+ * Uniform Boot Environment
+ * =============================================================================
+ */
+
+#define UBE_MEM_DEBUG 0
+#if UBE_MEM_DEBUG
+#define ube_puts(x) printf("%s", x)
+#define ube_put_hex(x) printf("%x", x)
+#define ube_put_lhex(x) printf("%Lx", x)
+#else
+#define ube_puts(x)
+#define ube_put_hex(x)
+#define ube_put_lhex(x)
+#endif /* UBE_MEM_DEBUG */
+static void convert_uniform_boot_memory(
+ struct parameters *real_mode, struct ube_memory *mem)
+{
+ int i;
+ int entries;
+ unsigned long mem_k;
+ mem_k = 0;
+ entries = (mem->size - sizeof(*mem))/sizeof(mem->map[0]);
+ for(i = 0; (i < entries) && (i < E820MAX); i++) {
+ unsigned long type;
+ ube_puts("ube-mem: ");
+ ube_put_lhex(mem->map[i].size);
+ ube_puts(" @ ");
+ ube_put_lhex(mem->map[i].start);
+ ube_puts(" (");
+ switch(mem->map[i].type) {
+ case UBE_MEM_RAM:
+ type = E820_RAM;
+ ube_puts("ram");
+ break;
+ case UBE_MEM_ACPI:
+ type = E820_ACPI;
+ ube_puts("ACPI data");
+ break;
+ case UBE_MEM_NVS:
+ type = E820_NVS;
+ ube_puts("ACPI NVS");
+ break;
+ case UBE_MEM_RESERVED:
+ default:
+ type = E820_RESERVED;
+ ube_puts("reserved");
+ break;
+ }
+ ube_puts(")\n");
+ add_e820_map(real_mode,
+ mem->map[i].start, mem->map[i].size, type);
+ }
+}
+
+static void convert_uniform_boot(struct param_info *info,
+ struct uniform_boot_header *header)
+{
+ /* Uniform boot environment */
+ unsigned long env_bytes;
+ char *env;
+ if (header->arg_bytes) {
+ append_command_line(info->real_mode, (void *)(header->arg), header->arg_bytes);
+ }
+ env = (void *)(header->env);
+ env_bytes = header->env_bytes;
+ while(env_bytes) {
+ struct ube_record *record;
+ record = (void *)env;
+ if (record->tag == UBE_TAG_MEMORY) {
+ if (info->need_mem_sizes) {
+ convert_uniform_boot_memory(info->real_mode, (void *)record);
+ info->need_mem_sizes = 0;
+ }
+ }
+ env += record->size;
+ env_bytes -= record->size;
+ }
+}
+
+
+
+
+/*
+ * Hardware
+ * =============================================================================
+ */
+
+/* we're getting screwed again and again by this problem of the 8259.
+ * so we're going to leave this lying around for inclusion into
+ * crt0.S on an as-needed basis.
+ * well, that went ok, I hope. Now we have to reprogram the interrupts :-(
+ * we put them right after the intel-reserved hardware interrupts, at
+ * int 0x20-0x2F. There they won't mess up anything. Sadly IBM really
+ * messed this up with the original PC, and they haven't been able to
+ * rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,
+ * which is used for the internal hardware interrupts as well. We just
+ * have to reprogram the 8259's, and it isn't fun.
+ */
+
+static void setup_i8259(void)
+{
+ outb(0x11, 0x20); /*! initialization sequence to 8259A-1*/
+ outb(0x11, 0xA0); /*! and to 8259A-2*/
+
+ outb(0x20, 0x21); /*! start of hardware int's (0x20)*/
+ outb(0x28, 0xA1); /*! start of hardware int's 2 (0x28)*/
+
+ outb(0x04, 0x21); /*! 8259-1 is master*/
+ outb(0x02, 0xA1); /*! 8259-2 is slave*/
+
+ outb(0x01, 0x21); /*! 8086 mode for both*/
+ outb(0x01, 0xA1);
+
+ outb(0xFF, 0xA1); /*! mask off all interrupts for now*/
+ outb(0xFB, 0x21); /*! mask all irq's but irq2 which is cascaded*/
+}
+
+static void hardware_setup(struct param_info *info __unused)
+{
+ /* Disable nmi */
+ outb(0x80, 0x70);
+
+ /* Make sure any coprocessor is properly reset.. */
+ outb(0, 0xf0);
+ outb(0, 0xf1);
+
+ setup_i8259();
+}
+
+
+/*
+ * ELF Boot loader
+ * =============================================================================
+ */
+
+static int count_elf_notes(Elf_Bhdr *bhdr)
+{
+ unsigned char *note, *end;
+ int count;
+ count = 0;
+ note = ((char *)bhdr) + sizeof(*bhdr);
+ end = ((char *)bhdr) + bhdr->b_size;
+#if 0
+ printf("count_elf_notes %lx\n", (unsigned long)bhdr);
+#endif
+ while (note < end) {
+ Elf_Nhdr *hdr;
+ unsigned char *n_name, *n_desc, *next;
+ hdr = (Elf_Nhdr *)note;
+ n_name = note + sizeof(*hdr);
+ n_desc = n_name + ((hdr->n_namesz + 3) & ~3);
+ next = n_desc + ((hdr->n_descsz + 3) & ~3);
+#if 0
+ printf("elf_note = %lx\n", (unsigned long)note);
+ printf("elf_namesz = %x\n", hdr->n_namesz);
+ printf("elf_descsz = %x\n", hdr->n_descsz);
+ printf("elf_type = %x\n", hdr->n_type);
+ printf("elf_name = %lx\n", (unsigned long)n_name);
+ printf("elf_desc = %lx\n", (unsigned long)n_desc);
+#endif
+ if (next > end)
+ break;
+ count++;
+ note = next;
+ }
+ return count;
+}
+
+static Elf_Nhdr *find_elf_note(Elf_Bhdr *bhdr,
+ Elf_Word namesz, unsigned char *name, Elf_Word type)
+{
+ unsigned char *note, *end;
+ note = ((char *)bhdr) + sizeof(*bhdr);
+ end = ((char *)bhdr) + bhdr->b_size;
+ while(note < end) {
+ Elf_Nhdr *hdr;
+ unsigned char *n_name, *n_desc, *next;
+ hdr = (Elf_Nhdr *)note;
+ n_name = note + sizeof(*hdr);
+ n_desc = n_name + ((hdr->n_namesz + 3) & ~3);
+ next = n_desc + ((hdr->n_descsz + 3) & ~3);
+ if (next > end)
+ break;
+ if ((hdr->n_type == type) &&
+ (hdr->n_namesz == namesz) &&
+ (memcmp(n_name, name, namesz) == 0)) {
+ return hdr;
+ }
+ note = next;
+ }
+ return 0;
+}
+
+static void convert_elf_command_line(struct param_info *info,
+ Elf_Word descsz, unsigned char *desc)
+{
+ append_command_line(info->real_mode, desc, descsz);
+}
+
+struct {
+ Elf_Word namesz;
+ unsigned char *name;
+ Elf_Word type;
+ void (*convert)(struct param_info *info, Elf_Word descsz, unsigned char *desc);
+} elf_notes[] =
+{
+ { 0, "", EBN_COMMAND_LINE, convert_elf_command_line },
+};
+
+static void convert_elf_boot(struct param_info *info, Elf_Bhdr *bhdr)
+{
+ unsigned char *note, *end;
+ note = ((char *)bhdr) + sizeof(*bhdr);
+ end = ((char *)bhdr) + bhdr->b_size;
+ while(note < end) {
+ Elf_Nhdr *hdr;
+ unsigned char *n_name, *n_desc, *next;
+ size_t i;
+ hdr = (Elf_Nhdr *)note;
+ n_name = note + sizeof(*hdr);
+ n_desc = n_name + ((hdr->n_namesz + 3) & ~3);
+ next = n_desc + ((hdr->n_descsz + 3) & ~3);
+ if (next > end)
+ break;
+ for(i = 0; i < sizeof(elf_notes)/sizeof(elf_notes[0]); i++) {
+ if ((hdr->n_type == elf_notes[i].type) &&
+ (hdr->n_namesz == elf_notes[i].namesz) &&
+ (memcmp(n_name, elf_notes[i].name, elf_notes[i].namesz) == 0)) {
+ elf_notes[i].convert(info, hdr->n_descsz, n_desc);
+ break;
+ }
+ }
+ note = next;
+ }
+}
+
+/*
+ * LinuxBIOS
+ * =============================================================================
+ */
+
+#define LB_MEM_DEBUG 0
+#if LB_MEM_DEBUG
+#define lb_puts(x) printf("%s", x)
+#define lb_put_hex(x) printf("%x", x)
+#define lb_put_lhex(x) printf("%Lx", x)
+#else
+#define lb_puts(x)
+#define lb_put_hex(x)
+#define lb_put_lhex(x)
+#endif /* LB_MEM_DEBUG */
+
+static unsigned count_lb_records(void *start, unsigned long length)
+{
+ struct lb_record *rec;
+ void *end;
+ unsigned count;
+ count = 0;
+ end = ((char *)start) + length;
+ for(rec = start; ((void *)rec < end) &&
+ (rec->size <= (unsigned long)(end - (void *)rec));
+ rec = (void *)(((char *)rec) + rec->size)) {
+ count++;
+ }
+ return count;
+}
+
+static struct lb_header *__find_lb_table(void *start, void *end)
+{
+ unsigned char *ptr;
+ /* For now be stupid.... */
+ for(ptr = start; (void *)ptr < end; ptr += 16) {
+ struct lb_header *head = (void *)ptr;
+ if ((head->signature[0] == 'L') &&
+ (head->signature[1] == 'B') &&
+ (head->signature[2] == 'I') &&
+ (head->signature[3] == 'O') &&
+ (head->header_bytes == sizeof(*head)) &&
+ (compute_checksum(head, sizeof(*head)) == 0) &&
+ (compute_checksum(ptr + sizeof(*head), head->table_bytes) ==
+ head->table_checksum) &&
+ (count_lb_records(ptr + sizeof(*head), head->table_bytes) ==
+ head->table_entries)
+ ) {
+ return head;
+ }
+ };
+ return 0;
+}
+
+static int find_lb_table(struct param_info *info)
+{
+ struct lb_header *head;
+ head = 0;
+ if (!head) {
+ /* First try at address 0 */
+ head = __find_lb_table((void *)0x00000, (void *)0x1000);
+ }
+ if (!head) {
+ /* Then try at address 0xf0000 */
+ head = __find_lb_table((void *)0xf0000, (void *)0x100000);
+ }
+ if (head) {
+ info->has_linuxbios = 1;
+ info->lb_table = head;
+ return 1;
+ }
+ return 0;
+}
+
+static void convert_lb_memory(struct param_info *info, struct lb_memory *mem)
+{
+ int i;
+ int entries;
+ entries = (mem->size - sizeof(*mem))/sizeof(mem->map[0]);
+ for(i = 0; (i < entries) && (i < E820MAX); i++) {
+ unsigned long type;
+ unsigned long long end;
+ end = mem->map[i].start + mem->map[i].size;
+ lb_puts("lb-mem: ");
+ lb_put_lhex(mem->map[i].start);
+ lb_puts(" - ");
+ lb_put_lhex(end);
+ lb_puts(" (");
+ switch(mem->map[i].type) {
+ case LB_MEM_RAM:
+ type = E820_RAM;
+ lb_puts("ram");
+ break;
+ default:
+ type = E820_RESERVED;
+ lb_puts("reserved");
+ break;
+ }
+ lb_puts(")\n");
+ add_e820_map(info->real_mode,
+ mem->map[i].start, mem->map[i].size, type);
+ }
+ info->need_mem_sizes = 0;
+}
+
+static void query_lb_values(struct param_info *info)
+{
+ struct lb_header *head;
+ struct lb_record *rec;
+ void *start, *end;
+ head = info->lb_table;
+ start = ((unsigned char *)head) + sizeof(*head);
+ end = ((char *)start) + head->table_bytes;
+ for(rec = start; ((void *)rec < end) &&
+ (rec->size <= (unsigned long)(end - (void *)rec));
+ rec = (void *)(((char *)rec) + rec->size)) {
+ switch(rec->tag) {
+ case LB_TAG_MEMORY:
+ {
+ struct lb_memory *mem;
+ mem = (struct lb_memory *) rec;
+ convert_lb_memory(info, mem);
+ break;
+ }
+ default:
+ break;
+ };
+ }
+}
+
+/*
+ * PCBIOS
+ * =============================================================================
+ */
+#define PC_MEM_DEBUG 0
+#if PC_MEM_DEBUG
+#define pc_puts(x) printf("%s", x)
+#define pc_put_hex(x) printf("%x", x)
+#define pc_put_lhex(x) printf("%Lx", x)
+#else
+#define pc_puts(x)
+#define pc_put_hex(x)
+#define pc_put_lhex(x)
+#endif /* PC_MEM_DEBUG */
+
+/* functions for querying the pcbios */
+extern void noop(void); /* for testing purposes only */
+extern int meme820(struct e820entry *buf, int count);
+extern unsigned int meme801(void);
+extern unsigned short mem88(void);
+extern unsigned short basememsize(void);
+
+struct meminfo {
+ int map_count;
+ struct e820entry map[E820MAX];
+};
+
+static struct meminfo meminfo;
+static void get_meminfo(struct param_info *info)
+{
+ int i;
+ pc_puts("getting meminfo...\n");
+ meminfo.map_count = meme820(meminfo.map, E820MAX);
+ pc_puts("got meminfo count="); pc_put_hex(meminfo.map_count); pc_puts("\n");
+ for(i = 0; i < meminfo.map_count; i++) {
+ unsigned long long end;
+ struct e820entry *seg = meminfo.map + i;
+ end = seg->addr + seg->size;
+ pc_puts("BIOS-e820: ");
+ pc_put_lhex(seg->addr);
+ pc_puts(" - ");
+ pc_put_lhex(end);
+ pc_puts(" (");
+ switch(seg->type) {
+ case E820_RAM:
+ pc_puts("ram");
+ info->need_mem_sizes = 0;
+ break;
+ case E820_ACPI:
+ pc_puts("ACPI data");
+ break;
+ case E820_NVS:
+ pc_puts("ACPI NVS");
+ break;
+ case E820_RESERVED:
+ default:
+ pc_puts("reserved");
+ break;
+ }
+ pc_puts(")\n");
+ add_e820_map(info->real_mode,
+ seg->addr, seg->size, seg->type);
+ }
+ info->real_mode->alt_mem_k = meme801();
+ info->real_mode->ext_mem_k = mem88();
+ if (info->real_mode->alt_mem_k || info->real_mode->ext_mem_k) {
+ info->need_mem_sizes = 0;
+ }
+}
+
+static void query_pcbios_values(struct param_info *info)
+{
+ get_meminfo(info);
+}
+
+/*
+ * Bootloaders
+ * =============================================================================
+ */
+
+
+static void query_bootloader_param_class(struct param_info *info)
+{
+ int has_bootloader_type = 0;
+ Elf_Bhdr *hdr = 0;
+ if (!has_bootloader_type && (info->type == 0x2BADB002)) {
+ /* Orignal multiboot specification */
+ info->has_multiboot = 1;
+ has_bootloader_type = 1;
+ }
+ if (!has_bootloader_type && (info->type == 0x0A11B007)) {
+ /* Uniform boot proposal */
+ unsigned long checksum;
+ struct uniform_boot_header *header;
+ header = info->data;
+ checksum = compute_checksum(header, header->header_bytes);
+ if (checksum == 0) {
+ info->has_uniform_boot = 1;
+ has_bootloader_type = 1;
+ } else{
+ printf("Bad uniform boot header checksum!\n");
+ }
+ }
+ if (info->type == ELF_BHDR_MAGIC) {
+ hdr = info->data;
+ }
+ if (info->param && (info->param->b_signature == ELF_BHDR_MAGIC)) {
+ hdr = info->param;
+ }
+ if (!has_bootloader_type && hdr) {
+ /* Good ELF boot proposal... */
+ unsigned long checksum;
+ int count;
+ checksum = 0;
+ if (hdr->b_checksum != 0) {
+ checksum = compute_checksum(hdr, hdr->b_size);
+ }
+ count = count_elf_notes(hdr);
+ if ((hdr->b_signature == ELF_BHDR_MAGIC) &&
+ (checksum == 0) &&
+ hdr->b_records == count) {
+ info->has_elf_boot = 1;
+ info->param = hdr;
+ has_bootloader_type = 1;
+ }
+ else {
+ printf("Bad ELF parameter table!\n");
+ printf(" checksum = %x\n", checksum);
+ printf(" count = %x\n", count);
+ printf(" hdr = %x\n", (unsigned long)hdr);
+ printf(" b_size = %x\n", hdr->b_size);
+ printf("b_signature = %x\n", hdr->b_signature);
+ printf(" b_records = %x\n", hdr->b_records);
+ }
+ }
+ if (!has_bootloader_type) {
+ printf("Unknown bootloader class!\n");
+ printf("type=%x\n", info->type);
+ printf("data=%x\n", (unsigned)info->data);
+ printf("param=%x\n", (unsigned)info->param);
+ }
+}
+
+static void query_bootloader_values(struct param_info *info)
+{
+ if (info->has_multiboot) {
+ convert_multiboot(info, info->data);
+ }
+ else if (info->has_uniform_boot) {
+ convert_uniform_boot(info, info->data);
+ }
+ else if (info->has_elf_boot) {
+ convert_elf_boot(info, info->param);
+ }
+}
+
+/*
+ * Firmware
+ * =============================================================================
+ */
+
+static int bootloader_query_firmware_class(struct param_info *info)
+{
+ Elf_Nhdr *hdr;
+ unsigned char *note, *n_name, *n_desc;
+ int detected_firmware_type;
+ if (!info->has_elf_boot) {
+ /* Only the elf boot tables gives us a firmware type */
+ return 0;
+ }
+ detected_firmware_type = 0;
+ n_desc = 0;
+
+ hdr = find_elf_note(info->param, 0, 0, EBN_FIRMWARE_TYPE);
+ if (!hdr) {
+ /* If I'm not explicitly told the firmware type
+ * do my best to guess it for myself.
+ */
+ detected_firmware_type = 0;
+ } else {
+ note = (char *)hdr;
+ n_name = note + sizeof(*hdr);
+ n_desc = n_name + ((hdr->n_namesz + 3) & ~3);
+ }
+ if (!detected_firmware_type && hdr &&
+ (hdr->n_descsz == 7) &&
+ (memcmp(n_desc, "PCBIOS", 7) == 0)) {
+ info->has_pcbios = 1;
+ detected_firmware_type = 1;
+ }
+ if (!detected_firmware_type && hdr &&
+ (hdr->n_descsz == 10) &&
+ (memcmp(n_desc, "LinuxBIOS", 10) == 0)) {
+ /* Don't believe I'm linuxBIOS unless I can
+ * find the linuxBIOS table..
+ */
+ detected_firmware_type = find_lb_table(info);
+ }
+ if (!detected_firmware_type && hdr &&
+ (hdr->n_descsz == 0)) {
+ /* No firmware is present */
+ detected_firmware_type = 1;
+ }
+ if (!detected_firmware_type && hdr &&
+ (hdr->n_descsz == 1) &&
+ (memcmp(n_desc, "", 1) == 0)) {
+ /* No firmware is present */
+ detected_firmware_type = 1;
+ }
+ if (!detected_firmware_type && hdr) {
+ printf("Unknown firmware type: %s\n", n_desc);
+ }
+ return detected_firmware_type;
+}
+
+static void query_firmware_class(struct param_info *info)
+{
+ int detected_firmware_type = 0;
+
+ /* First say I have no firmware at all... */
+ info->has_pcbios = 0;
+ info->has_linuxbios = 0;
+
+ /* See if the bootloader has told us what
+ * kind of firmware we are running on.
+ */
+ detected_firmware_type = bootloader_query_firmware_class(info);
+
+ /* See if we can detect linuxbios. */
+ if (!detected_firmware_type) {
+ detected_firmware_type = find_lb_table(info);
+ }
+
+ if (!detected_firmware_type) {
+ /* if all else fails assume a standard pcbios... */
+ info->has_pcbios = 1;
+ }
+
+ /* Now print out the firmware type... */
+ printf("Firmware type:");
+ if (info->has_linuxbios) {
+ printf(" LinuxBIOS");
+ }
+ if (info->has_pcbios) {
+ printf(" PCBIOS");
+ }
+ printf("\n");
+}
+
+static void query_firmware_values(struct param_info *info)
+{
+ if (info->has_linuxbios) {
+ query_lb_values(info);
+ }
+ if (info->has_pcbios) {
+ query_pcbios_values(info);
+ }
+
+}
+
+/*
+ * Debug
+ * =============================================================================
+ */
+
+#if 0
+static void print_offsets(void)
+{
+ struct parameters *real_mode = 0;
+ printf("print_offsets\n");
+
+ printf("orig_x =%x\n", (uint32_t)&real_mode->orig_x);
+ printf("orig_y =%x\n", (uint32_t)&real_mode->orig_y);
+ printf("ext_mem_k =%x\n", (uint32_t)&real_mode->ext_mem_k);
+ printf("orig_video_page =%x\n", (uint32_t)&real_mode->orig_video_page);
+ printf("orig_video_mode =%x\n", (uint32_t)&real_mode->orig_video_mode);
+ printf("orig_video_cols =%x\n", (uint32_t)&real_mode->orig_video_cols);
+ printf("unused2 =%x\n", (uint32_t)&real_mode->unused2);
+ printf("orig_video_ega_bx =%x\n", (uint32_t)&real_mode->orig_video_ega_bx);
+ printf("unused3 =%x\n", (uint32_t)&real_mode->unused3);
+ printf("orig_video_lines =%x\n", (uint32_t)&real_mode->orig_video_lines);
+ printf("orig_video_isVGA =%x\n", (uint32_t)&real_mode->orig_video_isVGA);
+ printf("orig_video_points =%x\n", (uint32_t)&real_mode->orig_video_points);
+ printf("lfb_width =%x\n", (uint32_t)&real_mode->lfb_width);
+ printf("lfb_height =%x\n", (uint32_t)&real_mode->lfb_height);
+ printf("lfb_depth =%x\n", (uint32_t)&real_mode->lfb_depth);
+ printf("lfb_base =%x\n", (uint32_t)&real_mode->lfb_base);
+ printf("lfb_size =%x\n", (uint32_t)&real_mode->lfb_size);
+ printf("cl_magic =%x\n", (uint32_t)&real_mode->cl_magic);
+ printf("cl_offset =%x\n", (uint32_t)&real_mode->cl_offset);
+ printf("lfb_linelength =%x\n", (uint32_t)&real_mode->lfb_linelength);
+ printf("red_size =%x\n", (uint32_t)&real_mode->red_size);
+ printf("red_pos =%x\n", (uint32_t)&real_mode->red_pos);
+ printf("green_size =%x\n", (uint32_t)&real_mode->green_size);
+ printf("green_pos =%x\n", (uint32_t)&real_mode->green_pos);
+ printf("blue_size =%x\n", (uint32_t)&real_mode->blue_size);
+ printf("blue_pos =%x\n", (uint32_t)&real_mode->blue_pos);
+ printf("rsvd_size =%x\n", (uint32_t)&real_mode->rsvd_size);
+ printf("rsvd_pos =%x\n", (uint32_t)&real_mode->rsvd_pos);
+ printf("vesapm_seg =%x\n", (uint32_t)&real_mode->vesapm_seg);
+ printf("vesapm_off =%x\n", (uint32_t)&real_mode->vesapm_off);
+ printf("pages =%x\n", (uint32_t)&real_mode->pages);
+ printf("reserved4 =%x\n", (uint32_t)&real_mode->reserved4);
+ printf("apm_bios_info =%x\n", (uint32_t)&real_mode->apm_bios_info);
+ printf("drive_info =%x\n", (uint32_t)&real_mode->drive_info);
+ printf("sys_desc_table =%x\n", (uint32_t)&real_mode->sys_desc_table);
+ printf("alt_mem_k =%x\n", (uint32_t)&real_mode->alt_mem_k);
+ printf("reserved5 =%x\n", (uint32_t)&real_mode->reserved5);
+ printf("e820_map_nr =%x\n", (uint32_t)&real_mode->e820_map_nr);
+ printf("reserved6 =%x\n", (uint32_t)&real_mode->reserved6);
+ printf("mount_root_rdonly =%x\n", (uint32_t)&real_mode->mount_root_rdonly);
+ printf("reserved7 =%x\n", (uint32_t)&real_mode->reserved7);
+ printf("ramdisk_flags =%x\n", (uint32_t)&real_mode->ramdisk_flags);
+ printf("reserved8 =%x\n", (uint32_t)&real_mode->reserved8);
+ printf("orig_root_dev =%x\n", (uint32_t)&real_mode->orig_root_dev);
+ printf("reserved9 =%x\n", (uint32_t)&real_mode->reserved9);
+ printf("aux_device_info =%x\n", (uint32_t)&real_mode->aux_device_info);
+ printf("reserved10 =%x\n", (uint32_t)&real_mode->reserved10);
+ printf("param_block_signature=%x\n", (uint32_t)&real_mode->param_block_signature);
+ printf("param_block_version =%x\n", (uint32_t)&real_mode->param_block_version);
+ printf("reserved11 =%x\n", (uint32_t)&real_mode->reserved11);
+ printf("loader_type =%x\n", (uint32_t)&real_mode->loader_type);
+ printf("loader_flags =%x\n", (uint32_t)&real_mode->loader_flags);
+ printf("reserved12 =%x\n", (uint32_t)&real_mode->reserved12);
+ printf("kernel_start =%x\n", (uint32_t)&real_mode->kernel_start);
+ printf("initrd_start =%x\n", (uint32_t)&real_mode->initrd_start);
+ printf("initrd_size =%x\n", (uint32_t)&real_mode->initrd_size);
+ printf("reserved13 =%x\n", (uint32_t)&real_mode->reserved13);
+ printf("e820_map =%x\n", (uint32_t)&real_mode->e820_map);
+ printf("reserved16 =%x\n", (uint32_t)&real_mode->reserved16);
+ printf("command_line =%x\n", (uint32_t)&real_mode->command_line);
+ printf("reserved17 =%x\n", (uint32_t)&real_mode->reserved17);
+}
+
+static void print_linux_params(struct param_info *info)
+{
+ int i;
+
+ printf("print_linux_params\n");
+ /* Default screen size */
+ printf("orig_x =%x\n", info->real_mode->orig_x);
+ printf("orig_y =%x\n", info->real_mode->orig_y);
+ printf("orig_video_page =%x\n", info->real_mode->orig_video_page);
+ printf("orig_video_mode =%x\n", info->real_mode->orig_video_mode);
+ printf("orig_video_cols =%x\n", info->real_mode->orig_video_cols);
+ printf("orig_video_lines =%x\n", info->real_mode->orig_video_lines);
+ printf("orig_video_ega_bx=%x\n", info->real_mode->orig_video_ega_bx);
+ printf("orig_video_isVGA =%x\n", info->real_mode->orig_video_isVGA);
+ printf("orig_video_points=%x\n", info->real_mode->orig_video_points);
+
+
+ /* System descriptor table... */
+ printf("sys_dest_table_len=%x\n", info->real_mode->sys_desc_table.length);
+
+ /* Memory sizes */
+ printf("ext_mem_k =%x\n", info->real_mode->ext_mem_k);
+ printf("alt_mem_k =%x\n", info->real_mode->alt_mem_k);
+ printf("e820_map_nr =%x\n", info->real_mode->e820_map_nr);
+ for(i = 0; i < E820MAX; i++) {
+ printf("addr[%x] =%Lx\n",
+ i, info->real_mode->e820_map[i].addr);
+ printf("size[%x] =%Lx\n",
+ i, info->real_mode->e820_map[i].size);
+ printf("type[%x] =%Lx\n",
+ i, info->real_mode->e820_map[i].type);
+ }
+ printf("mount_root_rdonly=%x\n", info->real_mode->mount_root_rdonly);
+ printf("ramdisk_flags =%x\n", info->real_mode->ramdisk_flags);
+ printf("orig_root_dev =%x\n", info->real_mode->orig_root_dev);
+ printf("aux_device_info =%x\n", info->real_mode->aux_device_info);
+ printf("param_block_signature=%x\n", *((uint32_t *)info->real_mode->param_block_signature));
+ printf("loader_type =%x\n", info->real_mode->loader_type);
+ printf("loader_flags =%x\n", info->real_mode->loader_flags);
+ printf("initrd_start =%x\n", info->real_mode->initrd_start);
+ printf("initrd_size =%x\n", info->real_mode->initrd_size);
+
+ /* Where I'm putting the command line */
+ printf("cl_magic =%x\n", info->real_mode->cl_magic);
+ printf("cl_offset =%x\n", info->real_mode->cl_offset);
+
+ /* Now print the command line */
+ printf("command_line =%s\n", info->real_mode->command_line);
+}
+
+
+#endif
+
+/*
+ * main
+ * =============================================================================
+ */
+
+void initialize_linux_params(struct param_info *info)
+{
+ int len;
+ /* First the defaults */
+ memset(info->real_mode, 0, PAGE_SIZE);
+
+ /* Default screen size */
+ info->real_mode->orig_x = 0;
+ info->real_mode->orig_y = 25;
+ info->real_mode->orig_video_page = 0;
+ info->real_mode->orig_video_mode = 0;
+ info->real_mode->orig_video_cols = 80;
+ info->real_mode->orig_video_lines = 25;
+ info->real_mode->orig_video_ega_bx = 0;
+ info->real_mode->orig_video_isVGA = 1;
+ info->real_mode->orig_video_points = 16;
+
+ /* Fill this in later */
+ info->real_mode->ext_mem_k = 0;
+
+ /* Fill in later... */
+ info->real_mode->e820_map_nr = 0;
+
+ /* Where I'm putting the command line */
+ info->real_mode->cl_magic = CL_MAGIC_VALUE;
+ info->real_mode->cl_offset = 2048;
+
+ info->real_mode->cmd_line_ptr = info->real_mode->cl_offset + (unsigned long) info->real_mode;
+
+ /* Now set the command line */
+ len = strnlen(info->image->cmdline, sizeof(info->real_mode->command_line) -1);
+ memcpy(info->real_mode->command_line, info->image->cmdline, len);
+ info->real_mode->command_line[len] = '\0';
+
+ /* from the bios initially */
+ memset(&info->real_mode->apm_bios_info, 0, sizeof(info->real_mode->apm_bios_info));
+
+ memset(&info->real_mode->drive_info, 0, sizeof(info->real_mode->drive_info));
+
+ /* forget it for now... */
+ info->real_mode->sys_desc_table.length = 0;
+
+ /* Fill this in later */
+ info->real_mode->alt_mem_k = 0;
+ info->real_mode->ext_mem_k = 0;
+
+ /* default yes: this can be overridden on the command line */
+ info->real_mode->mount_root_rdonly = 0xFFFF;
+
+ /* old ramdisk options, These really should be command line
+ * things...
+ */
+ info->real_mode->ramdisk_flags = info->image->ramdisk_flags;
+
+ /* default to /dev/hda.
+ * Override this on the command line if necessary
+ */
+ info->real_mode->orig_root_dev = info->image->root_dev;
+
+ /* Originally from the bios? */
+ info->real_mode->aux_device_info = 0;
+
+ /* Boot block magic */
+ memcpy(info->real_mode->param_block_signature, "HdrS", 4);
+ info->real_mode->param_block_version = 0x0201;
+
+ /* Say I'm a kernel boot loader */
+ info->real_mode->loader_type = (LOADER_TYPE_KERNEL << 4) + 0 /* version */;
+
+ /* No loader flags */
+ info->real_mode->loader_flags = 0;
+
+ /* Ramdisk address and size ... */
+ info->real_mode->initrd_start = 0;
+ info->real_mode->initrd_size = 0;
+ if (info->image->initrd_size) {
+ info->real_mode->initrd_start = info->image->initrd_start;
+ info->real_mode->initrd_size = info->image->initrd_size;
+ }
+
+ /* Now remember those things that I need */
+ info->need_mem_sizes = 1;
+}
+
+void *convert_params(unsigned type, void *data, void *param, void *image)
+{
+ struct param_info info;
+#if 0
+ printf("hello world\n");
+#endif
+ info.real_mode = faked_real_mode;
+ info.type = type;
+ info.data = data;
+ info.param = param;
+ info.image = image;
+ initialize_linux_params(&info);
+ query_bootloader_param_class(&info);
+ query_firmware_class(&info);
+ query_firmware_values(&info);
+ query_bootloader_values(&info);
+
+ /* Do the hardware setup that linux might forget... */
+ hardware_setup(&info);
+
+ /* Print some debugging information */
+#if 0
+ printf("EXT_MEM_K=%x\n", info.real_mode->ext_mem_k);
+ printf("ALT_MEM_K=%x\n", info.real_mode->alt_mem_k);
+#endif
+#if 0
+ print_offsets();
+ print_linux_params(&info);
+#endif
+#if 0
+ printf("info.real_mode = 0x%x\n", info.real_mode );
+ printf("Jumping to Linux\n");
+#endif
+ return info.real_mode;
+}
+