2 * Copyright (C) 2009 Juergen Beisert, Pengutronix
4 * In parts from the GRUB2 project:
6 * GRUB -- GRand Unified Bootloader
7 * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2007,2008 Free Software Foundation, Inc.
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of
12 * the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
28 #include <environment.h>
32 #include <asm/syslib.h>
35 #define LINUX_MAGIC_SIGNATURE 0x53726448 /* "HdrS" */
38 #define LINUX_FLAG_BIG_KERNEL 0x1
41 #define LINUX_BOOT_LOADER_TYPE 0x72
44 #define LINUX_DEFAULT_SETUP_SECTS 4
47 #define LINUX_MAX_SETUP_SECTS 64
50 #define LINUX_OLD_REAL_MODE_SEGMT 0x9000
53 #define LINUX_OLD_REAL_MODE_ADDR (LINUX_OLD_REAL_MODE_SEGMT << 4)
56 #define LINUX_HEAP_END_OFFSET (LINUX_OLD_REAL_MODE_SEGMT - 0x200)
59 #define LINUX_FLAG_CAN_USE_HEAP 0x80
61 /** Define kernel command lines's start offset in the setup segment */
62 #define LINUX_CL_OFFSET 0x9000
64 /** Define kernel command lines's end offset */
65 #define LINUX_CL_END_OFFSET 0x90FF
68 #define LINUX_CL_MAGIC 0xA33F
71 #define LINUX_SETUP_MOVE_SIZE 0x9100
74 #define DISK_SECTOR_BITS 9
75 #define DISK_SECTOR_SIZE 0x200
77 /** Where to load a bzImage */
78 #define LINUX_BZIMAGE_ADDR 0x100000
80 struct linux_kernel_header
{
81 /* first sector of the image */
82 uint8_t code1
[0x0020];
83 uint16_t cl_magic
; /**< Magic number 0xA33F */
84 uint16_t cl_offset
; /**< The offset of command line */
85 uint8_t code2
[0x01F1 - 0x0020 - 2 - 2];
86 uint8_t setup_sects
; /**< The size of the setup in sectors */
87 uint16_t root_flags
; /**< If the root is mounted readonly */
88 uint16_t syssize
; /**< obsolete */
89 uint16_t swap_dev
; /**< obsolete */
90 uint16_t ram_size
; /**< obsolete */
91 uint16_t vid_mode
; /**< Video mode control */
92 uint16_t root_dev
; /**< Default root device number */
93 uint16_t boot_flag
; /**< 0xAA55 magic number */
95 /* second sector of the image */
96 uint16_t jump
; /**< Jump instruction (this is code!) */
97 uint32_t header
; /**< Magic signature "HdrS" */
98 uint16_t version
; /**< Boot protocol version supported */
99 uint32_t realmode_swtch
; /**< Boot loader hook */
100 uint16_t start_sys
; /**< The load-low segment (obsolete) */
101 uint16_t kernel_version
; /**< Points to kernel version string */
102 uint8_t type_of_loader
; /**< Boot loader identifier */
103 #define LINUX_LOADER_ID_LILO 0x0
104 #define LINUX_LOADER_ID_LOADLIN 0x1
105 #define LINUX_LOADER_ID_BOOTSECT 0x2
106 #define LINUX_LOADER_ID_SYSLINUX 0x3
107 #define LINUX_LOADER_ID_ETHERBOOT 0x4
108 #define LINUX_LOADER_ID_ELILO 0x5
109 #define LINUX_LOADER_ID_GRUB 0x7
110 #define LINUX_LOADER_ID_UBOOT 0x8
111 #define LINUX_LOADER_ID_XEN 0x9
112 #define LINUX_LOADER_ID_GUJIN 0xa
113 #define LINUX_LOADER_ID_QEMU 0xb
114 uint8_t loadflags
; /**< Boot protocol option flags */
115 uint16_t setup_move_size
; /**< Move to high memory size */
116 uint32_t code32_start
; /**< Boot loader hook */
117 uint32_t ramdisk_image
; /**< initrd load address */
118 uint32_t ramdisk_size
; /**< initrd size */
119 uint32_t bootsect_kludge
; /**< obsolete */
120 uint16_t heap_end_ptr
; /**< Free memory after setup end */
121 uint8_t ext_loader_ver
; /**< boot loader's extension of the version number */
122 uint8_t ext_loader_type
; /**< boot loader's extension of its type */
123 char *cmd_line_ptr
; /**< Points to the kernel command line */
124 uint32_t initrd_addr_max
; /**< Highest address for initrd */
126 /* for the records only. These members are defined in
127 * more recent Linux kernels
129 uint32_t kernel_alignment
; /**< Alignment unit required by the kernel */
130 uint8_t relocatable_kernel
; /** */
131 uint8_t min_alignment
; /** */
132 uint32_t cmdline_size
; /** */
133 uint32_t hardware_subarch
; /** */
134 uint64_t hardware_subarch_data
; /** */
135 uint32_t payload_offset
; /** */
136 uint32_t payload_length
; /** */
137 uint64_t setup_data
; /** */
138 uint64_t pref_address
; /** */
139 uint32_t init_size
; /** */
141 } __attribute__ ((packed
));
144 * Load an x86 Linux kernel bzImage and start it
146 * @param argc parameter count
147 * @param argv list of parameter
149 * Loads an x86 bzImage, checks for its integrity, stores the two parts
150 * (setup = 'real mode code' and kernel = 'protected mode code') to their
151 * default locations, switches back to real mode and runs the setup code.
153 static int do_linux16(cmd_tbl_t
*cmdtp
, int argc
, char *argv
[])
155 struct linux_kernel_header
*lh
= NULL
;
157 unsigned setup_sects
;
158 unsigned real_mode_size
;
160 const char *cmdline
= getenv("bootargs");
167 lh
= read_file(argv
[1], &image_size
);
169 printf("Cannot read file '%s'\n", argv
[1]);
173 if (lh
->boot_flag
!= 0xaa55) {
174 printf("File '%s' has invalid magic number\n", argv
[1]);
179 if (lh
->setup_sects
> LINUX_MAX_SETUP_SECTS
) {
180 printf("File '%s' contains too many setup sectors\n", argv
[1]);
185 setup_sects
= lh
->setup_sects
;
187 printf("Found a %d.%d image header\n", lh
->version
>> 8, lh
->version
& 0xFF);
189 if (lh
->header
== LINUX_MAGIC_SIGNATURE
&& lh
->version
>= 0x0200) {
190 /* kernel is recent enough */
192 if (!(lh
->loadflags
& LINUX_FLAG_BIG_KERNEL
)) {
193 printf("Cannot load a classic zImage. Use a bzImage instead\n");
196 lh
->type_of_loader
= LINUX_BOOT_LOADER_TYPE
; /* TODO */
198 if (lh
->version
>= 0x0201) {
199 lh
->heap_end_ptr
= LINUX_HEAP_END_OFFSET
;
200 lh
->loadflags
|= LINUX_FLAG_CAN_USE_HEAP
;
203 if (lh
->version
>= 0x0202)
204 lh
->cmd_line_ptr
= (void*)(LINUX_OLD_REAL_MODE_ADDR
+ LINUX_CL_OFFSET
); /* FIXME */
206 lh
->cl_magic
= LINUX_CL_MAGIC
;
207 lh
->cl_offset
= LINUX_CL_OFFSET
;
208 lh
->setup_move_size
= LINUX_SETUP_MOVE_SIZE
;
211 printf("Kernel too old to handle\n");
216 if (strlen(cmdline
) >= (LINUX_CL_END_OFFSET
- LINUX_CL_OFFSET
)) {
217 printf("Kernel command line exceeds the available space\n");
222 /* If SETUP_SECTS is not set, set it to the default. */
223 if (setup_sects
== 0) {
224 printf("Fixing setup sector count\n");
225 setup_sects
= LINUX_DEFAULT_SETUP_SECTS
;
228 if (setup_sects
>= 15) {
230 if (lh
->kernel_version
!= 0)
231 printf("Kernel version: '%s'\n", src
+ lh
->kernel_version
+ DISK_SECTOR_SIZE
);
235 * Size of the real mode part to handle in a separate way
237 real_mode_size
= (setup_sects
<< DISK_SECTOR_BITS
) + DISK_SECTOR_SIZE
;
240 * real mode space hole extended memory
241 * |---------------------------------------------->|----------->|------------------------------>
243 * <-1-|----------2-----------><-3- |
245 * <-4--|-5--> |---------6------------->
250 * 4) realmode stack when starting a Linux kernel
251 * 5) Kernel's real mode setup code
252 * 6) compressed kernel image
255 * Parts of the image we know:
260 * NOTE: This part is dangerous, as it copies some image content to
261 * various locations in the main memory. This could overwrite important
262 * data of the running barebox (hopefully not)
264 /* copy the real mode part of the image to the 9th segment */
265 memcpy((void*)LINUX_OLD_REAL_MODE_ADDR
, lh
, LINUX_SETUP_MOVE_SIZE
);
267 /* TODO add 'BOOT_IMAGE=<file>' and 'auto' if no user intervention was done (in front of all other params) */
268 /* copy also the command line into this area */
269 memcpy((void*)(LINUX_OLD_REAL_MODE_ADDR
+ LINUX_CL_OFFSET
), cmdline
, strlen(cmdline
) + 1);
270 printf("Using kernel command line: '%s'\n", cmdline
);
272 /* copy the compressed image part to its final address the setup code expects it
273 * Note: The protected mode part starts at offset (setup_sects + 1) * 512
275 memcpy((void*)LINUX_BZIMAGE_ADDR
, ((void*)lh
) + real_mode_size
, image_size
- real_mode_size
);
278 * switch back to real mode now and start the real mode part of the
279 * image at address "(LINUX_OLD_REAL_MODE_ADDR >> 4) + 0x20:0x0000"
280 * which means "0x9020:0x000" -> 0x90200
282 bios_start_linux(LINUX_OLD_REAL_MODE_SEGMT
); /* does not return */
291 static const __maybe_unused
char cmd_linux16_help
[] =
292 "Usage: linux16 <file>\n"
293 "Boot a linux kernel via real mode code\n";
296 BAREBOX_CMD_START(linux16
)
298 .usage
= "boot linux kernel",
299 BAREBOX_CMD_HELP(cmd_linux16_help
)
304 * @brief Boot support for Linux on x86
308 * @page linux16_command linux16: Boot a bzImage kernel on x86
310 * Usage is: linux16 \<file\>
312 * Boot a linux kernel via real mode code. Only kernel images in the
313 * @p bzImage format are supported.
317 * @page x86_boot_preparation Linux Preparation on x86
319 * Due to some real mode constraints, starting Linux is somehow tricky.
320 * Currently only @p bzImages are supported, because @p zImages would
321 * interfere with the @a barebox runtime.
322 * Also older load header versions than 2.00 aren't supported.
324 * The memory layout immediately before starting the Linux kernel:
327 real mode space hole extended memory
328 |---------------------------------------------->|----------->|------------------------------>
329 0 0x7e00 0x90000 0xa0000 0x100000
330 <-1-|----------2-----------><-3- |
331 <-4--|-5--> |---------6------------->
334 * @li 1 = @a barebox's real mode stack
335 * @li 2 = @a barebox's code
336 * @li 3 = @a barebox's flat mode stack
337 * @li 4 = real mode stack, when starting the Linux kernel
338 * @li 5 = Kernel's real mode setup code
339 * @li 6 = compressed kernel image
341 * A more detailed memory layout for kernel's real mode setup code
345 0x90000 0x97fff 0x99000 0x990ff
346 ---|------------------------------------------|----------------|--------------------|
347 |<-------- max setup code size ----------->|<--heap/stack-->|<-- command line -->|
351 * The regular entry point into the setup code is 0x90200 (2nd sector)
353 * To start the kernel, it's own setup code will be called. To do so, it
354 * must be called in real mode. So, @a barebox switches back to real mode
355 * a last time and does a jump to the setup code entry point. Now its up to
356 * the setup code to deflate the kernel, switching to its own protected mode
357 * setup and starting the kernel itself.
359 * @note This scenario only works, if a BIOS is still present. In this case
360 * there is no need for @a barebox to forward any system related information
361 * to the kernel. Everything is detected by kernel's setup code.