blob: f028c6db3cf54916180414a80a0e2a2749e3fd10 [file] [log] [blame]
/* 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 size_t strnlen(const char *s, size_t maxlen)
{
const char *es = s;
while (*es && maxlen) {
es++;
maxlen--;
}
return (es - s);
}
static void setup_boot_params(struct boot_params *bp, struct setup_header *sh)
{
memset(bp, 0, sizeof (struct boot_params));
bp->screen_info.orig_video_mode = 1;
bp->screen_info.orig_video_lines = 25;
bp->screen_info.orig_video_cols = 80;
bp->alt_mem_k = *(u32 *)MEMORY_SIZE_OFFSET;
memcpy(&bp->hdr, sh, sizeof (struct setup_header));
bp->hdr.cmd_line_ptr = CMDLINE_OFFSET;
bp->hdr.cmdline_size = strnlen((const char *)CMDLINE_OFFSET,256);
bp->hdr.ramdisk_size = *(u32 *)INITRD_SIZE_OFFSET;
bp->hdr.ramdisk_image = BZIMAGE_OFFSET + *(u32 *)BZIMAGE_SIZE_OFFSET + *(u32 *)INITRD_SIZE_OFFSET;
}
static int get_32bit_entry(unsigned char *ptr)
{
while (1){
if (*(u32 *)ptr == SETUP_SIGNATURE && *(u32 *)(ptr+4) == 0)
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);
}