blob: f028c6db3cf54916180414a80a0e2a2749e3fd10 [file] [log] [blame]
Alek Dub7f7baf2008-05-13 16:23:15 +08001/* bootstub.c for loading protected mode kernel
2 * Copyright (C) 2008 Alek Du <alek.du@intel.com>
3 */
4
5#include "types.h"
6#include "bootstub.h"
7#include "bootparam.h"
8
9struct gdt_ptr {
10 u16 len;
11 u32 ptr;
12} __attribute__((packed));
13
14static void setup_gdt(void)
15{
16 static const u64 boot_gdt[] __attribute__((aligned(16))) = {
17 /* CS: code, read/execute, 4 GB, base 0 */
18 [GDT_ENTRY_BOOT_CS] = GDT_ENTRY(0xc09b, 0, 0xfffff),
19 /* DS: data, read/write, 4 GB, base 0 */
20 [GDT_ENTRY_BOOT_DS] = GDT_ENTRY(0xc093, 0, 0xfffff),
21 };
22 static struct gdt_ptr gdt;
23
24 gdt.len = sizeof(boot_gdt)-1;
25 gdt.ptr = (u32)&boot_gdt;
26
27 asm volatile("lgdtl %0" : : "m" (gdt));
28}
29
30static void setup_idt(void)
31{
32 static const struct gdt_ptr null_idt = {0, 0};
33 asm volatile("lidtl %0" : : "m" (null_idt));
34}
35
36static void *memcpy(void *dest, const void *src, size_t count)
37{
38 char *tmp = dest;
39 const char *s = src;
40
41 while (count--)
42 *tmp++ = *s++;
43 return dest;
44}
45
46static void *memset(void *s, int c, size_t count)
47{
48 char *xs = s;
49
50 while (count--)
51 *xs++ = c;
52 return s;
53}
54
Alek Dud6f7f142008-05-14 16:59:04 +080055static size_t strnlen(const char *s, size_t maxlen)
56{
57 const char *es = s;
58 while (*es && maxlen) {
59 es++;
60 maxlen--;
61 }
62
63 return (es - s);
64}
65
66
Alek Dub7f7baf2008-05-13 16:23:15 +080067static void setup_boot_params(struct boot_params *bp, struct setup_header *sh)
68{
69 memset(bp, 0, sizeof (struct boot_params));
Alek Du0d217772008-05-14 15:30:32 +080070 bp->screen_info.orig_video_mode = 1;
71 bp->screen_info.orig_video_lines = 25;
72 bp->screen_info.orig_video_cols = 80;
Alek Du0fdceca2008-05-14 17:36:34 +080073 bp->alt_mem_k = *(u32 *)MEMORY_SIZE_OFFSET;
Alek Du2c4ebec2008-05-13 16:56:23 +080074 memcpy(&bp->hdr, sh, sizeof (struct setup_header));
75 bp->hdr.cmd_line_ptr = CMDLINE_OFFSET;
Alek Du0fdceca2008-05-14 17:36:34 +080076 bp->hdr.cmdline_size = strnlen((const char *)CMDLINE_OFFSET,256);
77 bp->hdr.ramdisk_size = *(u32 *)INITRD_SIZE_OFFSET;
78 bp->hdr.ramdisk_image = BZIMAGE_OFFSET + *(u32 *)BZIMAGE_SIZE_OFFSET + *(u32 *)INITRD_SIZE_OFFSET;
Alek Dub7f7baf2008-05-13 16:23:15 +080079}
80
81static int get_32bit_entry(unsigned char *ptr)
82{
83 while (1){
Alek Du1f2cc2d2008-05-14 15:37:56 +080084 if (*(u32 *)ptr == SETUP_SIGNATURE && *(u32 *)(ptr+4) == 0)
Alek Dub7f7baf2008-05-13 16:23:15 +080085 break;
86 ptr++;
87 }
88 ptr+=4;
89 return (((unsigned int)ptr+511)/512)*512;
90}
91
92int main(void)
93{
94 setup_idt();
95 setup_gdt();
96 setup_boot_params((struct boot_params *)BOOT_PARAMS_OFFSET,
Alek Du0fdceca2008-05-14 17:36:34 +080097 (struct setup_header *)SETUP_HEADER_OFFSET);
Alek Dub7f7baf2008-05-13 16:23:15 +080098 return get_32bit_entry((unsigned char *)BZIMAGE_OFFSET);
99}
100