diff options
author | Alek Du <alek.du@intel.com> | 2008-05-13 16:23:15 +0800 |
---|---|---|
committer | Patrick Tjin <pattjin@google.com> | 2014-07-21 20:22:35 -0700 |
commit | b7f7baf2e23345011ae4079e62c470418c2424e6 (patch) | |
tree | 708aa0d3e1934ad546cba7075106ce3cc6e7ccf4 | |
parent | 321a1bb385b0002ed6835e5fb22d80e5ef9165ac (diff) | |
download | bootstub-b7f7baf2e23345011ae4079e62c470418c2424e6.tar.gz |
* bootstub version 0.01
-rw-r--r-- | bootparam.h | 274 | ||||
-rw-r--r-- | bootstub.c | 80 | ||||
-rw-r--r-- | bootstub.h | 28 | ||||
-rw-r--r-- | bootstub.lds | 37 | ||||
-rw-r--r-- | head.S | 58 | ||||
-rw-r--r-- | types.h | 20 |
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 = . ;
+ }
+}
@@ -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 + @@ -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 |