2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2013 Free Software Foundation, Inc.
5 * GRUB is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * GRUB is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
19 #include <grub/charset.h>
20 #include <grub/command.h>
22 #include <grub/file.h>
24 #include <grub/linux.h>
25 #include <grub/loader.h>
27 #include <grub/types.h>
28 #include <grub/cpu/linux.h>
29 #include <grub/efi/efi.h>
30 #include <grub/efi/pe32.h>
31 #include <grub/i18n.h>
32 #include <grub/lib/cmdline.h>
34 GRUB_MOD_LICENSE ("GPLv3+");
36 #define GRUB_EFI_PAGE_SHIFT 12
37 #define BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> GRUB_EFI_PAGE_SHIFT)
38 #define GRUB_EFI_PE_MAGIC 0x5A4D
40 static grub_efi_guid_t fdt_guid
= GRUB_EFI_DEVICE_TREE_GUID
;
42 static grub_dl_t my_mod
;
45 static void *kernel_addr
;
46 static grub_uint64_t kernel_size
;
48 static char *linux_args
;
49 static grub_uint32_t cmdline_size
;
51 static grub_addr_t initrd_start
;
52 static grub_addr_t initrd_end
;
54 static void *loaded_fdt
;
58 get_firmware_fdt (void)
60 grub_efi_configuration_table_t
*tables
;
61 void *firmware_fdt
= NULL
;
64 /* Look for FDT in UEFI config tables. */
65 tables
= grub_efi_system_table
->configuration_table
;
67 for (i
= 0; i
< grub_efi_system_table
->num_table_entries
; i
++)
68 if (grub_memcmp (&tables
[i
].vendor_guid
, &fdt_guid
, sizeof (fdt_guid
)) == 0)
70 firmware_fdt
= tables
[i
].vendor_table
;
71 grub_dprintf ("linux", "found registered FDT @ %p\n", firmware_fdt
);
86 size
= BYTES_TO_PAGES (grub_fdt_get_totalsize (fdt
));
87 grub_efi_free_pages ((grub_efi_physical_address_t
) fdt
, size
);
93 raw_fdt
= get_firmware_fdt();
96 raw_fdt
? grub_fdt_get_totalsize (raw_fdt
) : GRUB_FDT_EMPTY_TREE_SZ
;
99 grub_dprintf ("linux", "allocating %ld bytes for fdt\n", size
);
100 fdt
= grub_efi_allocate_pages (0, BYTES_TO_PAGES (size
));
106 grub_memmove (fdt
, raw_fdt
, size
);
107 grub_fdt_set_totalsize (fdt
, size
);
111 grub_fdt_create_empty_tree (fdt
, size
);
116 check_kernel (struct grub_arm64_linux_kernel_header
*lh
)
118 if (lh
->magic
!= GRUB_ARM64_LINUX_MAGIC
)
119 return grub_error(GRUB_ERR_BAD_OS
, "invalid magic number");
121 if ((lh
->code0
& 0xffff) != GRUB_EFI_PE_MAGIC
)
122 return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET
,
123 N_("plain image kernel not supported - rebuild with CONFIG_(U)EFI_STUB enabled"));
125 grub_dprintf ("linux", "UEFI stub kernel:\n");
126 grub_dprintf ("linux", "text_offset = 0x%012llx\n",
127 (long long unsigned) lh
->text_offset
);
128 grub_dprintf ("linux", "PE/COFF header @ %08x\n", lh
->hdr_offset
);
130 return GRUB_ERR_NONE
;
134 finalize_params (void)
136 grub_efi_boot_services_t
*b
;
137 grub_efi_status_t status
;
144 node
= grub_fdt_find_subnode (fdt
, 0, "chosen");
146 node
= grub_fdt_add_subnode (fdt
, 0, "chosen");
151 /* Set initrd info */
152 if (initrd_start
&& initrd_end
> initrd_start
)
154 grub_dprintf ("linux", "Initrd @ 0x%012lx-0x%012lx\n",
155 initrd_start
, initrd_end
);
157 retval
= grub_fdt_set_prop64 (fdt
, node
, "linux,initrd-start",
161 retval
= grub_fdt_set_prop64 (fdt
, node
, "linux,initrd-end",
167 b
= grub_efi_system_table
->boot_services
;
168 status
= b
->install_configuration_table (&fdt_guid
, fdt
);
169 if (status
!= GRUB_EFI_SUCCESS
)
172 grub_dprintf ("linux", "Installed/updated FDT configuration table @ %p\n",
175 return GRUB_ERR_NONE
;
178 grub_efi_free_pages ((grub_efi_physical_address_t
) fdt
,
179 BYTES_TO_PAGES (grub_fdt_get_totalsize (fdt
)));
181 return grub_error(GRUB_ERR_BAD_OS
, "failed to install/update FDT");
185 grub_cmd_devicetree (grub_command_t cmd
__attribute__ ((unused
)),
186 int argc
, char *argv
[])
194 grub_error (GRUB_ERR_BAD_ARGUMENT
,
195 N_("you need to load the kernel first"));
196 return GRUB_ERR_BAD_OS
;
200 return grub_error (GRUB_ERR_BAD_ARGUMENT
, N_("filename expected"));
203 grub_free (loaded_fdt
);
206 dtb
= grub_file_open (argv
[0]);
210 size
= grub_file_size (dtb
);
211 blob
= grub_malloc (size
);
215 if (grub_file_read (dtb
, blob
, size
) < size
)
218 grub_error (GRUB_ERR_BAD_OS
, N_("premature end of file %s"), argv
[0]);
222 if (grub_fdt_check_header (blob
, size
) != 0)
224 grub_error (GRUB_ERR_BAD_OS
, N_("invalid device tree"));
230 grub_file_close (dtb
);
234 if (grub_errno
== GRUB_ERR_NONE
)
244 grub_linux_boot (void)
246 grub_efi_memory_mapped_device_path_t
*mempath
;
247 grub_efi_handle_t image_handle
;
248 grub_efi_boot_services_t
*b
;
249 grub_efi_status_t status
;
251 grub_efi_loaded_image_t
*loaded_image
;
254 retval
= finalize_params();
255 if (retval
!= GRUB_ERR_NONE
)
258 mempath
= grub_malloc (2 * sizeof (grub_efi_memory_mapped_device_path_t
));
262 mempath
[0].header
.type
= GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE
;
263 mempath
[0].header
.subtype
= GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE
;
264 mempath
[0].header
.length
= grub_cpu_to_le16_compile_time (sizeof (*mempath
));
265 mempath
[0].memory_type
= GRUB_EFI_LOADER_DATA
;
266 mempath
[0].start_address
= (grub_addr_t
) kernel_addr
;
267 mempath
[0].end_address
= (grub_addr_t
) kernel_addr
+ kernel_size
;
269 mempath
[1].header
.type
= GRUB_EFI_END_DEVICE_PATH_TYPE
;
270 mempath
[1].header
.subtype
= GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE
;
271 mempath
[1].header
.length
= sizeof (grub_efi_device_path_t
);
273 b
= grub_efi_system_table
->boot_services
;
274 status
= b
->load_image (0, grub_efi_image_handle
,
275 (grub_efi_device_path_t
*) mempath
,
276 kernel_addr
, kernel_size
, &image_handle
);
277 if (status
!= GRUB_EFI_SUCCESS
)
278 return grub_error (GRUB_ERR_BAD_OS
, "cannot load image");
280 grub_dprintf ("linux", "linux command line: '%s'\n", linux_args
);
282 /* Convert command line to UCS-2 */
283 loaded_image
= grub_efi_get_loaded_image (image_handle
);
284 loaded_image
->load_options_size
= len
=
285 (grub_strlen (linux_args
) + 1) * sizeof (grub_efi_char16_t
);
286 loaded_image
->load_options
=
287 grub_efi_allocate_pages (0,
288 BYTES_TO_PAGES (loaded_image
->load_options_size
));
289 if (!loaded_image
->load_options
)
292 loaded_image
->load_options_size
=
293 2 * grub_utf8_to_utf16 (loaded_image
->load_options
, len
,
294 (grub_uint8_t
*) linux_args
, len
, NULL
);
296 grub_dprintf("linux", "starting image %p\n", image_handle
);
297 status
= b
->start_image (image_handle
, 0, NULL
);
299 /* When successful, not reached */
300 b
->unload_image (image_handle
);
301 grub_efi_free_pages ((grub_efi_physical_address_t
) loaded_image
->load_options
,
302 BYTES_TO_PAGES (loaded_image
->load_options_size
));
308 grub_linux_unload (void)
310 grub_dl_unref (my_mod
);
313 grub_efi_free_pages ((grub_efi_physical_address_t
) initrd_start
,
314 BYTES_TO_PAGES (initrd_end
- initrd_start
));
315 initrd_start
= initrd_end
= 0;
316 grub_free (linux_args
);
318 grub_efi_free_pages ((grub_efi_physical_address_t
) kernel_addr
,
319 BYTES_TO_PAGES (kernel_size
));
321 grub_efi_free_pages ((grub_efi_physical_address_t
) fdt
,
322 BYTES_TO_PAGES (grub_fdt_get_totalsize (fdt
)));
324 return GRUB_ERR_NONE
;
328 grub_cmd_initrd (grub_command_t cmd
__attribute__ ((unused
)),
329 int argc
, char *argv
[])
331 struct grub_linux_initrd_context initrd_ctx
= { 0, 0, 0 };
332 int initrd_size
, initrd_pages
;
333 void *initrd_mem
= NULL
;
337 grub_error (GRUB_ERR_BAD_ARGUMENT
, N_("filename expected"));
343 grub_error (GRUB_ERR_BAD_ARGUMENT
,
344 N_("you need to load the kernel first"));
348 if (grub_initrd_init (argc
, argv
, &initrd_ctx
))
351 initrd_size
= grub_get_initrd_size (&initrd_ctx
);
352 grub_dprintf ("linux", "Loading initrd\n");
354 initrd_pages
= (BYTES_TO_PAGES (initrd_size
));
355 initrd_mem
= grub_efi_allocate_pages (0, initrd_pages
);
358 grub_error (GRUB_ERR_OUT_OF_MEMORY
, N_("out of memory"));
362 if (grub_initrd_load (&initrd_ctx
, argv
, initrd_mem
))
365 initrd_start
= (grub_addr_t
) initrd_mem
;
366 initrd_end
= initrd_start
+ initrd_size
;
367 grub_dprintf ("linux", "[addr=%p, size=0x%x]\n",
368 (void *) initrd_start
, initrd_size
);
371 grub_initrd_close (&initrd_ctx
);
372 if (initrd_mem
&& !initrd_start
)
373 grub_efi_free_pages ((grub_efi_physical_address_t
) initrd_mem
,
380 grub_cmd_linux (grub_command_t cmd
__attribute__ ((unused
)),
381 int argc
, char *argv
[])
383 grub_file_t file
= 0;
384 struct grub_arm64_linux_kernel_header lh
;
386 grub_dl_ref (my_mod
);
390 grub_error (GRUB_ERR_BAD_ARGUMENT
, N_("filename expected"));
394 file
= grub_file_open (argv
[0]);
398 kernel_size
= grub_file_size (file
);
400 if (grub_file_read (file
, &lh
, sizeof (lh
)) < (long) sizeof (lh
))
403 if (check_kernel (&lh
) != GRUB_ERR_NONE
)
408 grub_dprintf ("linux", "kernel file size: %lld\n", (long long) kernel_size
);
409 kernel_addr
= grub_efi_allocate_pages (0, BYTES_TO_PAGES (kernel_size
));
410 grub_dprintf ("linux", "kernel numpages: %lld\n",
411 (long long) BYTES_TO_PAGES (kernel_size
));
414 grub_error (GRUB_ERR_OUT_OF_MEMORY
, N_("out of memory"));
418 grub_file_seek (file
, 0);
419 if (grub_file_read (file
, kernel_addr
, kernel_size
)
420 < (grub_int64_t
) kernel_size
)
423 grub_error (GRUB_ERR_BAD_OS
, N_("premature end of file %s"), argv
[0]);
427 grub_dprintf ("linux", "kernel @ %p\n", kernel_addr
);
429 cmdline_size
= grub_loader_cmdline_size (argc
, argv
) + sizeof (LINUX_IMAGE
);
430 linux_args
= grub_malloc (cmdline_size
);
433 grub_error (GRUB_ERR_OUT_OF_MEMORY
, N_("out of memory"));
436 grub_memcpy (linux_args
, LINUX_IMAGE
, sizeof (LINUX_IMAGE
));
437 grub_create_loader_cmdline (argc
, argv
,
438 linux_args
+ sizeof (LINUX_IMAGE
) - 1,
441 if (grub_errno
== GRUB_ERR_NONE
)
443 grub_loader_set (grub_linux_boot
, grub_linux_unload
, 0);
449 grub_file_close (file
);
451 if (grub_errno
!= GRUB_ERR_NONE
)
453 grub_dl_unref (my_mod
);
457 if (linux_args
&& !loaded
)
458 grub_free (linux_args
);
460 if (kernel_addr
&& !loaded
)
461 grub_efi_free_pages ((grub_efi_physical_address_t
) kernel_addr
,
462 BYTES_TO_PAGES (kernel_size
));
468 static grub_command_t cmd_linux
, cmd_initrd
, cmd_devicetree
;
470 GRUB_MOD_INIT (linux
)
472 cmd_linux
= grub_register_command ("linux", grub_cmd_linux
, 0,
474 cmd_initrd
= grub_register_command ("initrd", grub_cmd_initrd
, 0,
477 grub_register_command ("devicetree", grub_cmd_devicetree
, 0,
478 N_("Load DTB file."));
482 GRUB_MOD_FINI (linux
)
484 grub_unregister_command (cmd_linux
);
485 grub_unregister_command (cmd_initrd
);
486 grub_unregister_command (cmd_devicetree
);