summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlek Du <alek.du@intel.com>2008-05-13 16:23:15 +0800
committerPatrick Tjin <pattjin@google.com>2014-07-21 20:22:35 -0700
commitb7f7baf2e23345011ae4079e62c470418c2424e6 (patch)
tree708aa0d3e1934ad546cba7075106ce3cc6e7ccf4
parent321a1bb385b0002ed6835e5fb22d80e5ef9165ac (diff)
downloadbootstub-b7f7baf2e23345011ae4079e62c470418c2424e6.tar.gz
* bootstub version 0.01
-rw-r--r--bootparam.h274
-rw-r--r--bootstub.c80
-rw-r--r--bootstub.h28
-rw-r--r--bootstub.lds37
-rw-r--r--head.S58
-rw-r--r--types.h20
6 files changed, 497 insertions, 0 deletions
diff --git a/bootparam.h b/bootparam.h
new file mode 100644
index 0000000..bd50669
--- /dev/null
+++ b/bootparam.h
@@ -0,0 +1,274 @@
+/* bootparms.h base on Linux kernel include/asm-x86/bootparam.h */
+
+#include "types.h"
+
+#define EDD_MBR_SIG_MAX 16
+#define E820MAX 128
+#define EDDMAXNR 6
+
+/* extensible setup data list node */
+struct setup_data {
+ __u64 next;
+ __u32 type;
+ __u32 len;
+ __u8 data[0];
+};
+
+struct screen_info {
+ __u8 orig_x; /* 0x00 */
+ __u8 orig_y; /* 0x01 */
+ __u16 ext_mem_k; /* 0x02 */
+ __u16 orig_video_page; /* 0x04 */
+ __u8 orig_video_mode; /* 0x06 */
+ __u8 orig_video_cols; /* 0x07 */
+ __u16 unused2; /* 0x08 */
+ __u16 orig_video_ega_bx;/* 0x0a */
+ __u16 unused3; /* 0x0c */
+ __u8 orig_video_lines; /* 0x0e */
+ __u8 orig_video_isVGA; /* 0x0f */
+ __u16 orig_video_points;/* 0x10 */
+
+ /* VESA graphic mode -- linear frame buffer */
+ __u16 lfb_width; /* 0x12 */
+ __u16 lfb_height; /* 0x14 */
+ __u16 lfb_depth; /* 0x16 */
+ __u32 lfb_base; /* 0x18 */
+ __u32 lfb_size; /* 0x1c */
+ __u16 cl_magic, cl_offset; /* 0x20 */
+ __u16 lfb_linelength; /* 0x24 */
+ __u8 red_size; /* 0x26 */
+ __u8 red_pos; /* 0x27 */
+ __u8 green_size; /* 0x28 */
+ __u8 green_pos; /* 0x29 */
+ __u8 blue_size; /* 0x2a */
+ __u8 blue_pos; /* 0x2b */
+ __u8 rsvd_size; /* 0x2c */
+ __u8 rsvd_pos; /* 0x2d */
+ __u16 vesapm_seg; /* 0x2e */
+ __u16 vesapm_off; /* 0x30 */
+ __u16 pages; /* 0x32 */
+ __u16 vesa_attributes; /* 0x34 */
+ __u32 capabilities; /* 0x36 */
+ __u8 _reserved[6]; /* 0x3a */
+} __attribute__((packed));
+
+struct apm_bios_info {
+ __u16 version;
+ __u16 cseg;
+ __u32 offset;
+ __u16 cseg_16;
+ __u16 dseg;
+ __u16 flags;
+ __u16 cseg_len;
+ __u16 cseg_16_len;
+ __u16 dseg_len;
+};
+
+struct ist_info {
+ __u32 signature;
+ __u32 command;
+ __u32 event;
+ __u32 perf_level;
+};
+
+struct sys_desc_table {
+ __u16 length;
+ __u8 table[14];
+};
+
+struct efi_info {
+ __u32 efi_loader_signature;
+ __u32 efi_systab;
+ __u32 efi_memdesc_size;
+ __u32 efi_memdesc_version;
+ __u32 efi_memmap;
+ __u32 efi_memmap_size;
+ __u32 efi_systab_hi;
+ __u32 efi_memmap_hi;
+};
+
+struct setup_header {
+ __u8 setup_sects;
+ __u16 root_flags;
+ __u32 syssize;
+ __u16 ram_size;
+ __u16 vid_mode;
+ __u16 root_dev;
+ __u16 boot_flag;
+ __u16 jump;
+ __u32 header;
+ __u16 version;
+ __u32 realmode_swtch;
+ __u16 start_sys;
+ __u16 kernel_version;
+ __u8 type_of_loader;
+ __u8 loadflags;
+ __u16 setup_move_size;
+ __u32 code32_start;
+ __u32 ramdisk_image;
+ __u32 ramdisk_size;
+ __u32 bootsect_kludge;
+ __u16 heap_end_ptr;
+ __u16 _pad1;
+ __u32 cmd_line_ptr;
+ __u32 initrd_addr_max;
+ __u32 kernel_alignment;
+ __u8 relocatable_kernel;
+ __u8 _pad2[3];
+ __u32 cmdline_size;
+ __u32 hardware_subarch;
+ __u64 hardware_subarch_data;
+ __u32 payload_offset;
+ __u32 payload_length;
+ __u64 setup_data;
+} __attribute__((packed));
+
+struct edid_info {
+ unsigned char dummy[128];
+};
+
+struct e820entry {
+ __u64 addr; /* start of memory segment */
+ __u64 size; /* size of memory segment */
+ __u32 type; /* type of memory segment */
+} __attribute__((packed));
+
+struct edd_device_params {
+ __u16 length;
+ __u16 info_flags;
+ __u32 num_default_cylinders;
+ __u32 num_default_heads;
+ __u32 sectors_per_track;
+ __u64 number_of_sectors;
+ __u16 bytes_per_sector;
+ __u32 dpte_ptr; /* 0xFFFFFFFF for our purposes */
+ __u16 key; /* = 0xBEDD */
+ __u8 device_path_info_length; /* = 44 */
+ __u8 reserved2;
+ __u16 reserved3;
+ __u8 host_bus_type[4];
+ __u8 interface_type[8];
+ union {
+ struct {
+ __u16 base_address;
+ __u16 reserved1;
+ __u32 reserved2;
+ } __attribute__ ((packed)) isa;
+ struct {
+ __u8 bus;
+ __u8 slot;
+ __u8 function;
+ __u8 channel;
+ __u32 reserved;
+ } __attribute__ ((packed)) pci;
+ /* pcix is same as pci */
+ struct {
+ __u64 reserved;
+ } __attribute__ ((packed)) ibnd;
+ struct {
+ __u64 reserved;
+ } __attribute__ ((packed)) xprs;
+ struct {
+ __u64 reserved;
+ } __attribute__ ((packed)) htpt;
+ struct {
+ __u64 reserved;
+ } __attribute__ ((packed)) unknown;
+ } interface_path;
+ union {
+ struct {
+ __u8 device;
+ __u8 reserved1;
+ __u16 reserved2;
+ __u32 reserved3;
+ __u64 reserved4;
+ } __attribute__ ((packed)) ata;
+ struct {
+ __u8 device;
+ __u8 lun;
+ __u8 reserved1;
+ __u8 reserved2;
+ __u32 reserved3;
+ __u64 reserved4;
+ } __attribute__ ((packed)) atapi;
+ struct {
+ __u16 id;
+ __u64 lun;
+ __u16 reserved1;
+ __u32 reserved2;
+ } __attribute__ ((packed)) scsi;
+ struct {
+ __u64 serial_number;
+ __u64 reserved;
+ } __attribute__ ((packed)) usb;
+ struct {
+ __u64 eui;
+ __u64 reserved;
+ } __attribute__ ((packed)) i1394;
+ struct {
+ __u64 wwid;
+ __u64 lun;
+ } __attribute__ ((packed)) fibre;
+ struct {
+ __u64 identity_tag;
+ __u64 reserved;
+ } __attribute__ ((packed)) i2o;
+ struct {
+ __u32 array_number;
+ __u32 reserved1;
+ __u64 reserved2;
+ } __attribute__ ((packed)) raid;
+ struct {
+ __u8 device;
+ __u8 reserved1;
+ __u16 reserved2;
+ __u32 reserved3;
+ __u64 reserved4;
+ } __attribute__ ((packed)) sata;
+ struct {
+ __u64 reserved1;
+ __u64 reserved2;
+ } __attribute__ ((packed)) unknown;
+ } device_path;
+ __u8 reserved4;
+ __u8 checksum;
+} __attribute__ ((packed));
+
+struct edd_info {
+ __u8 device;
+ __u8 version;
+ __u16 interface_support;
+ __u16 legacy_max_cylinder;
+ __u8 legacy_max_head;
+ __u8 legacy_sectors_per_track;
+ struct edd_device_params params;
+} __attribute__ ((packed));
+
+/* The so-called "zeropage" */
+struct boot_params {
+ struct screen_info screen_info; /* 0x000 */
+ struct apm_bios_info apm_bios_info; /* 0x040 */
+ __u8 _pad2[12]; /* 0x054 */
+ struct ist_info ist_info; /* 0x060 */
+ __u8 _pad3[16]; /* 0x070 */
+ __u8 hd0_info[16]; /* obsolete! */ /* 0x080 */
+ __u8 hd1_info[16]; /* obsolete! */ /* 0x090 */
+ struct sys_desc_table sys_desc_table; /* 0x0a0 */
+ __u8 _pad4[144]; /* 0x0b0 */
+ struct edid_info edid_info; /* 0x140 */
+ struct efi_info efi_info; /* 0x1c0 */
+ __u32 alt_mem_k; /* 0x1e0 */
+ __u32 scratch; /* Scratch field! */ /* 0x1e4 */
+ __u8 e820_entries; /* 0x1e8 */
+ __u8 eddbuf_entries; /* 0x1e9 */
+ __u8 edd_mbr_sig_buf_entries; /* 0x1ea */
+ __u8 _pad6[6]; /* 0x1eb */
+ struct setup_header hdr; /* setup header */ /* 0x1f1 */
+ __u8 _pad7[0x290-0x1f1-sizeof(struct setup_header)];
+ __u32 edd_mbr_sig_buffer[EDD_MBR_SIG_MAX]; /* 0x290 */
+ struct e820entry e820_map[E820MAX]; /* 0x2d0 */
+ __u8 _pad8[48]; /* 0xcd0 */
+ struct edd_info eddbuf[EDDMAXNR]; /* 0xd00 */
+ __u8 _pad9[276]; /* 0xeec */
+} __attribute__((packed));
+
diff --git a/bootstub.c b/bootstub.c
new file mode 100644
index 0000000..c2a1ebd
--- /dev/null
+++ b/bootstub.c
@@ -0,0 +1,80 @@
+/* bootstub.c for loading protected mode kernel
+ * Copyright (C) 2008 Alek Du <alek.du@intel.com>
+ */
+
+#include "types.h"
+#include "bootstub.h"
+#include "bootparam.h"
+
+struct gdt_ptr {
+ u16 len;
+ u32 ptr;
+} __attribute__((packed));
+
+static void setup_gdt(void)
+{
+ static const u64 boot_gdt[] __attribute__((aligned(16))) = {
+ /* CS: code, read/execute, 4 GB, base 0 */
+ [GDT_ENTRY_BOOT_CS] = GDT_ENTRY(0xc09b, 0, 0xfffff),
+ /* DS: data, read/write, 4 GB, base 0 */
+ [GDT_ENTRY_BOOT_DS] = GDT_ENTRY(0xc093, 0, 0xfffff),
+ };
+ static struct gdt_ptr gdt;
+
+ gdt.len = sizeof(boot_gdt)-1;
+ gdt.ptr = (u32)&boot_gdt;
+
+ asm volatile("lgdtl %0" : : "m" (gdt));
+}
+
+static void setup_idt(void)
+{
+ static const struct gdt_ptr null_idt = {0, 0};
+ asm volatile("lidtl %0" : : "m" (null_idt));
+}
+
+static void *memcpy(void *dest, const void *src, size_t count)
+{
+ char *tmp = dest;
+ const char *s = src;
+
+ while (count--)
+ *tmp++ = *s++;
+ return dest;
+}
+
+static void *memset(void *s, int c, size_t count)
+{
+ char *xs = s;
+
+ while (count--)
+ *xs++ = c;
+ return s;
+}
+
+static void setup_boot_params(struct boot_params *bp, struct setup_header *sh)
+{
+ memset(bp, 0, sizeof (struct boot_params));
+ memcpy(&bp->hdr, sh, sizeof (struct setup_header));
+}
+
+static int get_32bit_entry(unsigned char *ptr)
+{
+ while (1){
+ if (*(u32 *)ptr == SETUP_SIGNATURE)
+ break;
+ ptr++;
+ }
+ ptr+=4;
+ return (((unsigned int)ptr+511)/512)*512;
+}
+
+int main(void)
+{
+ setup_idt();
+ setup_gdt();
+ setup_boot_params((struct boot_params *)BOOT_PARAMS_OFFSET,
+ (struct setup_header*)SETUP_HEADER_OFFSET);
+ return get_32bit_entry((unsigned char *)BZIMAGE_OFFSET);
+}
+
diff --git a/bootstub.h b/bootstub.h
new file mode 100644
index 0000000..5978379
--- /dev/null
+++ b/bootstub.h
@@ -0,0 +1,28 @@
+/* define bootstub constrains here, like memory map etc.
+ */
+
+#ifndef _BOOT_STUB_HEAD
+#define _BOOT_STUB_HEAD
+
+#define CMDLINE_OFFSET 0x100000
+#define BZIMAGE_OFFSET 0x102000
+#define STACK_OFFSET 0x101000
+#define SETUP_HEADER_OFFSET (BZIMAGE_OFFSET + 0x1F1)
+#define SETUP_HEADER_SIZE (0x0202 + *(unsigned char*)(0x0201+BZIMAGE_OFFSET))
+#define BOOT_PARAMS_OFFSET 0x8000
+#define SETUP_SIGNATURE 0x5a5aaa55
+
+#define GDT_ENTRY_BOOT_CS 2
+#define __BOOT_CS (GDT_ENTRY_BOOT_CS * 8)
+
+#define GDT_ENTRY_BOOT_DS (GDT_ENTRY_BOOT_CS + 1)
+#define __BOOT_DS (GDT_ENTRY_BOOT_DS * 8)
+
+#define GDT_ENTRY(flags, base, limit) \
+ (((u64)(base & 0xff000000) << 32) | \
+ ((u64)flags << 40) | \
+ ((u64)(limit & 0x00ff0000) << 32) | \
+ ((u64)(base & 0x00ffffff) << 16) | \
+ ((u64)(limit & 0x0000ffff)))
+
+#endif
diff --git a/bootstub.lds b/bootstub.lds
new file mode 100644
index 0000000..4248c54
--- /dev/null
+++ b/bootstub.lds
@@ -0,0 +1,37 @@
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_ARCH(i386)
+ENTRY(_start)
+SECTIONS
+{
+ . = 0x101000; /* bootstub entry in DRAM */
+ .text.head : {
+ _head = . ;
+ *(.text.head)
+ _ehead = . ;
+ }
+ .text : {
+ _text = .; /* Text */
+ *(.text)
+ *(.text.*)
+ _etext = . ;
+ }
+ .rodata : {
+ _rodata = . ;
+ *(.rodata) /* read-only data */
+ *(.rodata.*)
+ _erodata = . ;
+ }
+ .data : {
+ _data = . ;
+ *(.data)
+ *(.data.*)
+ _edata = . ;
+ }
+ .bss : {
+ _bss = . ;
+ *(.bss)
+ *(.bss.*)
+ *(COMMON)
+ _end = . ;
+ }
+}
diff --git a/head.S b/head.S
new file mode 100644
index 0000000..7431584
--- /dev/null
+++ b/head.S
@@ -0,0 +1,58 @@
+/* head.S for bootstub to load protected mode kernel
+ * Copyright (C) 2008 Alek Du <alek.du@intel.com>
+ *
+ * Note. When FW hand-off control to bootstub, the CPU is already in protected
+ * Mode with 1. GDT(8)=4G GDT(10)=4G
+ * 2. CS=8, DS=ES=FS=GS=10
+ * 3. Paging mode disabled
+ * 4. Interrupt ENABLED
+ */
+
+/* When bootstub get control, the memory map in DRAM is like:
+ * ~ ~
+ * 0x102000 | initramfs |
+ *+bzImage size +-----------------------+
+ * | bzImage |
+ * 0x102000 +-----------------------+
+ * | boot stub |
+ * 0x101000 +-----------------------+
+ * | free space |
+ * | used as stack |
+ * 0x100100 +-----------------------+
+ * | kernel cmdline |
+ * 0x100000 +-----------------------+
+*/
+
+#include "bootstub.h"
+
+.text
+
+.section ".text.head","ax",@progbits
+ .globl _start
+
+_start:
+ cld
+ cli
+ /* DS=ES=FS=GS=10 */
+ movl 0x2, %eax
+ movl %eax, %ds
+ movl %eax, %es
+ movl %eax, %fs
+ movl %eax, %gs
+ movl %eax, %ss
+ /* setup stack, because we are heading off to "C" */
+ movl $STACK_OFFSET, %esp
+ /* after call main, GDT was set (0x10 and 0x18) IDT was clear
+ * eax will store 32bit entry of bzImage
+ */
+ calll main
+ ljmp $__BOOT_CS,$1f
+1:
+ /* tell kernel where is boot_param */
+ movl $(BOOT_PARAMS_OFFSET), %esi
+ xor %ebp, %ebp
+ xor %edi, %edi
+ xor %ebx, %ebx
+
+ jmpl *%eax # Jump to the 32-bit entrypoint
+
diff --git a/types.h b/types.h
new file mode 100644
index 0000000..b84de8e
--- /dev/null
+++ b/types.h
@@ -0,0 +1,20 @@
+/* types.h
+ * very early types definition
+ */
+
+#ifndef _TYPES_
+#define _TYPES_
+
+typedef unsigned char __u8;
+typedef unsigned short __u16;
+typedef unsigned int __u32;
+typedef unsigned long long __u64;
+
+typedef __u8 u8;
+typedef __u16 u16;
+typedef __u32 u32;
+typedef __u64 u64;
+
+typedef unsigned int size_t;
+
+#endif