Imported Upstream version 3.8
[debian/elilo] / x86_64 / sysdeps.h
1 /*
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>
9  *
10  * This file is part of the ELILO, the EFI Linux boot loader.
11  *
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)
15  *  any later version.
16  *
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.
21  *
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
25  *  02111-1307, USA.
26  *
27  * Please check out the elilo.txt for complete documentation on how
28  * to use this program.
29  */
30
31 /*
32  * This file is used to define all the x86_64-specific data structures
33  * and constant used by the generic ELILO
34  */
35 #ifndef __ELILO_SYSDEPS_X86_64_H__
36 #define __ELILO_SYSDEPS_X86_64_H__
37
38 #define ELILO_ARCH      "x86_64" /* ASCII string */
39 #define PADDR_MASK      0xfffffff
40
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))
44
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.
47  */
48 #define INITRD_START   (50*1024*1024)
49
50 /*
51  * This version must match the one in the kernel.
52  *
53  * This table was put together using information from the
54  * following Linux kernel source files:
55  *   linux/include/tty.h
56  *   linux/arch/i386/kernel/setup.c
57  *   linux/arch/i386/boot/bootsect.S
58  *   linux/arch/i386/boot/setup.S
59  *   linux/arch/i386/boot/video.S
60  *
61  * New fields in this structure for EFI and ELILO are:
62  *   efi_loader_sig
63  *   efi_st_addr
64  *
65  * A new bit, LDRFLAG_BOOT_PARAM_RELOC, in the loader_flags
66  * field is also defined in this file.
67  */
68
69 #pragma pack(1)
70
71 /* Definitions for converting EFI memory map to E820 map for Linux 
72  * These definitions are from include/linux/asm-x86_64/e820.h
73  * The structure x86_64_boot_params below is updated to accommodate E820 map 
74  * EFI memory map is converted to E820 map in this structure and passed
75  * to Linux. This way the OS does not need to do the conversion.
76  */
77 #define E820_RAM        1
78 #define E820_RESERVED   2
79 #define E820_ACPI       3
80 #define E820_NVS        4
81 #define E820_EXEC_CODE  5
82 #define E820_MAX        128
83
84 struct e820entry {
85         UINT64 addr;    /* start of memory segment */
86         UINT64 size;    /* size of memory segment */
87         UINT32 type;    /* type of memory segment */
88 } __attribute__((packed));
89
90
91 typedef union x86_64_boot_params {
92         UINT8 raw[0x2000];
93         struct {
94 /* Cursor position before passing control to kernel. */
95 /* 0x00 */      UINT8 orig_cursor_col;          /* LDR */
96 /* 0x01 */      UINT8 orig_cursor_row;          /* LDR */
97
98 /* Available contiguous extended memory in KB. */
99 /* 0x02 */      UINT16 ext_mem_k;               /* LDR */
100
101 /* Video page, mode and screen width before passing control to kernel. */
102 /* 0x04 */      UINT16 orig_video_page;         /* LDR */
103 /* 0x06 */      UINT8 orig_video_mode;          /* LDR */
104 /* 0x07 */      UINT8 orig_video_cols;          /* LDR */
105
106 /* 0x08 */      UINT16 unused_1;                /* unused */
107
108 /* %%TBD */
109 /* 0x0A */      UINT16 orig_ega_bx;             /* LDR */
110
111 /* 0x0C */      UINT16 unused_2;                /* unused */
112
113 /* Screen height before passing control to kernel. */
114 /* 0x0E */      UINT8 orig_video_rows;          /* LDR */
115
116 /* %%TBD */
117 /* 0x0F */      UINT8 is_vga;                   /* LDR */
118 /* 0x10 */      UINT16 orig_video_points;       /* LDR */
119
120 /* %%TBD */
121 /* 0x12 */      UINT16 lfb_width;               /* LDR */
122 /* 0x14 */      UINT16 lfb_height;              /* LDR */
123 /* 0x16 */      UINT16 lfb_depth;               /* LDR */
124 /* 0x18 */      UINT32 lfb_base;                /* LDR */
125 /* 0x1C */      UINT32 lfb_size;                /* LDR */
126
127 /* Offset of command line (from start of ia32_boot_param struct). */
128 /* The command line magik number must be set for the kernel setup */
129 /* code to use the command line offset. */
130 /* 0x20 */      UINT16 cmdline_magik;           /* LDR */
131 #define CMDLINE_MAGIK           0xA33F
132 /* 0x22 */      UINT16 cmdline_offset;          /* LDR */
133
134 /* %%TBD */
135 /* 0x24 */      UINT16 lfb_line_len;            /* LDR */
136
137 /* %%TBD */
138 /* 0x26 */      UINT8 lfb_red_size;             /* LDR */
139 /* 0x27 */      UINT8 lfb_red_pos;              /* LDR */
140 /* 0x28 */      UINT8 lfb_green_size;           /* LDR */
141 /* 0x29 */      UINT8 lfb_green_pos;            /* LDR */
142 /* 0x2A */      UINT8 lfb_blue_size;            /* LDR */
143 /* 0x2B */      UINT8 lfb_blue_pos;             /* LDR */
144 /* 0x2C */      UINT8 lfb_rsvd_size;            /* LDR */
145 /* 0x2D */      UINT8 lfb_rsvd_pos;             /* LDR */
146
147 /* %%TBD */
148 /* 0x2E */      UINT16 vesa_seg;                /* LDR */
149 /* 0x30 */      UINT16 vesa_off;                /* LDR */
150
151 /* %%TBD */
152 /* 0x32 */      UINT16 lfb_pages;               /* LDR */
153 /* 0x34 */      UINT8 lfb_reserved[0x0C];       /* reserved */
154
155 /* %%TBD */
156 /* 0x40 */      UINT16 apm_bios_ver;            /* LDR */
157 #define NO_APM_BIOS             0x0000
158
159 /* %%TBD */
160 /* 0x42 */      UINT16 bios_code_seg;           /* LDR */
161 /* 0x44 */      UINT32 bios_entry_point;        /* LDR */
162 /* 0x48 */      UINT16 bios_code_seg16;         /* LDR */
163 /* 0x4A */      UINT16 bios_data_seg;           /* LDR */
164
165 /* %%TBD */
166 /* 0x4C */      UINT16 apm_bios_flags;          /* LDR */
167 #define NO_32BIT_APM_MASK       0xFFFD
168
169 /* %%TBD */
170 /* 0x4E */      UINT32 bios_code_len;           /* LDR */
171 /* 0x52 */      UINT16 bios_data_len;           /* LDR */
172
173 /* 0x54 */      UINT8 unused_3[0x2C];           /* unused */
174
175 /* %%TBD */
176 /* 0x80 */      UINT8 hd0_info[0x10];           /* LDR */
177 /* 0x90 */      UINT8 hd1_info[0x10];           /* LDR */
178
179 /* %%TBD */
180 /* 0xA0 */      UINT16 mca_info_len;            /* LDR */
181 /* 0xA2 */      UINT8 mca_info_buf[0x10];       /* LDR */
182
183 /* 0xB2 */      UINT8 unused_4[0x10E];          /* unused */
184
185 /* EFI boot loader signature. */
186 /* 0x1C0 */     UINT8 efi_loader_sig[4];        /* LDR */
187 #define EFI_LOADER_SIG_X64      "EL64"
188
189 /* Address of the EFI system table. */
190 /* 0x1C4 */     UINT32 efi_sys_tbl;             /* LDR */
191
192 /* EFI memory descriptor size. */
193 /* 0x1C8 */     UINT32 efi_mem_desc_size;       /* LDR */
194
195 /* EFI memory descriptor version. */
196 /* 0x1CC */     UINT32 efi_mem_desc_ver;        /* LDR */
197
198 /* Address & size of EFI memory map. */
199 /* 0x1D0 */     UINT32 efi_mem_map;             /* LDR */
200 /* 0x1D4 */     UINT32 efi_mem_map_size;        /* LDR */
201
202 /* 0x1D8 */     UINT32 efi_sys_tbl_hi;          /* LDR */
203 /* 0x1DC */     UINT32 efi_mem_map_hi;          /* LDR */
204
205 /* Available contiguous extended memory in KB. */
206 /* 0x1E0 */     UINT32 alt_mem_k;               /* LDR */
207
208 /* 0x1E4 */     UINT32 unused_51;               /* unused */
209 /* 0x1E8 */     UINT8 e820_nrmap;
210 /* 0x1E9 */     UINT32 unused_52[2];            /* unused */
211
212 /* Size of setup code in sectors (1 sector == 512 bytes). */
213 /* 0x1F1 */     UINT8 setup_sectors;            /* BLD */
214
215 /* %%TBD */
216 /* 0x1F2 */     UINT16 mount_root_rdonly;       /* BLD */
217
218 /* %%TBD */
219 /* 0x1F4 */     UINT16 sys_size;                /* BLD */
220
221 /* %%TBD */
222 /* 0x1F6 */     UINT16 swap_dev;                /* BLD */
223
224 /* %%TBD */
225 /* 0x1F8 */     UINT16 ramdisk_flags;           /* BLD */
226 #define RAMDISK_PROMPT          0x8000
227 #define RAMDISK_LOAD            0x4000
228
229 /* %%TBD */
230 /* 0x1FA */     UINT16 video_mode_flag;         /* BLD */
231
232 /* %%TBD */
233 /* 0x1FC */     UINT16 orig_root_dev;           /* BLD */
234
235 /* 0x1FE */     UINT8 unused_6;                 /* unused */
236
237 /* %%TBD */
238 /* 0x1FF */     UINT8 aux_dev_info;             /* LDR */
239 #define NO_MOUSE                0x00
240 #define FOUND_MOUSE             0xAA
241
242 /* Jump past setup data (not used in EFI). */
243 /* 0x200 */     UINT16 jump;                    /* BLD */
244
245 /* Setup data signature. */
246 /* 0x202 */     UINT8 setup_sig[4];             /* BLD */
247 #define SETUP_SIG               "HdrS"
248
249 /* %%TBD */
250 /* 0x206 */     UINT8 hdr_minor;                /* BLD */
251 /* 0x207 */     UINT8 hdr_major;                /* BLD */
252
253 /* %%TBD */
254 /* 0x208 */     UINT32 rm_switch;               /* LDD */
255
256 /* %%TBD */
257 /* 0x20C */     UINT16 start_sys_seg;           /* BLD */
258
259 /* %%TBD */
260 /* 0x20E */     UINT16 kernel_verstr_offset;    /* BLD */
261
262 /* Loader type & version. */
263 /* 0x210 */     UINT8 loader_type;              /* LDR */
264 #define LDRTYPE_ELILO                   0x50    /* 5?h == elilo */
265                                                 /* ?0h == revision */
266
267 /* 0x211 */     UINT8 loader_flags;             /* BLD and LDR */
268 #define LDRFLAG_CAN_USE_HEAP            0x80
269 #define LDRFLAG_BOOT_PARAM_RELOC        0x40
270
271 /* %%TBD */
272 /* 0x212 */     UINT16 setup_move_size;         /* BLD */
273
274 /* %%TBD */
275 /* 0x214 */     UINT32 kernel_start;            /* LDR */
276
277 /* %%TBD */
278 /* 0x218 */     UINT32 initrd_start;            /* LDR */
279 /* 0x21C */     UINT32 initrd_size;             /* LDR */
280
281 /* %%TBD */
282 /* 0x220 */     UINT32 bootsect_helper;         /* BLD */
283
284 /* %%TBD */
285 /* 0x224 */     UINT16 heap_end_ptr;            /* LDR */
286
287 /* %%TBD */
288 /* 0x226 */     UINT16 unused_7;                /* LDR */
289
290 /* 0x228 */     UINT32 cmdline_addr;            /* LDR */
291 /* 0x22C */     UINT32 unused_8[41];
292 /* 0x2D0 */     UINT8  e820_map[2560];
293         } s;
294 } boot_params_t;
295 #pragma pack()
296
297 /*
298  * The stuff below here is for jumping to the kernel.
299  */
300
301 /*
302  * Some macros to copy and set memory after EFI has been
303  * stopped.
304  */
305
306 #define MEMCPY(to, from, cnt) { \
307         UINT8 *t = (UINT8 *)(to); \
308         UINT8 *f = (UINT8 *)(from); \
309         UINTN n = cnt; \
310         if (t && f && n) { \
311                 while (n--) { \
312                         *t++ = *f++; \
313                 } \
314         } \
315 }
316
317 #define MEMSET(ptr, size, val) { \
318         UINT8 *p = (UINT8 *)(ptr); \
319         UINTN n = (UINTN)(size); \
320         UINT8 v = (UINT8)(val); \
321         if (p && n) { \
322                 while (n--) { \
323                         *p++ = v; \
324                 } \
325         } \
326 }
327
328 /*
329  * Descriptor table pointer format.
330  */
331 #pragma pack(1)
332 typedef struct {
333         UINT16 limit;
334         UINT64 base;
335 } dt_addr_t;
336 #pragma pack()
337
338 extern UINTN high_base_mem;
339 extern UINTN high_ext_mem;
340
341 extern boot_params_t *param_start;
342 extern UINTN param_size;
343
344 extern VOID *kernel_start;
345 extern UINTN kernel_size;
346
347 extern VOID *initrd_start;
348 extern UINTN initrd_size;
349
350 extern dt_addr_t gdt_addr;
351 extern dt_addr_t idt_addr;
352
353 extern UINT16 init_gdt[];
354 extern UINTN sizeof_init_gdt;
355
356 extern UINT8 rmswitch_image[];
357 extern UINTN rmswitch_size;
358
359 extern INTN x86_64_use_legacy_free_boot();
360
361 /*
362  * How to jump to kernel code
363  */
364
365
366 static inline void
367 start_kernel(VOID *kentry, boot_params_t *bp)
368 {
369         struct {
370                 UINT32  kernel_entry;
371                 UINT16  kernel_cs;
372         } jumpvector;
373         UINTN   njump;
374         VOID    *jump_start;
375
376         /*
377          * Disable interrupts.
378          */
379         asm volatile ( "cli" : : );
380
381         /*
382          * Relocate initrd, if present.
383          */
384
385         if (bp->s.initrd_start) {
386                 MEMCPY(INITRD_START, bp->s.initrd_start, bp->s.initrd_size);
387                 bp->s.initrd_start = INITRD_START;
388         }
389         /*
390          * Copy boot sector, setup data and command line
391          * to final resting place.  We need to copy
392          * BOOT_PARAM_MEMSIZE bytes.
393          */
394
395         MEMCPY(high_base_mem, bp, 0x4000);
396
397         bp = (boot_params_t *)high_base_mem;
398         bp->s.cmdline_addr = high_base_mem + bp->s.cmdline_offset;
399
400         /*
401          * Initialize Linux GDT.
402          */
403
404         MEMSET(gdt_addr.base, gdt_addr.limit, 0);
405         MEMCPY(gdt_addr.base, init_gdt, sizeof_init_gdt);
406
407 // fixme: why x86_64_use_legacy_free_boot() goes to _relocate?
408 #if 0
409         if (! x86_64_use_legacy_free_boot()) {
410
411                 /*
412                  * Copy our real mode transition code to 0x7C00.
413                  */
414
415                 MEMCPY(0x7C00, rmswitch_image, rmswitch_size);
416
417                 asm volatile ( "mov $0x7C00, %%rbx" : : );
418                 asm volatile ( "jmp *%%rbx" : : );
419         }
420 #endif
421
422         /*
423          * Load descriptor table pointers.
424          */
425
426         asm volatile ( "lidt %0" : : "m" (idt_addr) );
427         asm volatile ( "lgdt %0" : : "m" (gdt_addr) );
428
429         /*
430          * rsi := address of boot sector and setup data
431          */
432
433         asm volatile ( "mov %0, %%rsi" : : "m" (high_base_mem) );
434
435         /*
436          * Jump to kernel entry point.
437          */
438         jumpvector.kernel_entry=kentry;
439         jumpvector.kernel_cs=0x10;
440         njump = &jumpvector;
441         jump_start = (VOID *)&jumpvector;
442         //asm volatile ( "mov %0, %%rcx" : : "m" (&jumpvector) );
443         asm volatile ( "mov %0, %%rcx" : : "m" (jump_start) );
444         //asm volatile ( "mov %0, %%rcx" : : "m" (njump) );
445         asm volatile ( "ljmp *(%%rcx)" : :);
446         /* Never come back to here. */
447 }
448
449 typedef struct sys_img_options {
450         UINT8 nothing_yet;
451 } sys_img_options_t;
452
453 #endif /* __ELILO_SYSDEPS_X86_64_H__ */