blob: 1b9d1cad8ea1b4b344bd78a35b70f7234c7d3292 [file] [log] [blame]
Alek Dub379eef2008-05-21 13:37:04 +08001/*
2 * bootstub 32 bit entry setting routings
3 * Copyright (C) 2008, Alek Du <alek.du@intel.com> Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17 *
Alek Dub7f7baf2008-05-13 16:23:15 +080018 */
19
20#include "types.h"
21#include "bootstub.h"
22#include "bootparam.h"
Alek Duc8496d12008-07-10 14:46:17 +080023#include "spi-uart.h"
24
25#define bs_printk(x) { if (! *(int *)SPI_UART_SUPPRESSION) bs_spi_printk(x);}
Alek Dub7f7baf2008-05-13 16:23:15 +080026
27struct gdt_ptr {
28 u16 len;
29 u32 ptr;
30} __attribute__((packed));
31
32static void setup_gdt(void)
33{
34 static const u64 boot_gdt[] __attribute__((aligned(16))) = {
35 /* CS: code, read/execute, 4 GB, base 0 */
36 [GDT_ENTRY_BOOT_CS] = GDT_ENTRY(0xc09b, 0, 0xfffff),
37 /* DS: data, read/write, 4 GB, base 0 */
38 [GDT_ENTRY_BOOT_DS] = GDT_ENTRY(0xc093, 0, 0xfffff),
39 };
40 static struct gdt_ptr gdt;
41
42 gdt.len = sizeof(boot_gdt)-1;
43 gdt.ptr = (u32)&boot_gdt;
44
45 asm volatile("lgdtl %0" : : "m" (gdt));
46}
47
48static void setup_idt(void)
49{
50 static const struct gdt_ptr null_idt = {0, 0};
51 asm volatile("lidtl %0" : : "m" (null_idt));
52}
53
54static void *memcpy(void *dest, const void *src, size_t count)
55{
56 char *tmp = dest;
57 const char *s = src;
58
59 while (count--)
60 *tmp++ = *s++;
61 return dest;
62}
63
64static void *memset(void *s, int c, size_t count)
65{
66 char *xs = s;
67
68 while (count--)
69 *xs++ = c;
70 return s;
71}
72
Alek Dud6f7f142008-05-14 16:59:04 +080073static size_t strnlen(const char *s, size_t maxlen)
74{
75 const char *es = s;
76 while (*es && maxlen) {
77 es++;
78 maxlen--;
79 }
80
81 return (es - s);
82}
83
84
Alek Dub7f7baf2008-05-13 16:23:15 +080085static void setup_boot_params(struct boot_params *bp, struct setup_header *sh)
86{
87 memset(bp, 0, sizeof (struct boot_params));
Alek Duacca6fb2008-06-02 14:19:57 +080088 bp->screen_info.orig_video_mode = 0;
89 bp->screen_info.orig_video_lines = 0;
90 bp->screen_info.orig_video_cols = 0;
Alek Du07cd7e22008-05-22 16:36:16 +080091 bp->alt_mem_k = 128*1024; // hard coded 128M mem here, since SFI will override it
Alek Du2c4ebec2008-05-13 16:56:23 +080092 memcpy(&bp->hdr, sh, sizeof (struct setup_header));
93 bp->hdr.cmd_line_ptr = CMDLINE_OFFSET;
Alek Du0fdceca2008-05-14 17:36:34 +080094 bp->hdr.cmdline_size = strnlen((const char *)CMDLINE_OFFSET,256);
Alek Du853e56b2008-05-16 16:44:31 +080095 bp->hdr.type_of_loader = 0xff; //bootstub is unknown bootloader for kernel :)
Alek Du0fdceca2008-05-14 17:36:34 +080096 bp->hdr.ramdisk_size = *(u32 *)INITRD_SIZE_OFFSET;
Alek Du853e56b2008-05-16 16:44:31 +080097 bp->hdr.ramdisk_image = (bp->alt_mem_k*1024 - bp->hdr.ramdisk_size) & 0xFFFFF000;
Jacob Pana5286332009-03-10 04:09:30 -070098 bp->hdr.hardware_subarch = X86_SUBARCH_MRST;
Alek Du853e56b2008-05-16 16:44:31 +080099 memcpy((u8*)bp->hdr.ramdisk_image, (u8 *)BZIMAGE_OFFSET + *(u32 *)BZIMAGE_SIZE_OFFSET, bp->hdr.ramdisk_size);
Alek Dub7f7baf2008-05-13 16:23:15 +0800100}
101
102static int get_32bit_entry(unsigned char *ptr)
103{
104 while (1){
Alek Du1f2cc2d2008-05-14 15:37:56 +0800105 if (*(u32 *)ptr == SETUP_SIGNATURE && *(u32 *)(ptr+4) == 0)
Alek Dub7f7baf2008-05-13 16:23:15 +0800106 break;
107 ptr++;
108 }
109 ptr+=4;
110 return (((unsigned int)ptr+511)/512)*512;
111}
112
Alek Du6135ebb2008-05-20 14:07:07 +0800113int bootstub(void)
Alek Dub7f7baf2008-05-13 16:23:15 +0800114{
115 setup_idt();
116 setup_gdt();
Alek Duc694cee2009-03-12 15:58:07 +0800117 bs_printk("Bootstub Version: 0.5 ...\n");
Alek Dub7f7baf2008-05-13 16:23:15 +0800118 setup_boot_params((struct boot_params *)BOOT_PARAMS_OFFSET,
Alek Du0fdceca2008-05-14 17:36:34 +0800119 (struct setup_header *)SETUP_HEADER_OFFSET);
Alek Dub7f7baf2008-05-13 16:23:15 +0800120 return get_32bit_entry((unsigned char *)BZIMAGE_OFFSET);
121}