2 * Copyright (C) 2001-2003 Hewlett-Packard Co.
3 * Contributed by Stephane Eranian <eranian@hpl.hp.com>
4 * Contributed by Mike Johnston <johnston@intel.com>
5 * Contributed by Chris Ahna <christopher.j.ahna@intel.com>
6 * Contributed by Fenghua Yu <fenghua.yu@intel.com>
7 * Contributed by Bibo Mao <bibo.mao@intel.com>
8 * Contributed by Chandramouli Narayanan <mouli@linux.intel.com>
10 * This file is part of the ELILO, the EFI Linux boot loader.
12 * ELILO is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2, or (at your option)
17 * ELILO is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with ELILO; see the file COPYING. If not, write to the Free
24 * Software Foundation, 59 Temple Place - Suite 330, Boston, MA
27 * Please check out the elilo.txt for complete documentation on how
28 * to use this program.
32 * This file is used to define all the x86_64-specific data structures
33 * and constant used by the generic ELILO
35 #ifndef __ELILO_SYSDEPS_X86_64_H__
36 #define __ELILO_SYSDEPS_X86_64_H__
38 #define ELILO_ARCH "x86_64" /* ASCII string */
39 #define PADDR_MASK 0xfffffff
41 /* for now use library versions */
42 #define Memset(a,v,n) SetMem((a),(n),(v))
43 #define Memcpy(a,b,n) CopyMem((a),(b),(n))
45 /* Put initrd to far away from kernel image to avoid conflict.
46 * May need to adjust this number if it is not big enough.
48 #define INITRD_START (50*1024*1024)
50 /* Default start address for kernel. */
51 #define DEFAULT_KERNEL_START 0x100000
55 * This version must match the one in the kernel.
57 * This table was put together using information from the
58 * following Linux kernel source files:
60 * linux/arch/i386/kernel/setup.c
61 * linux/arch/i386/boot/bootsect.S
62 * linux/arch/i386/boot/setup.S
63 * linux/arch/i386/boot/video.S
65 * New fields in this structure for EFI and ELILO are:
69 * A new bit, LDRFLAG_BOOT_PARAM_RELOC, in the loader_flags
70 * field is also defined in this file.
75 /* Definitions for converting EFI memory map to E820 map for Linux
76 * These definitions are from include/linux/asm-x86_64/e820.h
77 * The structure x86_64_boot_params below is updated to accommodate E820 map
78 * EFI memory map is converted to E820 map in this structure and passed
79 * to Linux. This way the OS does not need to do the conversion.
82 #define E820_RESERVED 2
85 #define E820_EXEC_CODE 5
89 UINT64 addr; /* start of memory segment */
90 UINT64 size; /* size of memory segment */
91 UINT32 type; /* type of memory segment */
92 } __attribute__((packed));
95 typedef union x86_64_boot_params {
98 /* Cursor position before passing control to kernel. */
99 /* 0x00 */ UINT8 orig_cursor_col; /* LDR */
100 /* 0x01 */ UINT8 orig_cursor_row; /* LDR */
102 /* Available contiguous extended memory in KB. */
103 /* 0x02 */ UINT16 ext_mem_k; /* LDR */
105 /* Video page, mode and screen width before passing control to kernel. */
106 /* 0x04 */ UINT16 orig_video_page; /* LDR */
107 /* 0x06 */ UINT8 orig_video_mode; /* LDR */
108 /* 0x07 */ UINT8 orig_video_cols; /* LDR */
110 /* 0x08 */ UINT16 pad_1; /* unused */
113 /* 0x0A */ UINT16 orig_ega_bx; /* LDR */
115 /* 0x0C */ UINT16 pad_2; /* unused */
117 /* Screen height before passing control to kernel. */
118 /* 0x0E */ UINT8 orig_video_rows; /* LDR */
121 /* 0x0F */ UINT8 is_vga; /* LDR */
122 /* 0x10 */ UINT16 orig_video_points; /* LDR */
125 /* 0x12 */ UINT16 lfb_width; /* LDR */
126 /* 0x14 */ UINT16 lfb_height; /* LDR */
127 /* 0x16 */ UINT16 lfb_depth; /* LDR */
128 /* 0x18 */ UINT32 lfb_base; /* LDR */
129 /* 0x1C */ UINT32 lfb_size; /* LDR */
131 /* Offset of command line (from start of ia32_boot_param struct). */
132 /* The command line magik number must be set for the kernel setup */
133 /* code to use the command line offset. */
134 /* 0x20 */ UINT16 cmdline_magik; /* LDR */
135 #define CMDLINE_MAGIK 0xA33F
136 /* 0x22 */ UINT16 cmdline_offset; /* LDR */
139 /* 0x24 */ UINT16 lfb_line_len; /* LDR */
142 /* 0x26 */ UINT8 lfb_red_size; /* LDR */
143 /* 0x27 */ UINT8 lfb_red_pos; /* LDR */
144 /* 0x28 */ UINT8 lfb_green_size; /* LDR */
145 /* 0x29 */ UINT8 lfb_green_pos; /* LDR */
146 /* 0x2A */ UINT8 lfb_blue_size; /* LDR */
147 /* 0x2B */ UINT8 lfb_blue_pos; /* LDR */
148 /* 0x2C */ UINT8 lfb_rsvd_size; /* LDR */
149 /* 0x2D */ UINT8 lfb_rsvd_pos; /* LDR */
152 /* 0x2E */ UINT16 vesa_seg; /* LDR */
153 /* 0x30 */ UINT16 vesa_off; /* LDR */
156 /* 0x32 */ UINT16 lfb_pages; /* LDR */
157 /* 0x34 */ UINT8 lfb_reserved[0x0C]; /* reserved */
160 /* 0x40 */ UINT16 apm_bios_ver; /* LDR */
161 #define NO_APM_BIOS 0x0000
164 /* 0x42 */ UINT16 bios_code_seg; /* LDR */
165 /* 0x44 */ UINT32 bios_entry_point; /* LDR */
166 /* 0x48 */ UINT16 bios_code_seg16; /* LDR */
167 /* 0x4A */ UINT16 bios_data_seg; /* LDR */
170 /* 0x4C */ UINT16 apm_bios_flags; /* LDR */
171 #define NO_32BIT_APM_MASK 0xFFFD
174 /* 0x4E */ UINT32 bios_code_len; /* LDR */
175 /* 0x52 */ UINT16 bios_data_len; /* LDR */
177 /* 0x54 */ UINT8 pad_3[0x2C]; /* unused */
180 /* 0x80 */ UINT8 hd0_info[0x10]; /* LDR */
181 /* 0x90 */ UINT8 hd1_info[0x10]; /* LDR */
184 /* 0xA0 */ UINT16 mca_info_len; /* LDR */
185 /* 0xA2 */ UINT8 mca_info_buf[0x10]; /* LDR */
187 /* 0xB2 */ UINT8 pad_4[0x10E]; /* unused */
189 /* EFI boot loader signature. */
190 /* 0x1C0 */ UINT8 efi_loader_sig[4]; /* LDR */
191 #define EFI_LOADER_SIG_X64 "EL64"
193 /* Address of the EFI system table. */
194 /* 0x1C4 */ UINT32 efi_sys_tbl; /* LDR */
196 /* EFI memory descriptor size. */
197 /* 0x1C8 */ UINT32 efi_mem_desc_size; /* LDR */
199 /* EFI memory descriptor version. */
200 /* 0x1CC */ UINT32 efi_mem_desc_ver; /* LDR */
202 /* Address & size of EFI memory map. */
203 /* 0x1D0 */ UINT32 efi_mem_map; /* LDR */
204 /* 0x1D4 */ UINT32 efi_mem_map_size; /* LDR */
206 /* 0x1D8 */ UINT32 efi_sys_tbl_hi; /* LDR */
207 /* 0x1DC */ UINT32 efi_mem_map_hi; /* LDR */
209 /* Available contiguous extended memory in KB. */
210 /* 0x1E0 */ UINT32 alt_mem_k; /* LDR */
212 /* 0x1E4 */ UINT32 pad_51; /* unused */
213 /* 0x1E8 */ UINT8 e820_nrmap;
214 /* 0x1E9 */ UINT32 pad_52[2]; /* unused */
216 /* Size of setup code in sectors (1 sector == 512 bytes). */
217 /* 0x1F1 */ UINT8 setup_sectors; /* BLD */
220 /* 0x1F2 */ UINT16 mount_root_rdonly; /* BLD */
223 /* 0x1F4 */ UINT32 sys_size; /* BLD */
226 /* 0x1F8 */ UINT16 ram_size_DNU; /* BLD */
229 /* 0x1FA */ UINT16 video_mode_flag; /* BLD */
232 /* 0x1FC */ UINT16 orig_root_dev; /* BLD */
235 /* 0x1FE */ UINT16 boot_flag; /* ? */
237 /* Jump past setup data (not used in EFI). */
238 /* 0x200 */ UINT16 jump; /* BLD */
240 /* Setup data signature. */
241 /* 0x202 */ UINT8 setup_sig[4]; /* BLD */
242 #define SETUP_SIG "HdrS"
245 /* 0x206 */ UINT8 hdr_minor; /* BLD */
246 /* 0x207 */ UINT8 hdr_major; /* BLD */
249 /* 0x208 */ UINT32 rm_switch; /* LDD */
252 /* 0x20C */ UINT16 start_sys_seg; /* BLD */
255 /* 0x20E */ UINT16 kernel_verstr_offset; /* BLD */
257 /* Loader type & version. */
258 /* 0x210 */ UINT8 loader_type; /* LDR */
259 #define LDRTYPE_ELILO 0x50 /* 5?h == elilo */
260 /* ?0h == revision */
262 /* 0x211 */ UINT8 loader_flags; /* BLD and LDR */
263 #define LDRFLAG_CAN_USE_HEAP 0x80
264 #define LDRFLAG_BOOT_PARAM_RELOC 0x40
267 /* 0x212 */ UINT16 setup_move_size; /* BLD */
270 /* 0x214 */ UINT32 kernel_start; /* LDR */
273 /* 0x218 */ UINT32 initrd_start; /* LDR */
274 /* 0x21C */ UINT32 initrd_size; /* LDR */
277 /* 0x220 */ UINT32 bootsect_helper_DNU; /* BLD */
280 /* 0x224 */ UINT16 heap_end_ptr; /* LDR */
283 /* 0x226 */ UINT8 ext_loader_ver; /* LDR */
284 /* 0x227 */ UINT8 ext_loader_type; /* LDR */
286 /* 0x228 */ UINT32 cmdline_addr; /* LDR */
287 /* 0x22C */ UINT32 initrd_addr_max; /* BLD */
288 /* 0x230 */ UINT32 kernel_alignment; /* BLD */
289 /* 0x234 */ UINT8 relocatable_kernel; /* BLD */
290 /* 0x235 */ UINT8 pad_8[3];
291 /* 0x238 */ UINT32 pad_9[38];
292 /* 0x2D0 */ UINT8 e820_map[2560];
298 * The stuff below here is for jumping to the kernel.
302 * Some macros to copy and set memory after EFI has been
306 #define MEMCPY(to, from, cnt) { \
307 UINT8 *t = (UINT8 *)(to); \
308 UINT8 *f = (UINT8 *)(from); \
310 if (t && f && n && (t<f)) { \
314 } else if (t && f && n && (t>f)) { \
323 #define MEMSET(ptr, size, val) { \
324 UINT8 *p = (UINT8 *)(ptr); \
325 UINTN n = (UINTN)(size); \
326 UINT8 v = (UINT8)(val); \
335 * Descriptor table pointer format.
344 extern UINTN high_base_mem;
345 extern UINTN high_ext_mem;
347 extern boot_params_t *param_start;
348 extern UINTN param_size;
350 extern VOID *kernel_start;
351 extern UINTN kernel_size;
352 extern VOID *kernel_load_address;
354 extern VOID *initrd_start;
355 extern UINTN initrd_size;
357 extern dt_addr_t gdt_addr;
358 extern dt_addr_t idt_addr;
360 extern UINT16 init_gdt[];
361 extern UINTN sizeof_init_gdt;
363 extern UINT8 rmswitch_image[];
364 extern UINTN rmswitch_size;
366 extern INTN x86_64_use_legacy_free_boot();
367 extern INTN x86_64_text_mode();
370 * How to jump to kernel code
375 start_kernel(VOID *kentry, boot_params_t *bp)
384 * Disable interrupts.
386 asm volatile ( "cli" : : );
389 * Relocate kernel (if needed).
390 * This assumes that the initrd didn't get loaded overlapping where
391 * we're planning to copy the kernel, but that's pretty unlikely
392 * since we couldn't alloc that space for the kernel (or the kernel
393 * would already be there).
395 if (kernel_start != kernel_load_address) {
396 MEMCPY(kernel_start, kernel_load_address, kernel_size);
400 * Copy boot sector, setup data and command line
401 * to final resting place. We need to copy
402 * BOOT_PARAM_MEMSIZE bytes.
405 MEMCPY(high_base_mem, bp, 0x4000);
407 bp = (boot_params_t *)high_base_mem;
408 bp->s.cmdline_addr = high_base_mem + bp->s.cmdline_offset;
411 * Initialize Linux GDT.
414 MEMSET(gdt_addr.base, gdt_addr.limit, 0);
415 MEMCPY(gdt_addr.base, init_gdt, sizeof_init_gdt);
417 // fixme: why x86_64_use_legacy_free_boot() goes to _relocate?
419 if (! x86_64_use_legacy_free_boot()) {
422 * Copy our real mode transition code to 0x7C00.
425 MEMCPY(0x7C00, rmswitch_image, rmswitch_size);
427 asm volatile ( "mov $0x7C00, %%rbx" : : );
428 asm volatile ( "jmp *%%rbx" : : );
433 * Load descriptor table pointers.
436 asm volatile ( "lidt %0" : : "m" (idt_addr) );
437 asm volatile ( "lgdt %0" : : "m" (gdt_addr) );
440 * rsi := address of boot sector and setup data
443 asm volatile ( "mov %0, %%rsi" : : "m" (high_base_mem) );
446 * Jump to kernel entry point.
448 * Cast is to tell gcc that we know we're going from
449 * 64-bit ptr to 32-bit integer.
451 jumpvector.kernel_entry=(UINT32)((UINT64)kentry);
452 jumpvector.kernel_cs=0x10;
453 jump_start = (VOID *)&jumpvector;
454 //asm volatile ( "mov %0, %%rcx" : : "m" (&jumpvector) );
455 asm volatile ( "mov %0, %%rcx" : : "m" (jump_start) );
456 asm volatile ( "ljmp *(%%rcx)" : :);
457 /* Never come back to here. */
460 typedef struct sys_img_options {
461 UINT8 dummy; /* forces non-zero offset for first field */
462 UINT8 text_mode; /* do not try to initialize Graphics Output Protocol */
465 #endif /* __ELILO_SYSDEPS_X86_64_H__ */