efi = disk/efi/efidisk.c;
efi = kern/efi/efi.c;
+ efi = kern/efi/efi_core.c;
efi = kern/efi/init.c;
efi = kern/efi/mm.c;
efi = term/efi/console.c;
image = {
name = xz_decompress;
+ ia64_efi = kern/ia64/efi/startup.S;
+ i386_efi = kern/i386/efi/startup.S;
+ x86_64_efi = kern/x86_64/efi/startup.S;
+ arm_efi = kern/arm/efi/startup.S;
+
mips = boot/mips/startup_raw.S;
+ mips = boot/mips/scratch.c;
common = boot/decompressor/minilib.c;
common = boot/decompressor/xz.c;
common = lib/xzembed/xz_dec_bcj.c;
common = lib/xzembed/xz_dec_lzma2.c;
common = lib/xzembed/xz_dec_stream.c;
+ efi = boot/efi/decompressor.c;
+ efi = kern/efi/efi_core.c;
+
+ x86_64_efi = kern/x86_64/efi/callwrap.S;
cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/xzembed -DGRUB_EMBED_DECOMPRESSOR=1';
ldadd = '$(TARGET_LIBGCC)';
cflags = '-Wno-unreachable-code $(TARGET_LDFLAGS_STATIC_LIBGCC)';
enable = mips;
+ enable = efi;
};
image = {
void *grub_decompressor_scratch;
-void
-find_scratch (void *src, void *dst, unsigned long srcsize,
- unsigned long dstsize)
-{
-#ifdef _mips
- /* Decoding from ROM. */
- if (((grub_addr_t) src & 0x10000000))
- {
- grub_decompressor_scratch = (void *) ALIGN_UP((grub_addr_t) dst + dstsize,
- 256);
- return;
- }
-#endif
- if ((char *) src + srcsize > (char *) dst + dstsize)
- grub_decompressor_scratch = (void *) ALIGN_UP ((grub_addr_t) src + srcsize,
- 256);
- else
- grub_decompressor_scratch = (void *) ALIGN_UP ((grub_addr_t) dst + dstsize,
- 256);
- return;
-}
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2010,2013 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/types.h>
+#include <grub/misc.h>
+#include <grub/decompressor.h>
+
+void
+find_scratch (void *src, void *dst, unsigned long srcsize,
+ unsigned long dstsize)
+{
+ if ((char *) src + srcsize > (char *) dst + dstsize)
+ grub_decompressor_scratch = (void *) ALIGN_UP ((grub_addr_t) src + srcsize,
+ 256);
+ else
+ grub_decompressor_scratch = (void *) ALIGN_UP ((grub_addr_t) dst + dstsize,
+ 256);
+ return;
+}
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2013 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/kernel.h>
+#include <grub/efi/efi.h>
+#include <grub/decompressor.h>
+
+/* The handle of GRUB itself. Filled in by the startup code. */
+grub_efi_handle_t grub_efi_image_handle;
+
+/* The pointer to a system table. Filled in by the startup code. */
+grub_efi_system_table_t *grub_efi_system_table;
+
+int
+grub_strcmp (const char *s1, const char *s2)
+{
+ while (*s1 && *s2)
+ {
+ if (*s1 != *s2)
+ break;
+
+ s1++;
+ s2++;
+ }
+
+ return (int) (grub_uint8_t) *s1 - (int) (grub_uint8_t) *s2;
+}
+
+static grub_size_t unc_pages, scratch_pages;
+static void *unc;
+
+void
+grub_efi_fini (void)
+{
+ if (unc)
+ grub_efi_free_pages ((grub_addr_t) unc, unc_pages);
+ if (grub_decompressor_scratch)
+ grub_efi_free_pages ((grub_addr_t) grub_decompressor_scratch,
+ scratch_pages);
+}
+
+void
+find_scratch (void *src __attribute__ ((unused)),
+ void *dst __attribute__ ((unused)),
+ unsigned long srcsize __attribute__ ((unused)),
+ unsigned long dstsize __attribute__ ((unused)))
+{
+}
+
+void __attribute__ ((noreturn))
+grub_main (void)
+{
+ grub_addr_t start;
+ grub_size_t sz;
+ grub_addr_t unc_size;
+ grub_efi_boot_services_t *b;
+ grub_efi_status_t status;
+ grub_efi_uintn_t exit_data_size;
+ grub_efi_char16_t *exit_data = 0;
+ grub_efi_handle_t image_handle;
+ grub_efi_loaded_image_t *image;
+
+ b = grub_efi_system_table->boot_services;
+
+ if (!grub_efi_get_section ("payload", &start, &sz)
+ || sz < 12)
+ grub_exit ();
+ if (grub_memcmp ((void *) start, "COMPRESS", 8) != 0)
+ grub_exit ();
+ unc_size = grub_get_unaligned32 ((char *) start + 8);
+
+ unc_pages = (unc_size + 0xfff) >> 12;
+
+ unc = grub_efi_allocate_pages (0, unc_pages);
+ if (!unc)
+ grub_exit ();
+
+ scratch_pages = 0x200000 >> 12;
+ grub_decompressor_scratch = grub_efi_allocate_pages (0, scratch_pages);
+ if (!grub_decompressor_scratch)
+ grub_exit ();
+
+ grub_decompress_core ((char *) start + 12, unc, sz - 12,
+ unc_size);
+
+ image = grub_efi_get_loaded_image (grub_efi_image_handle);
+
+ status = efi_call_6 (b->load_image, 0, grub_efi_image_handle,
+ image->file_path, unc, unc_size, &image_handle);
+ if (status != GRUB_EFI_SUCCESS)
+ efi_call_4 (grub_efi_system_table->boot_services->exit,
+ grub_efi_image_handle, status, 0, 0);
+
+ status = efi_call_3 (b->start_image, image_handle, &exit_data_size, &exit_data);
+
+ efi_call_4 (grub_efi_system_table->boot_services->exit,
+ grub_efi_image_handle, status, exit_data_size, exit_data);
+
+ grub_exit ();
+}
+
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2010,2013 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/types.h>
+#include <grub/misc.h>
+#include <grub/decompressor.h>
+
+void
+find_scratch (void *src, void *dst, unsigned long srcsize,
+ unsigned long dstsize)
+{
+ /* Decoding from ROM. */
+ if (((grub_addr_t) src & 0x10000000))
+ {
+ grub_decompressor_scratch = (void *) ALIGN_UP((grub_addr_t) dst + dstsize,
+ 256);
+ return;
+ }
+
+ if ((char *) src + srcsize > (char *) dst + dstsize)
+ grub_decompressor_scratch = (void *) ALIGN_UP ((grub_addr_t) src + srcsize,
+ 256);
+ else
+ grub_decompressor_scratch = (void *) ALIGN_UP ((grub_addr_t) dst + dstsize,
+ 256);
+ return;
+}
grub_efi_system_table_t *grub_efi_system_table;
static grub_efi_guid_t console_control_guid = GRUB_EFI_CONSOLE_CONTROL_GUID;
-static grub_efi_guid_t loaded_image_guid = GRUB_EFI_LOADED_IMAGE_GUID;
static grub_efi_guid_t device_path_guid = GRUB_EFI_DEVICE_PATH_GUID;
void *
return buffer;
}
-void *
-grub_efi_open_protocol (grub_efi_handle_t handle,
- grub_efi_guid_t *protocol,
- grub_efi_uint32_t attributes)
-{
- grub_efi_boot_services_t *b;
- grub_efi_status_t status;
- void *interface;
-
- b = grub_efi_system_table->boot_services;
- status = efi_call_6 (b->open_protocol, handle,
- protocol,
- &interface,
- grub_efi_image_handle,
- 0,
- attributes);
- if (status != GRUB_EFI_SUCCESS)
- return 0;
-
- return interface;
-}
-
int
grub_efi_set_text_mode (int on)
{
efi_call_1 (grub_efi_system_table->boot_services->stall, microseconds);
}
-grub_efi_loaded_image_t *
-grub_efi_get_loaded_image (grub_efi_handle_t image_handle)
-{
- return grub_efi_open_protocol (image_handle,
- &loaded_image_guid,
- GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
-}
-
-void
-grub_exit (void)
-{
- grub_efi_fini ();
- efi_call_4 (grub_efi_system_table->boot_services->exit,
- grub_efi_image_handle, GRUB_EFI_SUCCESS, 0, 0);
- for (;;) ;
-}
-
grub_err_t
grub_efi_set_virtual_address_map (grub_efi_uintn_t memory_map_size,
grub_efi_uintn_t descriptor_size,
return NULL;
}
-#pragma GCC diagnostic ignored "-Wcast-align"
-
-/* Search the mods section from the PE32/PE32+ image. This code uses
- a PE32 header, but should work with PE32+ as well. */
-grub_addr_t
-grub_efi_modules_addr (void)
-{
- grub_efi_loaded_image_t *image;
- struct grub_pe32_header *header;
- struct grub_pe32_coff_header *coff_header;
- struct grub_pe32_section_table *sections;
- struct grub_pe32_section_table *section;
- struct grub_module_info *info;
- grub_uint16_t i;
-
- image = grub_efi_get_loaded_image (grub_efi_image_handle);
- if (! image)
- return 0;
-
- header = image->image_base;
- coff_header = &(header->coff_header);
- sections
- = (struct grub_pe32_section_table *) ((char *) coff_header
- + sizeof (*coff_header)
- + coff_header->optional_header_size);
-
- for (i = 0, section = sections;
- i < coff_header->num_sections;
- i++, section++)
- {
- if (grub_strcmp (section->name, "mods") == 0)
- break;
- }
-
- if (i == coff_header->num_sections)
- return 0;
-
- info = (struct grub_module_info *) ((char *) image->image_base
- + section->virtual_address);
- if (info->magic != GRUB_MODULE_MAGIC)
- return 0;
-
- return (grub_addr_t) info;
-}
-
-#pragma GCC diagnostic error "-Wcast-align"
-
char *
grub_efi_get_filename (grub_efi_device_path_t *dp0)
{
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2006,2007,2008,2009,2010,2013 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/efi/efi.h>
+#include <grub/efi/pe32.h>
+
+static grub_efi_guid_t loaded_image_guid = GRUB_EFI_LOADED_IMAGE_GUID;
+
+void *
+grub_efi_open_protocol (grub_efi_handle_t handle,
+ grub_efi_guid_t *protocol,
+ grub_efi_uint32_t attributes)
+{
+ grub_efi_boot_services_t *b;
+ grub_efi_status_t status;
+ void *interface;
+
+ b = grub_efi_system_table->boot_services;
+ status = efi_call_6 (b->open_protocol, handle,
+ protocol,
+ &interface,
+ grub_efi_image_handle,
+ 0,
+ attributes);
+ if (status != GRUB_EFI_SUCCESS)
+ return 0;
+
+ return interface;
+}
+
+void
+grub_exit (void)
+{
+ grub_efi_fini ();
+ efi_call_4 (grub_efi_system_table->boot_services->exit,
+ grub_efi_image_handle, GRUB_EFI_SUCCESS, 0, 0);
+ for (;;) ;
+}
+
+grub_efi_loaded_image_t *
+grub_efi_get_loaded_image (grub_efi_handle_t image_handle)
+{
+ return grub_efi_open_protocol (image_handle,
+ &loaded_image_guid,
+ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+}
+
+/* Allocate pages. Return the pointer to the first of allocated pages. */
+void *
+grub_efi_allocate_pages (grub_efi_physical_address_t address,
+ grub_efi_uintn_t pages)
+{
+ grub_efi_allocate_type_t type;
+ grub_efi_status_t status;
+ grub_efi_boot_services_t *b;
+
+#if 1
+ /* Limit the memory access to less than 4GB for 32-bit platforms. */
+ if (address > 0xffffffff)
+ return 0;
+#endif
+
+#if 1
+ if (address == 0)
+ {
+ type = GRUB_EFI_ALLOCATE_MAX_ADDRESS;
+ address = 0xffffffff;
+ }
+ else
+ type = GRUB_EFI_ALLOCATE_ADDRESS;
+#else
+ if (address == 0)
+ type = GRUB_EFI_ALLOCATE_ANY_PAGES;
+ else
+ type = GRUB_EFI_ALLOCATE_ADDRESS;
+#endif
+
+ b = grub_efi_system_table->boot_services;
+ status = efi_call_4 (b->allocate_pages, type, GRUB_EFI_LOADER_DATA, pages, &address);
+ if (status != GRUB_EFI_SUCCESS)
+ return 0;
+
+ if (address == 0)
+ {
+ /* Uggh, the address 0 was allocated... This is too annoying,
+ so reallocate another one. */
+ address = 0xffffffff;
+ status = efi_call_4 (b->allocate_pages, type, GRUB_EFI_LOADER_DATA, pages, &address);
+ grub_efi_free_pages (0, pages);
+ if (status != GRUB_EFI_SUCCESS)
+ return 0;
+ }
+
+ return (void *) ((grub_addr_t) address);
+}
+
+/* Free pages starting from ADDRESS. */
+void
+grub_efi_free_pages (grub_efi_physical_address_t address,
+ grub_efi_uintn_t pages)
+{
+ grub_efi_boot_services_t *b;
+
+ b = grub_efi_system_table->boot_services;
+ efi_call_2 (b->free_pages, address, pages);
+}
+
+
+#pragma GCC diagnostic ignored "-Wcast-align"
+
+/* Search the mods section from the PE32/PE32+ image. This code uses
+ a PE32 header, but should work with PE32+ as well. */
+int
+grub_efi_get_section (const char *name,
+ grub_addr_t *start, grub_size_t *sz)
+{
+ grub_efi_loaded_image_t *image;
+ struct grub_pe32_header *header;
+ struct grub_pe32_coff_header *coff_header;
+ struct grub_pe32_section_table *sections;
+ struct grub_pe32_section_table *section;
+ grub_uint16_t i;
+
+ *start = 0;
+ if (sz)
+ *sz = 0;
+
+ image = grub_efi_get_loaded_image (grub_efi_image_handle);
+ if (! image)
+ return 0;
+
+ header = image->image_base;
+ coff_header = &(header->coff_header);
+ sections
+ = (struct grub_pe32_section_table *) ((char *) coff_header
+ + sizeof (*coff_header)
+ + coff_header->optional_header_size);
+
+ for (i = 0, section = sections;
+ i < coff_header->num_sections;
+ i++, section++)
+ {
+ if (grub_strcmp (section->name, name) == 0)
+ break;
+ }
+
+ if (i == coff_header->num_sections)
+ return 0;
+
+ *start = ((grub_addr_t) image->image_base + section->virtual_address);
+ if (sz)
+ *sz = section->virtual_size;
+
+ return 1;
+}
+
+#pragma GCC diagnostic error "-Wcast-align"
void
grub_efi_init (void)
{
- grub_modbase = grub_efi_modules_addr ();
+ if (!grub_efi_get_section ("mods", &grub_modbase, NULL)
+ || ((struct grub_module_info *) grub_modbase)->magic != GRUB_MODULE_MAGIC)
+ grub_modbase = 0;
+
/* First of all, initialize the console so that GRUB can display
messages. */
grub_console_init ();
static grub_efi_uint32_t finish_desc_version;
int grub_efi_is_finished = 0;
-/* Allocate pages. Return the pointer to the first of allocated pages. */
-void *
-grub_efi_allocate_pages (grub_efi_physical_address_t address,
- grub_efi_uintn_t pages)
-{
- grub_efi_allocate_type_t type;
- grub_efi_status_t status;
- grub_efi_boot_services_t *b;
-
-#if 1
- /* Limit the memory access to less than 4GB for 32-bit platforms. */
- if (address > 0xffffffff)
- return 0;
-#endif
-
-#if 1
- if (address == 0)
- {
- type = GRUB_EFI_ALLOCATE_MAX_ADDRESS;
- address = 0xffffffff;
- }
- else
- type = GRUB_EFI_ALLOCATE_ADDRESS;
-#else
- if (address == 0)
- type = GRUB_EFI_ALLOCATE_ANY_PAGES;
- else
- type = GRUB_EFI_ALLOCATE_ADDRESS;
-#endif
-
- b = grub_efi_system_table->boot_services;
- status = efi_call_4 (b->allocate_pages, type, GRUB_EFI_LOADER_DATA, pages, &address);
- if (status != GRUB_EFI_SUCCESS)
- return 0;
-
- if (address == 0)
- {
- /* Uggh, the address 0 was allocated... This is too annoying,
- so reallocate another one. */
- address = 0xffffffff;
- status = efi_call_4 (b->allocate_pages, type, GRUB_EFI_LOADER_DATA, pages, &address);
- grub_efi_free_pages (0, pages);
- if (status != GRUB_EFI_SUCCESS)
- return 0;
- }
-
- return (void *) ((grub_addr_t) address);
-}
-
-/* Free pages starting from ADDRESS. */
-void
-grub_efi_free_pages (grub_efi_physical_address_t address,
- grub_efi_uintn_t pages)
-{
- grub_efi_boot_services_t *b;
-
- b = grub_efi_system_table->boot_services;
- efi_call_2 (b->free_pages, address, pages);
-}
-
#if defined (__i386__) || defined (__x86_64__)
/* Helper for stop_broadcom. */
#include <grub/mm.h>
#include <grub/misc.h>
+#ifndef GRUB_EMBED_DECOMPRESSOR
+
static inline void
free (void *ptr)
{
return grub_realloc (ptr, size);
}
+#endif
+
static inline int
abs (int c)
{
struct xz_dec_lzma2 *lzma2, struct xz_buf *b);
/* Free the memory allocated for the BCJ filters. */
+#ifndef GRUB_EMBED_DECOMPRESSOR
#define xz_dec_bcj_end(s) kfree(s)
+#else
+#define xz_dec_bcj_end(s)
+#endif
#endif
char **device,
char **path);
-grub_addr_t grub_efi_modules_addr (void);
+int
+grub_efi_get_section (const char *name,
+ grub_addr_t *start, grub_size_t *sz);
void grub_efi_mm_init (void);
void grub_efi_mm_fini (void);