Merge branch 'master' of git://git.savannah.gnu.org/grub
This commit is contained in:
commit
286f1b63df
95 changed files with 6481 additions and 522 deletions
|
@ -101,6 +101,7 @@ if COND_i386_efi
|
|||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h
|
||||
endif
|
||||
|
||||
|
@ -112,10 +113,12 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video_fb.h
|
|||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/gfxterm.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/font.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bufio.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
|
||||
endif
|
||||
|
||||
if COND_i386_multiboot
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
|
||||
endif
|
||||
|
||||
if COND_i386_qemu
|
||||
|
@ -154,11 +157,13 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h
|
|||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
|
||||
endif
|
||||
|
||||
if COND_ia64_efi
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
|
||||
endif
|
||||
|
||||
if COND_mips
|
||||
|
@ -233,11 +238,13 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arm/efi/loader.h
|
|||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arm/system.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
|
||||
endif
|
||||
|
||||
if COND_arm64_efi
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
|
||||
endif
|
||||
|
||||
if COND_emu
|
||||
|
|
|
@ -59,9 +59,6 @@ kernel = {
|
|||
ia64_efi_ldflags = '-Wl,-r,-d';
|
||||
ia64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version';
|
||||
|
||||
x86_64_xen_cppflags = '$(CPPFLAGS_XEN)';
|
||||
i386_xen_cppflags = '$(CPPFLAGS_XEN)';
|
||||
|
||||
arm_efi_ldflags = '-Wl,-r,-d';
|
||||
arm_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version';
|
||||
|
||||
|
@ -174,8 +171,20 @@ kernel = {
|
|||
efi = kern/efi/init.c;
|
||||
efi = kern/efi/mm.c;
|
||||
efi = term/efi/console.c;
|
||||
efi = kern/acpi.c;
|
||||
efi = kern/efi/acpi.c;
|
||||
i386_coreboot = kern/i386/pc/acpi.c;
|
||||
i386_multiboot = kern/i386/pc/acpi.c;
|
||||
i386_coreboot = kern/acpi.c;
|
||||
i386_multiboot = kern/acpi.c;
|
||||
|
||||
x86 = kern/i386/tsc.c;
|
||||
x86 = kern/i386/tsc_pit.c;
|
||||
i386_efi = kern/i386/efi/tsc.c;
|
||||
x86_64_efi = kern/i386/efi/tsc.c;
|
||||
i386_efi = kern/i386/tsc_pmtimer.c;
|
||||
i386_coreboot = kern/i386/tsc_pmtimer.c;
|
||||
x86_64_efi = kern/i386/tsc_pmtimer.c;
|
||||
|
||||
i386_efi = kern/i386/efi/init.c;
|
||||
i386_efi = bus/pci.c;
|
||||
|
@ -187,6 +196,7 @@ kernel = {
|
|||
x86_64_efi = bus/pci.c;
|
||||
|
||||
xen = kern/i386/tsc.c;
|
||||
xen = kern/i386/xen/tsc.c;
|
||||
x86_64_xen = kern/x86_64/xen/hypercall.S;
|
||||
i386_xen = kern/i386/xen/hypercall.S;
|
||||
xen = kern/xen/init.c;
|
||||
|
@ -604,7 +614,6 @@ module = {
|
|||
module = {
|
||||
name = lsxen;
|
||||
common = commands/xen/lsxen.c;
|
||||
cppflags = '$(CPPFLAGS_XEN)';
|
||||
|
||||
enable = xen;
|
||||
};
|
||||
|
@ -669,10 +678,8 @@ module = {
|
|||
name = acpi;
|
||||
|
||||
common = commands/acpi.c;
|
||||
efi = commands/efi/acpi.c;
|
||||
i386_pc = commands/i386/pc/acpi.c;
|
||||
i386_coreboot = commands/i386/pc/acpi.c;
|
||||
i386_multiboot = commands/i386/pc/acpi.c;
|
||||
i386_pc = kern/acpi.c;
|
||||
i386_pc = kern/i386/pc/acpi.c;
|
||||
|
||||
enable = efi;
|
||||
enable = i386_pc;
|
||||
|
@ -847,7 +854,6 @@ module = {
|
|||
i386_coreboot = lib/i386/halt.c;
|
||||
i386_qemu = lib/i386/halt.c;
|
||||
xen = lib/xen/halt.c;
|
||||
xen_cppflags = '$(CPPFLAGS_XEN)';
|
||||
efi = lib/efi/halt.c;
|
||||
ieee1275 = lib/ieee1275/halt.c;
|
||||
emu = lib/emu/halt.c;
|
||||
|
@ -868,7 +874,6 @@ module = {
|
|||
mips_loongson = lib/mips/loongson/reboot.c;
|
||||
mips_qemu_mips = lib/mips/qemu_mips/reboot.c;
|
||||
xen = lib/xen/reboot.c;
|
||||
xen_cppflags = '$(CPPFLAGS_XEN)';
|
||||
uboot = lib/uboot/reboot.c;
|
||||
common = commands/reboot.c;
|
||||
};
|
||||
|
@ -1485,7 +1490,6 @@ module = {
|
|||
module = {
|
||||
name = gfxmenu;
|
||||
common = gfxmenu/gfxmenu.c;
|
||||
common = gfxmenu/model.c;
|
||||
common = gfxmenu/view.c;
|
||||
common = gfxmenu/font.c;
|
||||
common = gfxmenu/icon_manager.c;
|
||||
|
@ -1564,7 +1568,6 @@ module = {
|
|||
i386_xen = lib/i386/xen/relocator.S;
|
||||
x86_64_xen = lib/x86_64/xen/relocator.S;
|
||||
xen = lib/i386/relocator_common_c.c;
|
||||
xen_cppflags = '$(CPPFLAGS_XEN)';
|
||||
|
||||
extra_dist = lib/i386/relocator_common.S;
|
||||
extra_dist = kern/powerpc/cache_flush.S;
|
||||
|
@ -1585,7 +1588,6 @@ module = {
|
|||
sparc64_ieee1275 = lib/ieee1275/cmos.c;
|
||||
powerpc_ieee1275 = lib/ieee1275/cmos.c;
|
||||
xen = lib/xen/datetime.c;
|
||||
xen_cppflags = '$(CPPFLAGS_XEN)';
|
||||
|
||||
mips_arc = lib/arc/datetime.c;
|
||||
enable = noemu;
|
||||
|
@ -1684,11 +1686,17 @@ module = {
|
|||
enable = x86;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = xen_boot;
|
||||
common = lib/cmdline.c;
|
||||
arm64 = loader/arm64/xen_boot.c;
|
||||
enable = arm64;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = linux;
|
||||
x86 = loader/i386/linux.c;
|
||||
xen = loader/i386/xen.c;
|
||||
xen_cppflags = '$(CPPFLAGS_XEN)';
|
||||
i386_pc = lib/i386/pc/vesa_modes_table.c;
|
||||
mips = loader/mips/linux.c;
|
||||
powerpc_ieee1275 = loader/powerpc/ieee1275/linux.c;
|
||||
|
@ -1696,12 +1704,18 @@ module = {
|
|||
ia64_efi = loader/ia64/efi/linux.c;
|
||||
arm = loader/arm/linux.c;
|
||||
arm64 = loader/arm64/linux.c;
|
||||
fdt = lib/fdt.c;
|
||||
common = loader/linux.c;
|
||||
common = lib/cmdline.c;
|
||||
enable = noemu;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = fdt;
|
||||
arm64 = loader/arm64/fdt.c;
|
||||
common = lib/fdt.c;
|
||||
enable = fdt;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = xnu;
|
||||
x86 = loader/xnu_resume.c;
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <grub/machine/memory.h>
|
||||
#include <grub/machine/kernel.h>
|
||||
#include <grub/offsets.h>
|
||||
#include <grub/mips/asm.h>
|
||||
|
||||
#define BASE_ADDR 8
|
||||
|
||||
|
@ -118,32 +119,32 @@ parsestr:
|
|||
move $v0, $zero
|
||||
move $t3, $t1
|
||||
3:
|
||||
lb $t4, 0($t2)
|
||||
lb $t5, 0($t3)
|
||||
lb GRUB_ASM_T4, 0($t2)
|
||||
lb GRUB_ASM_T5, 0($t3)
|
||||
addiu $t2, $t2, 1
|
||||
addiu $t3, $t3, 1
|
||||
beq $t5, $zero, 1f
|
||||
beq GRUB_ASM_T5, $zero, 1f
|
||||
nop
|
||||
beq $t5, $t4, 3b
|
||||
beq GRUB_ASM_T5, GRUB_ASM_T4, 3b
|
||||
nop
|
||||
bne $t4, $zero, 1f
|
||||
bne GRUB_ASM_T4, $zero, 1f
|
||||
nop
|
||||
|
||||
addiu $t3, $t3, 0xffff
|
||||
digcont:
|
||||
lb $t5, 0($t3)
|
||||
lb GRUB_ASM_T5, 0($t3)
|
||||
/* Substract '0' from digit. */
|
||||
addiu $t5, $t5, 0xffd0
|
||||
bltz $t5, 1f
|
||||
addiu GRUB_ASM_T5, GRUB_ASM_T5, 0xffd0
|
||||
bltz GRUB_ASM_T5, 1f
|
||||
nop
|
||||
addiu $t4, $t5, 0xfff7
|
||||
bgtz $t4, 1f
|
||||
addiu GRUB_ASM_T4, GRUB_ASM_T5, 0xfff7
|
||||
bgtz GRUB_ASM_T4, 1f
|
||||
nop
|
||||
/* Multiply $v0 by 10 with bitshifts. */
|
||||
sll $v0, $v0, 1
|
||||
sll $t4, $v0, 2
|
||||
addu $v0, $v0, $t4
|
||||
addu $v0, $v0, $t5
|
||||
sll GRUB_ASM_T4, $v0, 2
|
||||
addu $v0, $v0, GRUB_ASM_T4
|
||||
addu $v0, $v0, GRUB_ASM_T5
|
||||
addiu $t3, $t3, 1
|
||||
b digcont
|
||||
nop
|
||||
|
@ -182,10 +183,10 @@ argdone:
|
|||
b argdone
|
||||
addiu $a1, $a1, 4
|
||||
do_check:
|
||||
lb $t4, 0($t7)
|
||||
beq $t4, $zero, 1f
|
||||
lb GRUB_ASM_T4, 0($t7)
|
||||
beq GRUB_ASM_T4, $zero, 1f
|
||||
lb $t3, 0($t6)
|
||||
bne $t3, $t4, 2f
|
||||
bne $t3, GRUB_ASM_T4, 2f
|
||||
addiu $t6, $t6, 1
|
||||
b do_check
|
||||
addiu $t7, $t7, 1
|
||||
|
@ -222,8 +223,8 @@ cmdlinedone:
|
|||
|
||||
1:
|
||||
beq $t1, $t3, 2f
|
||||
lb $t4, 0($t2)
|
||||
sb $t4, 0($t1)
|
||||
lb GRUB_ASM_T4, 0($t2)
|
||||
sb GRUB_ASM_T4, 0($t1)
|
||||
addiu $t1, $t1, 1
|
||||
b 1b
|
||||
addiu $t2, $t2, 1
|
||||
|
|
|
@ -61,18 +61,6 @@ static const struct grub_arg_option options[] = {
|
|||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
/* Simple checksum by summing all bytes. Used by ACPI and SMBIOS. */
|
||||
grub_uint8_t
|
||||
grub_byte_checksum (void *base, grub_size_t size)
|
||||
{
|
||||
grub_uint8_t *ptr;
|
||||
grub_uint8_t ret = 0;
|
||||
for (ptr = (grub_uint8_t *) base; ptr < ((grub_uint8_t *) base) + size;
|
||||
ptr++)
|
||||
ret += *ptr;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* rev1 is 1 if ACPIv1 is to be generated, 0 otherwise.
|
||||
rev2 contains the revision of ACPIv2+ to generate or 0 if none. */
|
||||
static int rev1, rev2;
|
||||
|
|
|
@ -51,7 +51,7 @@ grub_cmd_lsefimmap (grub_command_t cmd __attribute__ ((unused)),
|
|||
|
||||
grub_printf
|
||||
("Type Physical start - end #Pages "
|
||||
" Size Attributes\n");
|
||||
" Size Attributes\n");
|
||||
memory_map_end = ADD_MEMORY_DESCRIPTOR (memory_map, map_size);
|
||||
for (desc = memory_map;
|
||||
desc < memory_map_end;
|
||||
|
@ -74,7 +74,8 @@ grub_cmd_lsefimmap (grub_command_t cmd __attribute__ ((unused)),
|
|||
"ACPI-nvs",
|
||||
"MMIO ",
|
||||
"IO-ports",
|
||||
"PAL-code"
|
||||
"PAL-code",
|
||||
"persist ",
|
||||
};
|
||||
if (desc->type < ARRAY_SIZE (types_str))
|
||||
grub_printf ("%s ", types_str[desc->type]);
|
||||
|
@ -87,21 +88,29 @@ grub_cmd_lsefimmap (grub_command_t cmd __attribute__ ((unused)),
|
|||
desc->physical_start + (desc->num_pages << 12) - 1,
|
||||
desc->num_pages);
|
||||
|
||||
size = desc->num_pages;
|
||||
size <<= (12 - 10);
|
||||
if (size < 1024)
|
||||
grub_printf (" %4" PRIuGRUB_UINT64_T "KB", size);
|
||||
size = desc->num_pages << 12; /* 4 KiB page size */
|
||||
/*
|
||||
* Since size is a multiple of 4 KiB, no need to handle units
|
||||
* of just Bytes (which would use a mask of 0x3ff).
|
||||
*
|
||||
* 14 characters would support the largest possible number of 4 KiB
|
||||
* pages that are not a multiple of larger units (e.g., MiB):
|
||||
* 17592186044415 (0xffffff_fffff000), but that uses a lot of
|
||||
* whitespace for a rare case. 6 characters usually suffices;
|
||||
* columns will be off if not, but this is preferable to rounding.
|
||||
*/
|
||||
if (size & 0xfffff)
|
||||
grub_printf (" %6" PRIuGRUB_UINT64_T "KiB", size >> 10);
|
||||
else if (size & 0x3fffffff)
|
||||
grub_printf (" %6" PRIuGRUB_UINT64_T "MiB", size >> 20);
|
||||
else if (size & 0xffffffffff)
|
||||
grub_printf (" %6" PRIuGRUB_UINT64_T "GiB", size >> 30);
|
||||
else if (size & 0x3ffffffffffff)
|
||||
grub_printf (" %6" PRIuGRUB_UINT64_T "TiB", size >> 40);
|
||||
else if (size & 0xfffffffffffffff)
|
||||
grub_printf (" %6" PRIuGRUB_UINT64_T "PiB", size >> 50);
|
||||
else
|
||||
{
|
||||
size /= 1024;
|
||||
if (size < 1024)
|
||||
grub_printf (" %4" PRIuGRUB_UINT64_T "MB", size);
|
||||
else
|
||||
{
|
||||
size /= 1024;
|
||||
grub_printf (" %4" PRIuGRUB_UINT64_T "GB", size);
|
||||
}
|
||||
}
|
||||
grub_printf (" %6" PRIuGRUB_UINT64_T "EiB", size >> 60);
|
||||
|
||||
attr = desc->attribute;
|
||||
if (attr & GRUB_EFI_MEMORY_RUNTIME)
|
||||
|
@ -122,6 +131,12 @@ grub_cmd_lsefimmap (grub_command_t cmd __attribute__ ((unused)),
|
|||
grub_printf (" RP");
|
||||
if (attr & GRUB_EFI_MEMORY_XP)
|
||||
grub_printf (" XP");
|
||||
if (attr & GRUB_EFI_MEMORY_NV)
|
||||
grub_printf (" NV");
|
||||
if (attr & GRUB_EFI_MEMORY_MORE_RELIABLE)
|
||||
grub_printf (" MR");
|
||||
if (attr & GRUB_EFI_MEMORY_RO)
|
||||
grub_printf (" RO");
|
||||
|
||||
grub_printf ("\n");
|
||||
}
|
||||
|
|
|
@ -37,10 +37,20 @@ static const struct guid_mapping guid_mappings[] =
|
|||
{
|
||||
{ GRUB_EFI_ACPI_20_TABLE_GUID, "ACPI-2.0"},
|
||||
{ GRUB_EFI_ACPI_TABLE_GUID, "ACPI-1.0"},
|
||||
{ GRUB_EFI_CRC32_GUIDED_SECTION_EXTRACTION_GUID,
|
||||
"CRC32 GUIDED SECTION EXTRACTION"},
|
||||
{ GRUB_EFI_DEBUG_IMAGE_INFO_TABLE_GUID, "DEBUG IMAGE INFO"},
|
||||
{ GRUB_EFI_DXE_SERVICES_TABLE_GUID, "DXE SERVICES"},
|
||||
{ GRUB_EFI_HCDP_TABLE_GUID, "HCDP"},
|
||||
{ GRUB_EFI_HOB_LIST_GUID, "HOB LIST"},
|
||||
{ GRUB_EFI_LZMA_CUSTOM_DECOMPRESS_GUID, "LZMA CUSTOM DECOMPRESS"},
|
||||
{ GRUB_EFI_MEMORY_TYPE_INFORMATION_GUID, "MEMORY TYPE INFO"},
|
||||
{ GRUB_EFI_MPS_TABLE_GUID, "MPS"},
|
||||
{ GRUB_EFI_SAL_TABLE_GUID, "SAL"},
|
||||
{ GRUB_EFI_SMBIOS_TABLE_GUID, "SMBIOS"},
|
||||
{ GRUB_EFI_MPS_TABLE_GUID, "MPS"},
|
||||
{ GRUB_EFI_HCDP_TABLE_GUID, "HCDP"}
|
||||
{ GRUB_EFI_SYSTEM_RESOURCE_TABLE_GUID, "SYSTEM RESOURCE TABLE"},
|
||||
{ GRUB_EFI_TIANO_CUSTOM_DECOMPRESS_GUID, "TIANO CUSTOM DECOMPRESS"},
|
||||
{ GRUB_EFI_TSC_FREQUENCY_GUID, "TSC FREQUENCY"},
|
||||
};
|
||||
|
||||
static grub_err_t
|
||||
|
|
|
@ -37,6 +37,8 @@ static const char *names[] =
|
|||
is required to save accross hibernations. */
|
||||
[GRUB_MEMORY_NVS] = N_("ACPI non-volatile storage RAM"),
|
||||
[GRUB_MEMORY_BADRAM] = N_("faulty RAM (BadRAM)"),
|
||||
[GRUB_MEMORY_PERSISTENT] = N_("persistent RAM"),
|
||||
[GRUB_MEMORY_PERSISTENT_LEGACY] = N_("persistent RAM (legacy)"),
|
||||
[GRUB_MEMORY_COREBOOT_TABLES] = N_("RAM holding coreboot tables"),
|
||||
[GRUB_MEMORY_CODE] = N_("RAM holding firmware code")
|
||||
};
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <grub/fs.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/procfs.h>
|
||||
#include <grub/partition.h>
|
||||
|
||||
#ifdef GRUB_UTIL
|
||||
#include <grub/emu/hostdisk.h>
|
||||
|
@ -718,6 +719,7 @@ grub_cryptodisk_insert (grub_cryptodisk_t newdev, const char *name,
|
|||
newdev->id = last_cryptodisk_id++;
|
||||
newdev->source_id = source->id;
|
||||
newdev->source_dev_id = source->dev->id;
|
||||
newdev->partition_start = grub_partition_get_start (source->partition);
|
||||
newdev->next = cryptodisk_list;
|
||||
cryptodisk_list = newdev;
|
||||
|
||||
|
@ -740,7 +742,9 @@ grub_cryptodisk_get_by_source_disk (grub_disk_t disk)
|
|||
grub_cryptodisk_t dev;
|
||||
for (dev = cryptodisk_list; dev != NULL; dev = dev->next)
|
||||
if (dev->source_id == disk->id && dev->source_dev_id == disk->dev->id)
|
||||
return dev;
|
||||
if ((disk->partition && grub_partition_get_start (disk->partition) == dev->partition_start) ||
|
||||
(!disk->partition && dev->partition_start == 0))
|
||||
return dev;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -761,6 +765,7 @@ grub_cryptodisk_cheat_insert (grub_cryptodisk_t newdev, const char *name,
|
|||
newdev->cheat_fd = GRUB_UTIL_FD_INVALID;
|
||||
newdev->source_id = source->id;
|
||||
newdev->source_dev_id = source->dev->id;
|
||||
newdev->partition_start = grub_partition_get_start (source->partition);
|
||||
newdev->id = last_cryptodisk_id++;
|
||||
newdev->next = cryptodisk_list;
|
||||
cryptodisk_list = newdev;
|
||||
|
@ -964,33 +969,43 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
|
|||
grub_disk_t disk;
|
||||
grub_cryptodisk_t dev;
|
||||
char *diskname;
|
||||
char *disklast;
|
||||
char *disklast = NULL;
|
||||
grub_size_t len;
|
||||
|
||||
search_uuid = NULL;
|
||||
check_boot = state[2].set;
|
||||
diskname = args[0];
|
||||
if (diskname[0] == '(' && *(disklast = &diskname[grub_strlen (diskname) - 1]) == ')')
|
||||
len = grub_strlen (diskname);
|
||||
if (len && diskname[0] == '(' && diskname[len - 1] == ')')
|
||||
{
|
||||
disklast = &diskname[len - 1];
|
||||
*disklast = '\0';
|
||||
disk = grub_disk_open (diskname + 1);
|
||||
*disklast = ')';
|
||||
diskname++;
|
||||
}
|
||||
else
|
||||
disk = grub_disk_open (diskname);
|
||||
|
||||
disk = grub_disk_open (diskname);
|
||||
if (!disk)
|
||||
return grub_errno;
|
||||
{
|
||||
if (disklast)
|
||||
*disklast = ')';
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
dev = grub_cryptodisk_get_by_source_disk (disk);
|
||||
if (dev)
|
||||
{
|
||||
grub_dprintf ("cryptodisk", "already mounted as crypto%lu\n", dev->id);
|
||||
grub_disk_close (disk);
|
||||
if (disklast)
|
||||
*disklast = ')';
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
err = grub_cryptodisk_scan_device_real (args[0], disk);
|
||||
err = grub_cryptodisk_scan_device_real (diskname, disk);
|
||||
|
||||
grub_disk_close (disk);
|
||||
if (disklast)
|
||||
*disklast = ')';
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -227,7 +227,10 @@ dev_iterate (const struct grub_ieee1275_devalias *alias)
|
|||
|
||||
if (grub_ieee1275_open (alias->path, &ihandle))
|
||||
return;
|
||||
|
||||
|
||||
/* This method doesn't need memory allocation for the table. Open
|
||||
firmware takes care of all memory management and the result table
|
||||
stays in memory and is never freed. */
|
||||
INIT_IEEE1275_COMMON (&args.common, "call-method", 2, 3);
|
||||
args.method = (grub_ieee1275_cell_t) "vscsi-report-luns";
|
||||
args.ihandle = ihandle;
|
||||
|
@ -260,6 +263,82 @@ dev_iterate (const struct grub_ieee1275_devalias *alias)
|
|||
grub_free (buf);
|
||||
return;
|
||||
}
|
||||
else if (grub_strcmp (alias->type, "sas_ioa") == 0)
|
||||
{
|
||||
/* The method returns the number of disks and a table where
|
||||
* each ID is 64-bit long. Example of sas paths:
|
||||
* /pci@80000002000001f/pci1014,034A@0/sas/disk@c05db70800
|
||||
* /pci@80000002000001f/pci1014,034A@0/sas/disk@a05db70800
|
||||
* /pci@80000002000001f/pci1014,034A@0/sas/disk@805db70800 */
|
||||
|
||||
struct sas_children
|
||||
{
|
||||
struct grub_ieee1275_common_hdr common;
|
||||
grub_ieee1275_cell_t method;
|
||||
grub_ieee1275_cell_t ihandle;
|
||||
grub_ieee1275_cell_t max;
|
||||
grub_ieee1275_cell_t table;
|
||||
grub_ieee1275_cell_t catch_result;
|
||||
grub_ieee1275_cell_t nentries;
|
||||
}
|
||||
args;
|
||||
char *buf, *bufptr;
|
||||
unsigned i;
|
||||
grub_uint64_t *table;
|
||||
grub_uint16_t table_size;
|
||||
grub_ieee1275_ihandle_t ihandle;
|
||||
|
||||
buf = grub_malloc (grub_strlen (alias->path) +
|
||||
sizeof ("/disk@7766554433221100"));
|
||||
if (!buf)
|
||||
return;
|
||||
bufptr = grub_stpcpy (buf, alias->path);
|
||||
|
||||
/* Power machines documentation specify 672 as maximum SAS disks in
|
||||
one system. Using a slightly larger value to be safe. */
|
||||
table_size = 768;
|
||||
table = grub_malloc (table_size * sizeof (grub_uint64_t));
|
||||
|
||||
if (!table)
|
||||
{
|
||||
grub_free (buf);
|
||||
return;
|
||||
}
|
||||
|
||||
if (grub_ieee1275_open (alias->path, &ihandle))
|
||||
{
|
||||
grub_free (buf);
|
||||
grub_free (table);
|
||||
return;
|
||||
}
|
||||
|
||||
INIT_IEEE1275_COMMON (&args.common, "call-method", 4, 2);
|
||||
args.method = (grub_ieee1275_cell_t) "get-sas-children";
|
||||
args.ihandle = ihandle;
|
||||
args.max = table_size;
|
||||
args.table = (grub_ieee1275_cell_t) table;
|
||||
args.catch_result = 0;
|
||||
args.nentries = 0;
|
||||
|
||||
if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
|
||||
{
|
||||
grub_ieee1275_close (ihandle);
|
||||
grub_free (table);
|
||||
grub_free (buf);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < args.nentries; i++)
|
||||
{
|
||||
grub_snprintf (bufptr, sizeof ("/disk@7766554433221100"),
|
||||
"/disk@%" PRIxGRUB_UINT64_T, table[i]);
|
||||
dev_iterate_real (buf, buf);
|
||||
}
|
||||
|
||||
grub_ieee1275_close (ihandle);
|
||||
grub_free (table);
|
||||
grub_free (buf);
|
||||
}
|
||||
|
||||
if (!grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_TREE_SCANNING_FOR_DISKS)
|
||||
&& grub_strcmp (alias->type, "block") == 0)
|
||||
|
@ -422,16 +501,20 @@ grub_ofdisk_open (const char *name, grub_disk_t disk)
|
|||
op = ofdisk_hash_find (devpath);
|
||||
if (!op)
|
||||
op = ofdisk_hash_add (devpath, NULL);
|
||||
else
|
||||
grub_free (devpath);
|
||||
if (!op)
|
||||
return grub_errno;
|
||||
{
|
||||
grub_free (devpath);
|
||||
return grub_errno;
|
||||
}
|
||||
disk->id = (unsigned long) op;
|
||||
disk->data = op->open_path;
|
||||
|
||||
err = grub_ofdisk_get_block_size (devpath, &block_size, op);
|
||||
if (err)
|
||||
return err;
|
||||
{
|
||||
grub_free (devpath);
|
||||
return err;
|
||||
}
|
||||
if (block_size != 0)
|
||||
{
|
||||
for (disk->log_sector_size = 0;
|
||||
|
@ -442,6 +525,7 @@ grub_ofdisk_open (const char *name, grub_disk_t disk)
|
|||
disk->log_sector_size = 9;
|
||||
}
|
||||
|
||||
grub_free (devpath);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -963,7 +963,7 @@ grub_util_ldm_embed (struct grub_disk *disk, unsigned int *nsectors,
|
|||
|
||||
if (embed_type != GRUB_EMBED_PCBIOS)
|
||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||
"LDM curently supports only PC-BIOS embedding");
|
||||
"LDM currently supports only PC-BIOS embedding");
|
||||
if (disk->partition)
|
||||
return grub_error (GRUB_ERR_BUG, "disk isn't LDM");
|
||||
pv = grub_diskfilter_get_pv_from_disk (disk, &vg);
|
||||
|
|
|
@ -344,8 +344,16 @@ init_cbfsdisk (void)
|
|||
|
||||
ptr = *(grub_uint32_t *) 0xfffffffc;
|
||||
head = (struct cbfs_header *) (grub_addr_t) ptr;
|
||||
grub_dprintf ("cbfs", "head=%p\n", head);
|
||||
|
||||
if (!validate_head (head))
|
||||
/* coreboot current supports only ROMs <= 16 MiB. Bigger ROMs will
|
||||
have problems as RCBA is 18 MiB below end of 32-bit typically,
|
||||
so either memory map would have to be rearranged or we'd need to support
|
||||
reading ROMs through controller directly.
|
||||
*/
|
||||
if (ptr < 0xff000000
|
||||
|| 0xffffffff - ptr < (grub_uint32_t) sizeof (*head) + 0xf
|
||||
|| !validate_head (head))
|
||||
return;
|
||||
|
||||
cbfsdisk_size = ALIGN_UP (grub_be_to_cpu32 (head->romsize),
|
||||
|
|
|
@ -394,7 +394,7 @@ grub_ufs_read_file (struct grub_ufs_data *data,
|
|||
return -1;
|
||||
}
|
||||
else
|
||||
grub_memset (buf, UFS_BLKSZ (sblock) - skipfirst, 0);
|
||||
grub_memset (buf, 0, blockend);
|
||||
|
||||
buf += UFS_BLKSZ (sblock) - skipfirst;
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ BEGIN {
|
|||
}
|
||||
}
|
||||
else {
|
||||
printf "error: %u: unrecognized input format\n", NR;
|
||||
printf "error: %u: unrecognized input format\n", NR >"/dev/stderr";
|
||||
error++;
|
||||
}
|
||||
}
|
||||
|
@ -39,6 +39,8 @@ END {
|
|||
if (error >= 1)
|
||||
exit 1;
|
||||
|
||||
total_depcount = 0
|
||||
|
||||
for (mod in modtab) {
|
||||
# Remove duplications.
|
||||
split(modtab[mod], depmods, " ");
|
||||
|
@ -52,14 +54,42 @@ END {
|
|||
uniqmods[depmod] = 1;
|
||||
}
|
||||
modlist = ""
|
||||
depcount[mod] = 0
|
||||
for (depmod in uniqmods) {
|
||||
modlist = modlist " " depmod;
|
||||
inverse_dependencies[depmod] = inverse_dependencies[depmod] " " mod
|
||||
depcount[mod]++
|
||||
total_depcount++
|
||||
}
|
||||
if (mod == "all_video") {
|
||||
continue;
|
||||
}
|
||||
printf "%s:%s\n", mod, modlist;
|
||||
}
|
||||
|
||||
# Check that we have no dependency circles
|
||||
while (total_depcount != 0) {
|
||||
something_done = 0
|
||||
for (mod in depcount) {
|
||||
if (depcount[mod] == 0) {
|
||||
delete depcount[mod]
|
||||
split(inverse_dependencies[mod], inv_depmods, " ");
|
||||
for (ctr in inv_depmods) {
|
||||
depcount[inv_depmods[ctr]]--
|
||||
total_depcount--
|
||||
}
|
||||
delete inverse_dependencies[mod]
|
||||
something_done = 1
|
||||
}
|
||||
}
|
||||
if (something_done == 0) {
|
||||
for (mod in depcount) {
|
||||
circle = circle " " mod
|
||||
}
|
||||
printf "error: modules %s form a dependency circle\n", circle >"/dev/stderr";
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
modlist = ""
|
||||
while (getline <"video.lst") {
|
||||
modlist = modlist " " $1;
|
||||
|
|
|
@ -255,7 +255,7 @@ theme_set_string (grub_gfxmenu_view_t view,
|
|||
{
|
||||
unsigned int tmp;
|
||||
int err = theme_get_unsigned_int_from_proportional (value,
|
||||
view->screen.width,
|
||||
view->screen.height,
|
||||
&tmp);
|
||||
if (err != GRUB_ERR_NONE)
|
||||
return err;
|
||||
|
@ -275,7 +275,7 @@ theme_set_string (grub_gfxmenu_view_t view,
|
|||
{
|
||||
unsigned int tmp;
|
||||
int err = theme_get_unsigned_int_from_proportional (value,
|
||||
view->screen.width,
|
||||
view->screen.height,
|
||||
&tmp);
|
||||
if (err != GRUB_ERR_NONE)
|
||||
return err;
|
||||
|
|
34
grub-core/kern/acpi.c
Normal file
34
grub-core/kern/acpi.c
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2012 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/time.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/acpi.h>
|
||||
|
||||
/* Simple checksum by summing all bytes. Used by ACPI and SMBIOS. */
|
||||
grub_uint8_t
|
||||
grub_byte_checksum (void *base, grub_size_t size)
|
||||
{
|
||||
grub_uint8_t *ptr;
|
||||
grub_uint8_t ret = 0;
|
||||
for (ptr = (grub_uint8_t *) base; ptr < ((grub_uint8_t *) base) + size;
|
||||
ptr++)
|
||||
ret += *ptr;
|
||||
return ret;
|
||||
}
|
|
@ -28,6 +28,25 @@
|
|||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wcast-align"
|
||||
|
||||
#if defined(__powerpc__) && defined(GRUB_MACHINE_IEEE1275)
|
||||
#define GRUB_ELF_ENABLE_BI_ENDIAN 1
|
||||
#else
|
||||
#define GRUB_ELF_ENABLE_BI_ENDIAN 0
|
||||
#endif
|
||||
|
||||
#if defined(GRUB_CPU_WORDS_BIGENDIAN)
|
||||
#define GRUB_ELF_NATIVE_ENDIANNESS ELFDATA2MSB
|
||||
#define GRUB_ELF_OPPOSITE_ENDIANNESS ELFDATA2LSB
|
||||
#else
|
||||
#define GRUB_ELF_NATIVE_ENDIANNESS ELFDATA2LSB
|
||||
#define GRUB_ELF_OPPOSITE_ENDIANNESS ELFDATA2MSB
|
||||
#endif
|
||||
|
||||
static int grub_elf32_check_endianess_and_bswap_ehdr (grub_elf_t elf);
|
||||
static int grub_elf64_check_endianess_and_bswap_ehdr (grub_elf_t elf);
|
||||
|
||||
/* Check if EHDR is a valid ELF header. */
|
||||
static grub_err_t
|
||||
grub_elf_check_header (grub_elf_t elf)
|
||||
|
@ -38,8 +57,25 @@ grub_elf_check_header (grub_elf_t elf)
|
|||
|| e->e_ident[EI_MAG1] != ELFMAG1
|
||||
|| e->e_ident[EI_MAG2] != ELFMAG2
|
||||
|| e->e_ident[EI_MAG3] != ELFMAG3
|
||||
|| e->e_ident[EI_VERSION] != EV_CURRENT
|
||||
|| e->e_version != EV_CURRENT)
|
||||
|| e->e_ident[EI_VERSION] != EV_CURRENT)
|
||||
return grub_error (GRUB_ERR_BAD_OS, N_("invalid arch-independent ELF magic"));
|
||||
|
||||
if (grub_elf_is_elf32 (elf))
|
||||
{
|
||||
if (!grub_elf32_check_endianess_and_bswap_ehdr (elf)) {
|
||||
return grub_error (GRUB_ERR_BAD_OS, "invalid ELF endianness magic");
|
||||
}
|
||||
}
|
||||
else if (grub_elf_is_elf64 (elf))
|
||||
{
|
||||
if (!grub_elf64_check_endianess_and_bswap_ehdr (elf)) {
|
||||
return grub_error (GRUB_ERR_BAD_OS, "invalid ELF endianness magic");
|
||||
}
|
||||
}
|
||||
else
|
||||
return grub_error (GRUB_ERR_BAD_OS, "unknown ELF class");
|
||||
|
||||
if (e->e_version != EV_CURRENT)
|
||||
return grub_error (GRUB_ERR_BAD_OS, N_("invalid arch-independent ELF magic"));
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
|
@ -117,6 +153,9 @@ grub_elf_open (const char *name)
|
|||
}
|
||||
|
||||
|
||||
#define grub_swap_bytes_halfXX grub_swap_bytes16
|
||||
#define grub_swap_bytes_wordXX grub_swap_bytes32
|
||||
|
||||
/* 32-bit */
|
||||
#define ehdrXX ehdr32
|
||||
#define ELFCLASSXX ELFCLASS32
|
||||
|
@ -127,7 +166,12 @@ grub_elf_open (const char *name)
|
|||
#define grub_elf_is_elfXX grub_elf_is_elf32
|
||||
#define grub_elfXX_load_phdrs grub_elf32_load_phdrs
|
||||
#define ElfXX_Phdr Elf32_Phdr
|
||||
#define ElfXX_Ehdr Elf32_Ehdr
|
||||
#define grub_uintXX_t grub_uint32_t
|
||||
#define grub_swap_bytes_addrXX grub_swap_bytes32
|
||||
#define grub_swap_bytes_offXX grub_swap_bytes32
|
||||
#define grub_swap_bytes_XwordXX grub_swap_bytes32
|
||||
#define grub_elfXX_check_endianess_and_bswap_ehdr grub_elf32_check_endianess_and_bswap_ehdr
|
||||
|
||||
#include "elfXX.c"
|
||||
|
||||
|
@ -140,7 +184,12 @@ grub_elf_open (const char *name)
|
|||
#undef grub_elf_is_elfXX
|
||||
#undef grub_elfXX_load_phdrs
|
||||
#undef ElfXX_Phdr
|
||||
#undef ElfXX_Ehdr
|
||||
#undef grub_uintXX_t
|
||||
#undef grub_swap_bytes_addrXX
|
||||
#undef grub_swap_bytes_offXX
|
||||
#undef grub_swap_bytes_XwordXX
|
||||
#undef grub_elfXX_check_endianess_and_bswap_ehdr
|
||||
|
||||
|
||||
/* 64-bit */
|
||||
|
@ -153,6 +202,11 @@ grub_elf_open (const char *name)
|
|||
#define grub_elf_is_elfXX grub_elf_is_elf64
|
||||
#define grub_elfXX_load_phdrs grub_elf64_load_phdrs
|
||||
#define ElfXX_Phdr Elf64_Phdr
|
||||
#define ElfXX_Ehdr Elf64_Ehdr
|
||||
#define grub_uintXX_t grub_uint64_t
|
||||
#define grub_swap_bytes_addrXX grub_swap_bytes64
|
||||
#define grub_swap_bytes_offXX grub_swap_bytes64
|
||||
#define grub_swap_bytes_XwordXX grub_swap_bytes64
|
||||
#define grub_elfXX_check_endianess_and_bswap_ehdr grub_elf64_check_endianess_and_bswap_ehdr
|
||||
|
||||
#include "elfXX.c"
|
||||
|
|
|
@ -31,6 +31,25 @@ grub_elfXX_load_phdrs (grub_elf_t elf)
|
|||
return grub_errno;
|
||||
}
|
||||
|
||||
#if GRUB_ELF_ENABLE_BI_ENDIAN
|
||||
if (elf->ehdr.ehdrXX.e_ident[EI_DATA] == GRUB_ELF_OPPOSITE_ENDIANNESS)
|
||||
{
|
||||
ElfXX_Phdr *phdr;
|
||||
for (phdr = elf->phdrs; (char *) phdr < (char *) elf->phdrs + phdrs_size;
|
||||
phdr = (ElfXX_Phdr *) ((char *) phdr + elf->ehdr.ehdrXX.e_phentsize))
|
||||
{
|
||||
phdr->p_type = grub_swap_bytes_wordXX (phdr->p_type);
|
||||
phdr->p_flags = grub_swap_bytes_wordXX (phdr->p_flags);
|
||||
phdr->p_offset = grub_swap_bytes_offXX (phdr->p_offset);
|
||||
phdr->p_vaddr = grub_swap_bytes_addrXX (phdr->p_vaddr);
|
||||
phdr->p_paddr = grub_swap_bytes_addrXX (phdr->p_paddr);
|
||||
phdr->p_filesz = grub_swap_bytes_XwordXX (phdr->p_filesz);
|
||||
phdr->p_memsz = grub_swap_bytes_XwordXX (phdr->p_memsz);
|
||||
phdr->p_align = grub_swap_bytes_XwordXX (phdr->p_align);
|
||||
}
|
||||
}
|
||||
#endif /* GRUB_ELF_ENABLE_BI_ENDIAN */
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
|
@ -154,3 +173,35 @@ grub_elfXX_load (grub_elf_t elf, const char *filename,
|
|||
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static int
|
||||
grub_elfXX_check_endianess_and_bswap_ehdr (grub_elf_t elf)
|
||||
{
|
||||
ElfXX_Ehdr *e = &(elf->ehdr.ehdrXX);
|
||||
if (e->e_ident[EI_DATA] == GRUB_ELF_NATIVE_ENDIANNESS)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if GRUB_ELF_ENABLE_BI_ENDIAN
|
||||
if (e->e_ident[EI_DATA] == GRUB_ELF_OPPOSITE_ENDIANNESS)
|
||||
{
|
||||
e->e_type = grub_swap_bytes_halfXX (e->e_type);
|
||||
e->e_machine = grub_swap_bytes_halfXX (e->e_machine);
|
||||
e->e_version = grub_swap_bytes_wordXX (e->e_version);
|
||||
e->e_entry = grub_swap_bytes_addrXX (e->e_entry);
|
||||
e->e_phoff = grub_swap_bytes_offXX (e->e_phoff);
|
||||
e->e_shoff = grub_swap_bytes_offXX (e->e_shoff);
|
||||
e->e_flags = grub_swap_bytes_wordXX (e->e_flags);
|
||||
e->e_ehsize = grub_swap_bytes_halfXX (e->e_ehsize);
|
||||
e->e_phentsize = grub_swap_bytes_halfXX (e->e_phentsize);
|
||||
e->e_phnum = grub_swap_bytes_halfXX (e->e_phnum);
|
||||
e->e_shentsize = grub_swap_bytes_halfXX (e->e_shentsize);
|
||||
e->e_shnum = grub_swap_bytes_halfXX (e->e_shnum);
|
||||
e->e_shstrndx = grub_swap_bytes_halfXX (e->e_shstrndx);
|
||||
return 1;
|
||||
}
|
||||
#endif /* GRUB_ELF_ENABLE_BI_ENDIAN */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -89,7 +89,16 @@ grub_file_open (const char *name)
|
|||
|
||||
file->device = device;
|
||||
|
||||
if (device->disk && file_name[0] != '/')
|
||||
/* In case of relative pathnames and non-Unix systems (like Windows)
|
||||
* name of host files may not start with `/'. Blocklists for host files
|
||||
* are meaningless as well (for a start, host disk does not allow any direct
|
||||
* access - it is just a marker). So skip host disk in this case.
|
||||
*/
|
||||
if (device->disk && file_name[0] != '/'
|
||||
#if defined(GRUB_UTIL) || defined(GRUB_MACHINE_EMU)
|
||||
&& grub_strcmp (device->disk->name, "host")
|
||||
#endif
|
||||
)
|
||||
/* This is a block list. */
|
||||
file->fs = &grub_fs_blocklist;
|
||||
else
|
||||
|
|
40
grub-core/kern/i386/efi/tsc.c
Normal file
40
grub-core/kern/i386/efi/tsc.c
Normal file
|
@ -0,0 +1,40 @@
|
|||
/* kern/i386/tsc.c - x86 TSC time source implementation
|
||||
* Requires Pentium or better x86 CPU that supports the RDTSC instruction.
|
||||
* This module uses the PIT to calibrate the TSC to
|
||||
* real time.
|
||||
*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2008 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/time.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/i386/tsc.h>
|
||||
#include <grub/efi/efi.h>
|
||||
#include <grub/efi/api.h>
|
||||
|
||||
int
|
||||
grub_tsc_calibrate_from_efi (void)
|
||||
{
|
||||
grub_uint64_t start_tsc, end_tsc;
|
||||
/* Use EFI Time Service to calibrate TSC */
|
||||
start_tsc = grub_get_tsc ();
|
||||
efi_call_1 (grub_efi_system_table->boot_services->stall, 1000);
|
||||
end_tsc = grub_get_tsc ();
|
||||
grub_tsc_rate = grub_divmod64 ((1ULL << 32), end_tsc - start_tsc, 0);
|
||||
return 1;
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
/* kern/i386/tsc.c - x86 TSC time source implementation
|
||||
* Requires Pentium or better x86 CPU that supports the RDTSC instruction.
|
||||
* This module uses the RTC (via grub_get_rtc()) to calibrate the TSC to
|
||||
* real time.
|
||||
* This module calibrates the TSC to real time.
|
||||
*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2008 Free Software Foundation, Inc.
|
||||
|
@ -25,12 +24,6 @@
|
|||
#include <grub/misc.h>
|
||||
#include <grub/i386/tsc.h>
|
||||
#include <grub/i386/cpuid.h>
|
||||
#ifdef GRUB_MACHINE_XEN
|
||||
#include <grub/xen.h>
|
||||
#else
|
||||
#include <grub/i386/pit.h>
|
||||
#endif
|
||||
#include <grub/cpu/io.h>
|
||||
|
||||
/* This defines the value TSC had at the epoch (that is, when we calibrated it). */
|
||||
static grub_uint64_t tsc_boot_time;
|
||||
|
@ -40,66 +33,6 @@ static grub_uint64_t tsc_boot_time;
|
|||
in 32-bit. */
|
||||
grub_uint32_t grub_tsc_rate;
|
||||
|
||||
/* Read the TSC value, which increments with each CPU clock cycle. */
|
||||
static __inline grub_uint64_t
|
||||
grub_get_tsc (void)
|
||||
{
|
||||
grub_uint32_t lo, hi;
|
||||
grub_uint32_t a,b,c,d;
|
||||
|
||||
/* The CPUID instruction is a 'serializing' instruction, and
|
||||
avoids out-of-order execution of the RDTSC instruction. */
|
||||
grub_cpuid (0,a,b,c,d);
|
||||
/* Read TSC value. We cannot use "=A", since this would use
|
||||
%rax on x86_64. */
|
||||
__asm__ __volatile__ ("rdtsc":"=a" (lo), "=d" (hi));
|
||||
|
||||
return (((grub_uint64_t) hi) << 32) | lo;
|
||||
}
|
||||
|
||||
#ifndef GRUB_MACHINE_XEN
|
||||
|
||||
static __inline int
|
||||
grub_cpu_is_tsc_supported (void)
|
||||
{
|
||||
grub_uint32_t a,b,c,d;
|
||||
if (! grub_cpu_is_cpuid_supported ())
|
||||
return 0;
|
||||
|
||||
grub_cpuid(1,a,b,c,d);
|
||||
|
||||
return (d & (1 << 4)) != 0;
|
||||
}
|
||||
|
||||
static void
|
||||
grub_pit_wait (grub_uint16_t tics)
|
||||
{
|
||||
/* Disable timer2 gate and speaker. */
|
||||
grub_outb (grub_inb (GRUB_PIT_SPEAKER_PORT)
|
||||
& ~ (GRUB_PIT_SPK_DATA | GRUB_PIT_SPK_TMR2),
|
||||
GRUB_PIT_SPEAKER_PORT);
|
||||
|
||||
/* Set tics. */
|
||||
grub_outb (GRUB_PIT_CTRL_SELECT_2 | GRUB_PIT_CTRL_READLOAD_WORD,
|
||||
GRUB_PIT_CTRL);
|
||||
grub_outb (tics & 0xff, GRUB_PIT_COUNTER_2);
|
||||
grub_outb (tics >> 8, GRUB_PIT_COUNTER_2);
|
||||
|
||||
/* Enable timer2 gate, keep speaker disabled. */
|
||||
grub_outb ((grub_inb (GRUB_PIT_SPEAKER_PORT) & ~ GRUB_PIT_SPK_DATA)
|
||||
| GRUB_PIT_SPK_TMR2,
|
||||
GRUB_PIT_SPEAKER_PORT);
|
||||
|
||||
/* Wait. */
|
||||
while ((grub_inb (GRUB_PIT_SPEAKER_PORT) & GRUB_PIT_SPK_TMR2_LATCH) == 0x00);
|
||||
|
||||
/* Disable timer2 gate and speaker. */
|
||||
grub_outb (grub_inb (GRUB_PIT_SPEAKER_PORT)
|
||||
& ~ (GRUB_PIT_SPK_DATA | GRUB_PIT_SPK_TMR2),
|
||||
GRUB_PIT_SPEAKER_PORT);
|
||||
}
|
||||
#endif
|
||||
|
||||
static grub_uint64_t
|
||||
grub_tsc_get_time_ms (void)
|
||||
{
|
||||
|
@ -110,52 +43,52 @@ grub_tsc_get_time_ms (void)
|
|||
return ((al * grub_tsc_rate) >> 32) + ah * grub_tsc_rate;
|
||||
}
|
||||
|
||||
#ifndef GRUB_MACHINE_XEN
|
||||
/* Calibrate the TSC based on the RTC. */
|
||||
static void
|
||||
calibrate_tsc (void)
|
||||
static __inline int
|
||||
grub_cpu_is_tsc_supported (void)
|
||||
{
|
||||
/* First calibrate the TSC rate (relative, not absolute time). */
|
||||
grub_uint64_t end_tsc;
|
||||
#ifndef GRUB_MACHINE_XEN
|
||||
grub_uint32_t a,b,c,d;
|
||||
if (! grub_cpu_is_cpuid_supported ())
|
||||
return 0;
|
||||
|
||||
tsc_boot_time = grub_get_tsc ();
|
||||
grub_pit_wait (0xffff);
|
||||
end_tsc = grub_get_tsc ();
|
||||
grub_cpuid(1,a,b,c,d);
|
||||
|
||||
grub_tsc_rate = 0;
|
||||
if (end_tsc > tsc_boot_time)
|
||||
grub_tsc_rate = grub_divmod64 ((55ULL << 32), end_tsc - tsc_boot_time, 0);
|
||||
if (grub_tsc_rate == 0)
|
||||
grub_tsc_rate = 5368;/* 800 MHz */
|
||||
}
|
||||
return (d & (1 << 4)) != 0;
|
||||
#else
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
calibrate_tsc_hardcode (void)
|
||||
{
|
||||
grub_tsc_rate = 5368;/* 800 MHz */
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
grub_tsc_init (void)
|
||||
{
|
||||
#ifdef GRUB_MACHINE_XEN
|
||||
grub_uint64_t t;
|
||||
tsc_boot_time = grub_get_tsc ();
|
||||
t = grub_xen_shared_info->vcpu_info[0].time.tsc_to_system_mul;
|
||||
if (grub_xen_shared_info->vcpu_info[0].time.tsc_shift > 0)
|
||||
t <<= grub_xen_shared_info->vcpu_info[0].time.tsc_shift;
|
||||
else
|
||||
t >>= -grub_xen_shared_info->vcpu_info[0].time.tsc_shift;
|
||||
grub_tsc_rate = grub_divmod64 (t, 1000000, 0);
|
||||
grub_install_get_time_ms (grub_tsc_get_time_ms);
|
||||
#else
|
||||
if (grub_cpu_is_tsc_supported ())
|
||||
{
|
||||
calibrate_tsc ();
|
||||
grub_install_get_time_ms (grub_tsc_get_time_ms);
|
||||
}
|
||||
else
|
||||
if (!grub_cpu_is_tsc_supported ())
|
||||
{
|
||||
#if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_IEEE1275)
|
||||
grub_install_get_time_ms (grub_rtc_get_time_ms);
|
||||
#else
|
||||
grub_fatal ("no TSC found");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
tsc_boot_time = grub_get_tsc ();
|
||||
|
||||
#ifdef GRUB_MACHINE_XEN
|
||||
(void) (grub_tsc_calibrate_from_xen () || calibrate_tsc_hardcode());
|
||||
#elif defined (GRUB_MACHINE_EFI)
|
||||
(void) (grub_tsc_calibrate_from_pit () || grub_tsc_calibrate_from_pmtimer () || grub_tsc_calibrate_from_efi() || calibrate_tsc_hardcode());
|
||||
#elif defined (GRUB_MACHINE_COREBOOT)
|
||||
(void) (grub_tsc_calibrate_from_pmtimer () || grub_tsc_calibrate_from_pit () || calibrate_tsc_hardcode());
|
||||
#else
|
||||
(void) (grub_tsc_calibrate_from_pit () || calibrate_tsc_hardcode());
|
||||
#endif
|
||||
grub_install_get_time_ms (grub_tsc_get_time_ms);
|
||||
}
|
||||
|
|
84
grub-core/kern/i386/tsc_pit.c
Normal file
84
grub-core/kern/i386/tsc_pit.c
Normal file
|
@ -0,0 +1,84 @@
|
|||
/* kern/i386/tsc.c - x86 TSC time source implementation
|
||||
* Requires Pentium or better x86 CPU that supports the RDTSC instruction.
|
||||
* This module uses the PIT to calibrate the TSC to
|
||||
* real time.
|
||||
*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2008 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/time.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/i386/tsc.h>
|
||||
#include <grub/i386/pit.h>
|
||||
#include <grub/cpu/io.h>
|
||||
|
||||
static int
|
||||
grub_pit_wait (void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
/* Disable timer2 gate and speaker. */
|
||||
grub_outb (grub_inb (GRUB_PIT_SPEAKER_PORT)
|
||||
& ~ (GRUB_PIT_SPK_DATA | GRUB_PIT_SPK_TMR2),
|
||||
GRUB_PIT_SPEAKER_PORT);
|
||||
|
||||
/* Set tics. */
|
||||
grub_outb (GRUB_PIT_CTRL_SELECT_2 | GRUB_PIT_CTRL_READLOAD_WORD,
|
||||
GRUB_PIT_CTRL);
|
||||
/* 0xffff ticks: 55ms. */
|
||||
grub_outb (0xff, GRUB_PIT_COUNTER_2);
|
||||
grub_outb (0xff, GRUB_PIT_COUNTER_2);
|
||||
|
||||
/* Enable timer2 gate, keep speaker disabled. */
|
||||
grub_outb ((grub_inb (GRUB_PIT_SPEAKER_PORT) & ~ GRUB_PIT_SPK_DATA)
|
||||
| GRUB_PIT_SPK_TMR2,
|
||||
GRUB_PIT_SPEAKER_PORT);
|
||||
|
||||
if ((grub_inb (GRUB_PIT_SPEAKER_PORT) & GRUB_PIT_SPK_TMR2_LATCH) == 0x00) {
|
||||
ret = 1;
|
||||
/* Wait. */
|
||||
while ((grub_inb (GRUB_PIT_SPEAKER_PORT) & GRUB_PIT_SPK_TMR2_LATCH) == 0x00);
|
||||
}
|
||||
|
||||
/* Disable timer2 gate and speaker. */
|
||||
grub_outb (grub_inb (GRUB_PIT_SPEAKER_PORT)
|
||||
& ~ (GRUB_PIT_SPK_DATA | GRUB_PIT_SPK_TMR2),
|
||||
GRUB_PIT_SPEAKER_PORT);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Calibrate the TSC based on the RTC. */
|
||||
int
|
||||
grub_tsc_calibrate_from_pit (void)
|
||||
{
|
||||
/* First calibrate the TSC rate (relative, not absolute time). */
|
||||
grub_uint64_t start_tsc, end_tsc;
|
||||
|
||||
start_tsc = grub_get_tsc ();
|
||||
if (!grub_pit_wait ())
|
||||
return 0;
|
||||
end_tsc = grub_get_tsc ();
|
||||
|
||||
grub_tsc_rate = 0;
|
||||
if (end_tsc > start_tsc)
|
||||
grub_tsc_rate = grub_divmod64 ((55ULL << 32), end_tsc - start_tsc, 0);
|
||||
if (grub_tsc_rate == 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
160
grub-core/kern/i386/tsc_pmtimer.c
Normal file
160
grub-core/kern/i386/tsc_pmtimer.c
Normal file
|
@ -0,0 +1,160 @@
|
|||
/* kern/i386/tsc.c - x86 TSC time source implementation
|
||||
* Requires Pentium or better x86 CPU that supports the RDTSC instruction.
|
||||
* This module uses the PIT to calibrate the TSC to
|
||||
* real time.
|
||||
*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2008 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/time.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/i386/tsc.h>
|
||||
#include <grub/acpi.h>
|
||||
#include <grub/cpu/io.h>
|
||||
|
||||
static void *
|
||||
grub_acpi_rsdt_find_table (struct grub_acpi_table_header *rsdt, const char *sig)
|
||||
{
|
||||
grub_size_t s;
|
||||
grub_uint32_t *ptr;
|
||||
|
||||
if (!rsdt)
|
||||
return 0;
|
||||
|
||||
if (grub_memcmp (rsdt->signature, "RSDT", 4) != 0)
|
||||
return 0;
|
||||
|
||||
ptr = (grub_uint32_t *) (rsdt + 1);
|
||||
s = (rsdt->length - sizeof (*rsdt)) / sizeof (grub_uint32_t);
|
||||
for (; s; s--, ptr++)
|
||||
{
|
||||
struct grub_acpi_table_header *tbl;
|
||||
tbl = (struct grub_acpi_table_header *) (grub_addr_t) *ptr;
|
||||
if (grub_memcmp (tbl->signature, sig, 4) == 0)
|
||||
return tbl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *
|
||||
grub_acpi_xsdt_find_table (struct grub_acpi_table_header *xsdt, const char *sig)
|
||||
{
|
||||
grub_size_t s;
|
||||
grub_uint64_t *ptr;
|
||||
|
||||
if (!xsdt)
|
||||
return 0;
|
||||
|
||||
if (grub_memcmp (xsdt->signature, "XSDT", 4) != 0)
|
||||
return 0;
|
||||
|
||||
ptr = (grub_uint64_t *) (xsdt + 1);
|
||||
s = (xsdt->length - sizeof (*xsdt)) / sizeof (grub_uint32_t);
|
||||
for (; s; s--, ptr++)
|
||||
{
|
||||
struct grub_acpi_table_header *tbl;
|
||||
#if GRUB_CPU_SIZEOF_VOID_P != 8
|
||||
if (*ptr >> 32)
|
||||
continue;
|
||||
#endif
|
||||
tbl = (struct grub_acpi_table_header *) (grub_addr_t) *ptr;
|
||||
if (grub_memcmp (tbl->signature, sig, 4) == 0)
|
||||
return tbl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct grub_acpi_fadt *
|
||||
grub_acpi_find_fadt (void)
|
||||
{
|
||||
struct grub_acpi_fadt *fadt = 0;
|
||||
struct grub_acpi_rsdp_v10 *rsdpv1;
|
||||
struct grub_acpi_rsdp_v20 *rsdpv2;
|
||||
rsdpv1 = grub_machine_acpi_get_rsdpv1 ();
|
||||
if (rsdpv1)
|
||||
fadt = grub_acpi_rsdt_find_table ((struct grub_acpi_table_header *)
|
||||
(grub_addr_t) rsdpv1->rsdt_addr,
|
||||
GRUB_ACPI_FADT_SIGNATURE);
|
||||
if (fadt)
|
||||
return fadt;
|
||||
rsdpv2 = grub_machine_acpi_get_rsdpv2 ();
|
||||
if (rsdpv2)
|
||||
fadt = grub_acpi_rsdt_find_table ((struct grub_acpi_table_header *)
|
||||
(grub_addr_t) rsdpv2->rsdpv1.rsdt_addr,
|
||||
GRUB_ACPI_FADT_SIGNATURE);
|
||||
if (fadt)
|
||||
return fadt;
|
||||
if (rsdpv2
|
||||
#if GRUB_CPU_SIZEOF_VOID_P != 8
|
||||
&& !(rsdpv2->xsdt_addr >> 32)
|
||||
#endif
|
||||
)
|
||||
fadt = grub_acpi_xsdt_find_table ((struct grub_acpi_table_header *)
|
||||
(grub_addr_t) rsdpv2->xsdt_addr,
|
||||
GRUB_ACPI_FADT_SIGNATURE);
|
||||
if (fadt)
|
||||
return fadt;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
grub_tsc_calibrate_from_pmtimer (void)
|
||||
{
|
||||
grub_uint32_t start;
|
||||
grub_uint32_t last;
|
||||
grub_uint32_t cur, end;
|
||||
struct grub_acpi_fadt *fadt;
|
||||
grub_port_t p;
|
||||
grub_uint64_t start_tsc;
|
||||
grub_uint64_t end_tsc;
|
||||
int num_iter = 0;
|
||||
|
||||
fadt = grub_acpi_find_fadt ();
|
||||
if (!fadt)
|
||||
return 0;
|
||||
p = fadt->pmtimer;
|
||||
if (!p)
|
||||
return 0;
|
||||
|
||||
start = grub_inl (p) & 0xffffff;
|
||||
last = start;
|
||||
/* It's 3.579545 MHz clock. Wait 1 ms. */
|
||||
end = start + 3580;
|
||||
start_tsc = grub_get_tsc ();
|
||||
while (1)
|
||||
{
|
||||
cur = grub_inl (p) & 0xffffff;
|
||||
if (cur < last)
|
||||
cur |= 0x1000000;
|
||||
num_iter++;
|
||||
if (cur >= end)
|
||||
{
|
||||
end_tsc = grub_get_tsc ();
|
||||
grub_tsc_rate = grub_divmod64 ((1ULL << 32), end_tsc - start_tsc, 0);
|
||||
return 1;
|
||||
}
|
||||
/* Check for broken PM timer.
|
||||
50000000 TSCs is between 5 ms (10GHz) and 200 ms (250 MHz)
|
||||
if after this time we still don't have 1 ms on pmtimer, then
|
||||
pmtimer is broken.
|
||||
*/
|
||||
if ((num_iter & 0xffffff) == 0 && grub_get_tsc () - start_tsc > 5000000) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
40
grub-core/kern/i386/xen/tsc.c
Normal file
40
grub-core/kern/i386/xen/tsc.c
Normal file
|
@ -0,0 +1,40 @@
|
|||
/* kern/i386/tsc.c - x86 TSC time source implementation
|
||||
* Requires Pentium or better x86 CPU that supports the RDTSC instruction.
|
||||
* This module uses the PIT to calibrate the TSC to
|
||||
* real time.
|
||||
*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2008 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/time.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/i386/tsc.h>
|
||||
#include <grub/xen.h>
|
||||
|
||||
int
|
||||
grub_tsc_calibrate_from_xen (void)
|
||||
{
|
||||
grub_uint64_t t;
|
||||
t = grub_xen_shared_info->vcpu_info[0].time.tsc_to_system_mul;
|
||||
if (grub_xen_shared_info->vcpu_info[0].time.tsc_shift > 0)
|
||||
t <<= grub_xen_shared_info->vcpu_info[0].time.tsc_shift;
|
||||
else
|
||||
t >>= -grub_xen_shared_info->vcpu_info[0].time.tsc_shift;
|
||||
grub_tsc_rate = grub_divmod64 (t, 1000000, 0);
|
||||
return 1;
|
||||
}
|
|
@ -166,7 +166,7 @@ heap_init (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type,
|
|||
{
|
||||
unsigned long *total = data;
|
||||
|
||||
if (type != 1)
|
||||
if (type != GRUB_MEMORY_AVAILABLE)
|
||||
return 0;
|
||||
|
||||
if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PRE1_5M_CLAIM))
|
||||
|
|
|
@ -138,6 +138,10 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
|
|||
sym = (Elf_Sym *) ((char *) mod->symtab
|
||||
+ mod->symsize * ELF_R_SYM (rel->r_info));
|
||||
sym_value = sym->st_value;
|
||||
if (s->sh_type == SHT_RELA)
|
||||
{
|
||||
sym_value += ((Elf_Rela *) rel)->r_addend;
|
||||
}
|
||||
if (sym_value == (grub_addr_t) &__gnu_local_gp_dummy)
|
||||
sym_value = (grub_addr_t) mod->got;
|
||||
else if (sym_value == (grub_addr_t) &_gp_disp_dummy)
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <grub/machine/memory.h>
|
||||
#include <grub/machine/kernel.h>
|
||||
#include <grub/offsets.h>
|
||||
#include <grub/mips/asm.h>
|
||||
|
||||
#define BASE_ADDR 8
|
||||
|
||||
|
@ -95,8 +96,8 @@ cont:
|
|||
modulesmovcont:
|
||||
beq $t3, $0, modulesmovdone
|
||||
nop
|
||||
lb $t4, 0($t2)
|
||||
sb $t4, 0($t1)
|
||||
lb GRUB_ASM_T4, 0($t2)
|
||||
sb GRUB_ASM_T4, 0($t1)
|
||||
addiu $t2, $t2, -1
|
||||
addiu $t1, $t1, -1
|
||||
b modulesmovcont
|
||||
|
|
|
@ -268,6 +268,7 @@ grub_parser_execute (char *source)
|
|||
grub_parser_execute_getline (&line, 0, &source);
|
||||
grub_rescue_parse_line (line, grub_parser_execute_getline, &source);
|
||||
grub_free (line);
|
||||
grub_print_error ();
|
||||
}
|
||||
|
||||
return grub_errno;
|
||||
|
|
|
@ -470,7 +470,8 @@ grub_password_get (char buf[], unsigned buf_size)
|
|||
|
||||
if (key == '\b')
|
||||
{
|
||||
cur_len--;
|
||||
if (cur_len)
|
||||
cur_len--;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,9 @@
|
|||
#include <grub/fdt.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/dl.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
#define FDT_SUPPORTED_VERSION 17
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include <grub/symbol.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/mips/asm.h>
|
||||
|
||||
.file "setjmp.S"
|
||||
|
||||
|
@ -29,40 +30,42 @@ GRUB_MOD_LICENSE "GPLv3+"
|
|||
* int grub_setjmp (grub_jmp_buf env)
|
||||
*/
|
||||
FUNCTION(grub_setjmp)
|
||||
sw $s0, 0($a0)
|
||||
sw $s1, 4($a0)
|
||||
sw $s2, 8($a0)
|
||||
sw $s3, 12($a0)
|
||||
sw $s4, 16($a0)
|
||||
sw $s5, 20($a0)
|
||||
sw $s6, 24($a0)
|
||||
sw $s7, 28($a0)
|
||||
sw $s8, 32($a0)
|
||||
sw $gp, 36($a0)
|
||||
sw $sp, 40($a0)
|
||||
sw $ra, 44($a0)
|
||||
GRUB_ASM_REG_S $s0, 0($a0)
|
||||
GRUB_ASM_REG_S $s1, 8($a0)
|
||||
GRUB_ASM_REG_S $s2, 16($a0)
|
||||
GRUB_ASM_REG_S $s3, 24($a0)
|
||||
GRUB_ASM_REG_S $s4, 32($a0)
|
||||
GRUB_ASM_REG_S $s5, 40($a0)
|
||||
GRUB_ASM_REG_S $s6, 48($a0)
|
||||
GRUB_ASM_REG_S $s7, 56($a0)
|
||||
GRUB_ASM_REG_S $s8, 64($a0)
|
||||
GRUB_ASM_REG_S $gp, 72($a0)
|
||||
GRUB_ASM_REG_S $sp, 80($a0)
|
||||
GRUB_ASM_REG_S $ra, 88($a0)
|
||||
move $v0, $zero
|
||||
move $v1, $zero
|
||||
jr $ra
|
||||
nop
|
||||
/*
|
||||
* int grub_longjmp (grub_jmp_buf env, int val)
|
||||
*/
|
||||
FUNCTION(grub_longjmp)
|
||||
lw $s0, 0($a0)
|
||||
lw $s1, 4($a0)
|
||||
lw $s2, 8($a0)
|
||||
lw $s3, 12($a0)
|
||||
lw $s4, 16($a0)
|
||||
lw $s5, 20($a0)
|
||||
lw $s6, 24($a0)
|
||||
lw $s7, 28($a0)
|
||||
lw $s8, 32($a0)
|
||||
lw $gp, 36($a0)
|
||||
lw $sp, 40($a0)
|
||||
lw $ra, 44($a0)
|
||||
GRUB_ASM_REG_L $s0, 0($a0)
|
||||
GRUB_ASM_REG_L $s1, 8($a0)
|
||||
GRUB_ASM_REG_L $s2, 16($a0)
|
||||
GRUB_ASM_REG_L $s3, 24($a0)
|
||||
GRUB_ASM_REG_L $s4, 32($a0)
|
||||
GRUB_ASM_REG_L $s5, 40($a0)
|
||||
GRUB_ASM_REG_L $s6, 48($a0)
|
||||
GRUB_ASM_REG_L $s7, 56($a0)
|
||||
GRUB_ASM_REG_L $s8, 64($a0)
|
||||
GRUB_ASM_REG_L $gp, 72($a0)
|
||||
GRUB_ASM_REG_L $sp, 80($a0)
|
||||
GRUB_ASM_REG_L $ra, 88($a0)
|
||||
move $v0, $a1
|
||||
bne $v0, $zero, 1f
|
||||
addiu $v0, $v0, 1
|
||||
1:
|
||||
move $v1, $zero
|
||||
jr $ra
|
||||
nop
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <grub/dl.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/normal.h>
|
||||
#include <grub/net.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
|
@ -70,7 +71,15 @@ grub_file_progress_hook_real (grub_disk_addr_t sector __attribute__ ((unused)),
|
|||
percent = grub_divmod64 (100 * file->progress_offset,
|
||||
file->size, 0);
|
||||
|
||||
partial_file_name = grub_strrchr (file->name, '/');
|
||||
/* grub_net_fs_open() saves off partial file structure before name is initialized.
|
||||
It already saves passed file name in net structure so just use it in this case.
|
||||
*/
|
||||
if (file->device->net)
|
||||
partial_file_name = grub_strrchr (file->device->net->name, '/');
|
||||
else if (file->name) /* grub_file_open() may leave it as NULL */
|
||||
partial_file_name = grub_strrchr (file->name, '/');
|
||||
else
|
||||
partial_file_name = NULL;
|
||||
if (partial_file_name)
|
||||
partial_file_name++;
|
||||
else
|
||||
|
|
185
grub-core/loader/arm64/fdt.c
Normal file
185
grub-core/loader/arm64/fdt.c
Normal file
|
@ -0,0 +1,185 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2013-2015 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/fdt.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/cpu/fdtload.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/efi/efi.h>
|
||||
|
||||
static void *loaded_fdt;
|
||||
static void *fdt;
|
||||
|
||||
static void *
|
||||
get_firmware_fdt (void)
|
||||
{
|
||||
grub_efi_configuration_table_t *tables;
|
||||
grub_efi_guid_t fdt_guid = GRUB_EFI_DEVICE_TREE_GUID;
|
||||
void *firmware_fdt = NULL;
|
||||
unsigned int i;
|
||||
|
||||
/* Look for FDT in UEFI config tables. */
|
||||
tables = grub_efi_system_table->configuration_table;
|
||||
|
||||
for (i = 0; i < grub_efi_system_table->num_table_entries; i++)
|
||||
if (grub_memcmp (&tables[i].vendor_guid, &fdt_guid, sizeof (fdt_guid)) == 0)
|
||||
{
|
||||
firmware_fdt = tables[i].vendor_table;
|
||||
grub_dprintf ("linux", "found registered FDT @ %p\n", firmware_fdt);
|
||||
break;
|
||||
}
|
||||
|
||||
return firmware_fdt;
|
||||
}
|
||||
|
||||
void *
|
||||
grub_fdt_load (grub_size_t additional_size)
|
||||
{
|
||||
void *raw_fdt;
|
||||
grub_size_t size;
|
||||
|
||||
if (fdt)
|
||||
{
|
||||
size = GRUB_EFI_BYTES_TO_PAGES (grub_fdt_get_totalsize (fdt));
|
||||
grub_efi_free_pages ((grub_efi_physical_address_t) fdt, size);
|
||||
}
|
||||
|
||||
if (loaded_fdt)
|
||||
raw_fdt = loaded_fdt;
|
||||
else
|
||||
raw_fdt = get_firmware_fdt();
|
||||
|
||||
size =
|
||||
raw_fdt ? grub_fdt_get_totalsize (raw_fdt) : GRUB_FDT_EMPTY_TREE_SZ;
|
||||
size += additional_size;
|
||||
|
||||
grub_dprintf ("linux", "allocating %ld bytes for fdt\n", size);
|
||||
fdt = grub_efi_allocate_pages (0, GRUB_EFI_BYTES_TO_PAGES (size));
|
||||
if (!fdt)
|
||||
return NULL;
|
||||
|
||||
if (raw_fdt)
|
||||
{
|
||||
grub_memmove (fdt, raw_fdt, size);
|
||||
grub_fdt_set_totalsize (fdt, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_fdt_create_empty_tree (fdt, size);
|
||||
}
|
||||
return fdt;
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
grub_fdt_install (void)
|
||||
{
|
||||
grub_efi_boot_services_t *b;
|
||||
grub_efi_guid_t fdt_guid = GRUB_EFI_DEVICE_TREE_GUID;
|
||||
grub_efi_status_t status;
|
||||
|
||||
b = grub_efi_system_table->boot_services;
|
||||
status = b->install_configuration_table (&fdt_guid, fdt);
|
||||
if (status != GRUB_EFI_SUCCESS)
|
||||
return grub_error (GRUB_ERR_IO, "failed to install FDT");
|
||||
|
||||
grub_dprintf ("fdt", "Installed/updated FDT configuration table @ %p\n",
|
||||
fdt);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
void
|
||||
grub_fdt_unload (void) {
|
||||
if (!fdt) {
|
||||
return;
|
||||
}
|
||||
grub_efi_free_pages ((grub_efi_physical_address_t) fdt,
|
||||
GRUB_EFI_BYTES_TO_PAGES (grub_fdt_get_totalsize (fdt)));
|
||||
fdt = NULL;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_devicetree (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc, char *argv[])
|
||||
{
|
||||
grub_file_t dtb;
|
||||
void *blob = NULL;
|
||||
int size;
|
||||
|
||||
if (loaded_fdt)
|
||||
grub_free (loaded_fdt);
|
||||
loaded_fdt = NULL;
|
||||
|
||||
/* No arguments means "use firmware FDT". */
|
||||
if (argc == 0)
|
||||
{
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
dtb = grub_file_open (argv[0]);
|
||||
if (!dtb)
|
||||
goto out;
|
||||
|
||||
size = grub_file_size (dtb);
|
||||
blob = grub_malloc (size);
|
||||
if (!blob)
|
||||
goto out;
|
||||
|
||||
if (grub_file_read (dtb, blob, size) < size)
|
||||
{
|
||||
if (!grub_errno)
|
||||
grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), argv[0]);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (grub_fdt_check_header (blob, size) != 0)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_OS, N_("invalid device tree"));
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
if (dtb)
|
||||
grub_file_close (dtb);
|
||||
|
||||
if (blob)
|
||||
{
|
||||
if (grub_errno == GRUB_ERR_NONE)
|
||||
loaded_fdt = blob;
|
||||
else
|
||||
grub_free (blob);
|
||||
}
|
||||
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static grub_command_t cmd_devicetree;
|
||||
|
||||
GRUB_MOD_INIT (fdt)
|
||||
{
|
||||
cmd_devicetree =
|
||||
grub_register_command ("devicetree", grub_cmd_devicetree, 0,
|
||||
N_("Load DTB file."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI (fdt)
|
||||
{
|
||||
grub_unregister_command (cmd_devicetree);
|
||||
}
|
|
@ -26,6 +26,7 @@
|
|||
#include <grub/mm.h>
|
||||
#include <grub/types.h>
|
||||
#include <grub/cpu/linux.h>
|
||||
#include <grub/cpu/fdtload.h>
|
||||
#include <grub/efi/efi.h>
|
||||
#include <grub/efi/pe32.h>
|
||||
#include <grub/i18n.h>
|
||||
|
@ -45,69 +46,6 @@ static grub_uint32_t cmdline_size;
|
|||
static grub_addr_t initrd_start;
|
||||
static grub_addr_t initrd_end;
|
||||
|
||||
static void *loaded_fdt;
|
||||
static void *fdt;
|
||||
|
||||
static void *
|
||||
get_firmware_fdt (void)
|
||||
{
|
||||
grub_efi_configuration_table_t *tables;
|
||||
grub_efi_guid_t fdt_guid = GRUB_EFI_DEVICE_TREE_GUID;
|
||||
void *firmware_fdt = NULL;
|
||||
unsigned int i;
|
||||
|
||||
/* Look for FDT in UEFI config tables. */
|
||||
tables = grub_efi_system_table->configuration_table;
|
||||
|
||||
for (i = 0; i < grub_efi_system_table->num_table_entries; i++)
|
||||
if (grub_memcmp (&tables[i].vendor_guid, &fdt_guid, sizeof (fdt_guid)) == 0)
|
||||
{
|
||||
firmware_fdt = tables[i].vendor_table;
|
||||
grub_dprintf ("linux", "found registered FDT @ %p\n", firmware_fdt);
|
||||
break;
|
||||
}
|
||||
|
||||
return firmware_fdt;
|
||||
}
|
||||
|
||||
void *
|
||||
grub_linux_get_fdt (void)
|
||||
{
|
||||
void *raw_fdt;
|
||||
grub_size_t size;
|
||||
|
||||
if (fdt)
|
||||
{
|
||||
size = BYTES_TO_PAGES (grub_fdt_get_totalsize (fdt));
|
||||
grub_efi_free_pages ((grub_efi_physical_address_t) fdt, size);
|
||||
}
|
||||
|
||||
if (loaded_fdt)
|
||||
raw_fdt = loaded_fdt;
|
||||
else
|
||||
raw_fdt = get_firmware_fdt();
|
||||
|
||||
size =
|
||||
raw_fdt ? grub_fdt_get_totalsize (raw_fdt) : GRUB_FDT_EMPTY_TREE_SZ;
|
||||
size += 0x400;
|
||||
|
||||
grub_dprintf ("linux", "allocating %ld bytes for fdt\n", size);
|
||||
fdt = grub_efi_allocate_pages (0, BYTES_TO_PAGES (size));
|
||||
if (!fdt)
|
||||
return NULL;
|
||||
|
||||
if (raw_fdt)
|
||||
{
|
||||
grub_memmove (fdt, raw_fdt, size);
|
||||
grub_fdt_set_totalsize (fdt, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_fdt_create_empty_tree (fdt, size);
|
||||
}
|
||||
return fdt;
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
grub_arm64_uefi_check_image (struct grub_arm64_linux_kernel_header * lh)
|
||||
{
|
||||
|
@ -129,12 +67,13 @@ grub_arm64_uefi_check_image (struct grub_arm64_linux_kernel_header * lh)
|
|||
static grub_err_t
|
||||
finalize_params_linux (void)
|
||||
{
|
||||
grub_efi_boot_services_t *b;
|
||||
grub_efi_guid_t fdt_guid = GRUB_EFI_DEVICE_TREE_GUID;
|
||||
grub_efi_status_t status;
|
||||
int node, retval;
|
||||
|
||||
if (!grub_linux_get_fdt ())
|
||||
void *fdt;
|
||||
|
||||
fdt = grub_fdt_load (0x400);
|
||||
|
||||
if (!fdt)
|
||||
goto failure;
|
||||
|
||||
node = grub_fdt_find_subnode (fdt, 0, "chosen");
|
||||
|
@ -160,82 +99,16 @@ finalize_params_linux (void)
|
|||
goto failure;
|
||||
}
|
||||
|
||||
b = grub_efi_system_table->boot_services;
|
||||
status = b->install_configuration_table (&fdt_guid, fdt);
|
||||
if (status != GRUB_EFI_SUCCESS)
|
||||
if (grub_fdt_install() != GRUB_ERR_NONE)
|
||||
goto failure;
|
||||
|
||||
grub_dprintf ("linux", "Installed/updated FDT configuration table @ %p\n",
|
||||
fdt);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
|
||||
failure:
|
||||
grub_efi_free_pages ((grub_efi_physical_address_t) fdt,
|
||||
BYTES_TO_PAGES (grub_fdt_get_totalsize (fdt)));
|
||||
fdt = NULL;
|
||||
grub_fdt_unload();
|
||||
return grub_error(GRUB_ERR_BAD_OS, "failed to install/update FDT");
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_devicetree (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc, char *argv[])
|
||||
{
|
||||
grub_file_t dtb;
|
||||
void *blob = NULL;
|
||||
int size;
|
||||
|
||||
if (!loaded)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
N_("you need to load the kernel first"));
|
||||
return GRUB_ERR_BAD_OS;
|
||||
}
|
||||
|
||||
if (argc != 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
|
||||
|
||||
if (loaded_fdt)
|
||||
grub_free (loaded_fdt);
|
||||
loaded_fdt = NULL;
|
||||
|
||||
dtb = grub_file_open (argv[0]);
|
||||
if (!dtb)
|
||||
goto out;
|
||||
|
||||
size = grub_file_size (dtb);
|
||||
blob = grub_malloc (size);
|
||||
if (!blob)
|
||||
goto out;
|
||||
|
||||
if (grub_file_read (dtb, blob, size) < size)
|
||||
{
|
||||
if (!grub_errno)
|
||||
grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), argv[0]);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (grub_fdt_check_header (blob, size) != 0)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_OS, N_("invalid device tree"));
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
if (dtb)
|
||||
grub_file_close (dtb);
|
||||
|
||||
if (blob)
|
||||
{
|
||||
if (grub_errno == GRUB_ERR_NONE)
|
||||
loaded_fdt = blob;
|
||||
else
|
||||
grub_free (blob);
|
||||
}
|
||||
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
grub_arm64_uefi_boot_image (grub_addr_t addr, grub_size_t size, char *args)
|
||||
{
|
||||
|
@ -276,7 +149,7 @@ grub_arm64_uefi_boot_image (grub_addr_t addr, grub_size_t size, char *args)
|
|||
(grub_strlen (args) + 1) * sizeof (grub_efi_char16_t);
|
||||
loaded_image->load_options =
|
||||
grub_efi_allocate_pages (0,
|
||||
BYTES_TO_PAGES (loaded_image->load_options_size));
|
||||
GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size));
|
||||
if (!loaded_image->load_options)
|
||||
return grub_errno;
|
||||
|
||||
|
@ -290,7 +163,7 @@ grub_arm64_uefi_boot_image (grub_addr_t addr, grub_size_t size, char *args)
|
|||
/* When successful, not reached */
|
||||
b->unload_image (image_handle);
|
||||
grub_efi_free_pages ((grub_efi_physical_address_t) loaded_image->load_options,
|
||||
BYTES_TO_PAGES (loaded_image->load_options_size));
|
||||
GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size));
|
||||
|
||||
return grub_errno;
|
||||
}
|
||||
|
@ -312,16 +185,13 @@ grub_linux_unload (void)
|
|||
loaded = 0;
|
||||
if (initrd_start)
|
||||
grub_efi_free_pages ((grub_efi_physical_address_t) initrd_start,
|
||||
BYTES_TO_PAGES (initrd_end - initrd_start));
|
||||
GRUB_EFI_BYTES_TO_PAGES (initrd_end - initrd_start));
|
||||
initrd_start = initrd_end = 0;
|
||||
grub_free (linux_args);
|
||||
if (kernel_addr)
|
||||
grub_efi_free_pages ((grub_efi_physical_address_t) kernel_addr,
|
||||
BYTES_TO_PAGES (kernel_size));
|
||||
if (fdt)
|
||||
grub_efi_free_pages ((grub_efi_physical_address_t) fdt,
|
||||
BYTES_TO_PAGES (grub_fdt_get_totalsize (fdt)));
|
||||
|
||||
GRUB_EFI_BYTES_TO_PAGES (kernel_size));
|
||||
grub_fdt_unload ();
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
|
@ -352,7 +222,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
|
|||
initrd_size = grub_get_initrd_size (&initrd_ctx);
|
||||
grub_dprintf ("linux", "Loading initrd\n");
|
||||
|
||||
initrd_pages = (BYTES_TO_PAGES (initrd_size));
|
||||
initrd_pages = (GRUB_EFI_BYTES_TO_PAGES (initrd_size));
|
||||
initrd_mem = grub_efi_allocate_pages (0, initrd_pages);
|
||||
if (!initrd_mem)
|
||||
{
|
||||
|
@ -407,9 +277,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
|
|||
grub_loader_unset();
|
||||
|
||||
grub_dprintf ("linux", "kernel file size: %lld\n", (long long) kernel_size);
|
||||
kernel_addr = grub_efi_allocate_pages (0, BYTES_TO_PAGES (kernel_size));
|
||||
kernel_addr = grub_efi_allocate_pages (0, GRUB_EFI_BYTES_TO_PAGES (kernel_size));
|
||||
grub_dprintf ("linux", "kernel numpages: %lld\n",
|
||||
(long long) BYTES_TO_PAGES (kernel_size));
|
||||
(long long) GRUB_EFI_BYTES_TO_PAGES (kernel_size));
|
||||
if (!kernel_addr)
|
||||
{
|
||||
grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
|
||||
|
@ -460,13 +330,13 @@ fail:
|
|||
|
||||
if (kernel_addr && !loaded)
|
||||
grub_efi_free_pages ((grub_efi_physical_address_t) kernel_addr,
|
||||
BYTES_TO_PAGES (kernel_size));
|
||||
GRUB_EFI_BYTES_TO_PAGES (kernel_size));
|
||||
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
|
||||
static grub_command_t cmd_linux, cmd_initrd, cmd_devicetree;
|
||||
static grub_command_t cmd_linux, cmd_initrd;
|
||||
|
||||
GRUB_MOD_INIT (linux)
|
||||
{
|
||||
|
@ -474,9 +344,6 @@ GRUB_MOD_INIT (linux)
|
|||
N_("Load Linux."));
|
||||
cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd, 0,
|
||||
N_("Load initrd."));
|
||||
cmd_devicetree =
|
||||
grub_register_command ("devicetree", grub_cmd_devicetree, 0,
|
||||
N_("Load DTB file."));
|
||||
my_mod = mod;
|
||||
}
|
||||
|
||||
|
@ -484,5 +351,4 @@ GRUB_MOD_FINI (linux)
|
|||
{
|
||||
grub_unregister_command (cmd_linux);
|
||||
grub_unregister_command (cmd_initrd);
|
||||
grub_unregister_command (cmd_devicetree);
|
||||
}
|
||||
|
|
587
grub-core/loader/arm64/xen_boot.c
Normal file
587
grub-core/loader/arm64/xen_boot.c
Normal file
|
@ -0,0 +1,587 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2014 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/cache.h>
|
||||
#include <grub/charset.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/fdt.h>
|
||||
#include <grub/list.h>
|
||||
#include <grub/loader.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/types.h>
|
||||
#include <grub/cpu/fdtload.h>
|
||||
#include <grub/cpu/linux.h>
|
||||
#include <grub/efi/efi.h>
|
||||
#include <grub/efi/pe32.h> /* required by struct xen_hypervisor_header */
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/lib/cmdline.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
#define XEN_HYPERVISOR_NAME "xen_hypervisor"
|
||||
|
||||
#define MODULE_DEFAULT_ALIGN (0x0)
|
||||
#define MODULE_IMAGE_MIN_ALIGN MODULE_DEFAULT_ALIGN
|
||||
#define MODULE_INITRD_MIN_ALIGN MODULE_DEFAULT_ALIGN
|
||||
#define MODULE_XSM_MIN_ALIGN MODULE_DEFAULT_ALIGN
|
||||
#define MODULE_CUSTOM_MIN_ALIGN MODULE_DEFAULT_ALIGN
|
||||
|
||||
#define MODULE_IMAGE_COMPATIBLE "multiboot,kernel\0multiboot,module"
|
||||
#define MODULE_INITRD_COMPATIBLE "multiboot,ramdisk\0multiboot,module"
|
||||
#define MODULE_XSM_COMPATIBLE "xen,xsm-policy\0multiboot,module"
|
||||
#define MODULE_CUSTOM_COMPATIBLE "multiboot,module"
|
||||
|
||||
/* This maximum size is defined in Power.org ePAPR V1.1
|
||||
* https://www.power.org/documentation/epapr-version-1-1/
|
||||
* 2.2.1.1 Node Name Requirements
|
||||
* node-name@unit-address
|
||||
* 31 + 1(@) + 16(64bit address in hex format) + 1(\0) = 49
|
||||
*/
|
||||
#define FDT_NODE_NAME_MAX_SIZE (49)
|
||||
|
||||
struct compat_string_struct
|
||||
{
|
||||
grub_size_t size;
|
||||
const char *compat_string;
|
||||
};
|
||||
typedef struct compat_string_struct compat_string_struct_t;
|
||||
#define FDT_COMPATIBLE(x) {.size = sizeof(x), .compat_string = (x)}
|
||||
|
||||
enum module_type
|
||||
{
|
||||
MODULE_IMAGE,
|
||||
MODULE_INITRD,
|
||||
MODULE_XSM,
|
||||
MODULE_CUSTOM
|
||||
};
|
||||
typedef enum module_type module_type_t;
|
||||
|
||||
struct fdt_node_info
|
||||
{
|
||||
module_type_t type;
|
||||
|
||||
const char *compat_string;
|
||||
grub_size_t compat_string_size;
|
||||
};
|
||||
|
||||
struct xen_hypervisor_header
|
||||
{
|
||||
struct grub_arm64_linux_kernel_header efi_head;
|
||||
|
||||
/* This is always PE\0\0. */
|
||||
grub_uint8_t signature[GRUB_PE32_SIGNATURE_SIZE];
|
||||
/* The COFF file header. */
|
||||
struct grub_pe32_coff_header coff_header;
|
||||
/* The Optional header. */
|
||||
struct grub_pe64_optional_header optional_header;
|
||||
};
|
||||
|
||||
struct xen_boot_binary
|
||||
{
|
||||
struct xen_boot_binary *next;
|
||||
struct xen_boot_binary **prev;
|
||||
const char *name;
|
||||
|
||||
grub_addr_t start;
|
||||
grub_size_t size;
|
||||
grub_size_t align;
|
||||
|
||||
char *cmdline;
|
||||
int cmdline_size;
|
||||
|
||||
struct fdt_node_info node_info;
|
||||
};
|
||||
|
||||
static grub_dl_t my_mod;
|
||||
|
||||
static int loaded;
|
||||
|
||||
static struct xen_boot_binary *xen_hypervisor;
|
||||
static struct xen_boot_binary *module_head;
|
||||
static const grub_size_t module_default_align[] = {
|
||||
MODULE_IMAGE_MIN_ALIGN,
|
||||
MODULE_INITRD_MIN_ALIGN,
|
||||
MODULE_XSM_MIN_ALIGN,
|
||||
MODULE_CUSTOM_MIN_ALIGN
|
||||
};
|
||||
|
||||
static const compat_string_struct_t default_compat_string[] = {
|
||||
FDT_COMPATIBLE (MODULE_IMAGE_COMPATIBLE),
|
||||
FDT_COMPATIBLE (MODULE_INITRD_COMPATIBLE),
|
||||
FDT_COMPATIBLE (MODULE_XSM_COMPATIBLE),
|
||||
FDT_COMPATIBLE (MODULE_CUSTOM_COMPATIBLE)
|
||||
};
|
||||
|
||||
static __inline grub_addr_t
|
||||
xen_boot_address_align (grub_addr_t start, grub_size_t align)
|
||||
{
|
||||
return (align ? (ALIGN_UP (start, align)) : start);
|
||||
}
|
||||
|
||||
/* set module type according to command name. */
|
||||
static grub_err_t
|
||||
set_module_type (grub_command_t cmd, struct xen_boot_binary *module)
|
||||
{
|
||||
if (!grub_strcmp (cmd->name, "xen_linux"))
|
||||
module->node_info.type = MODULE_IMAGE;
|
||||
else if (!grub_strcmp (cmd->name, "xen_initrd"))
|
||||
module->node_info.type = MODULE_INITRD;
|
||||
else if (!grub_strcmp (cmd->name, "xen_xsm"))
|
||||
module->node_info.type = MODULE_XSM;
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
prepare_xen_hypervisor_params (void *xen_boot_fdt)
|
||||
{
|
||||
int chosen_node = 0;
|
||||
int retval;
|
||||
|
||||
chosen_node = grub_fdt_find_subnode (xen_boot_fdt, 0, "chosen");
|
||||
if (chosen_node < 0)
|
||||
chosen_node = grub_fdt_add_subnode (xen_boot_fdt, 0, "chosen");
|
||||
if (chosen_node < 1)
|
||||
return grub_error (GRUB_ERR_IO, "failed to get chosen node in FDT");
|
||||
|
||||
grub_dprintf ("xen_loader",
|
||||
"Xen Hypervisor cmdline : %s @ %p size:%d\n",
|
||||
xen_hypervisor->cmdline, xen_hypervisor->cmdline,
|
||||
xen_hypervisor->cmdline_size);
|
||||
|
||||
retval = grub_fdt_set_prop (xen_boot_fdt, chosen_node, "bootargs",
|
||||
xen_hypervisor->cmdline,
|
||||
xen_hypervisor->cmdline_size);
|
||||
if (retval)
|
||||
return grub_error (GRUB_ERR_IO, "failed to install/update FDT");
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
prepare_xen_module_params (struct xen_boot_binary *module, void *xen_boot_fdt)
|
||||
{
|
||||
int retval, chosen_node = 0, module_node = 0;
|
||||
char module_name[FDT_NODE_NAME_MAX_SIZE];
|
||||
|
||||
retval = grub_snprintf (module_name, FDT_NODE_NAME_MAX_SIZE, "module@%lx",
|
||||
xen_boot_address_align (module->start,
|
||||
module->align));
|
||||
grub_dprintf ("xen_loader", "Module node name %s \n", module_name);
|
||||
|
||||
if (retval < (int) sizeof ("module@"))
|
||||
return grub_error (GRUB_ERR_IO, N_("failed to get FDT"));
|
||||
|
||||
chosen_node = grub_fdt_find_subnode (xen_boot_fdt, 0, "chosen");
|
||||
if (chosen_node < 0)
|
||||
chosen_node = grub_fdt_add_subnode (xen_boot_fdt, 0, "chosen");
|
||||
if (chosen_node < 1)
|
||||
return grub_error (GRUB_ERR_IO, "failed to get chosen node in FDT");
|
||||
|
||||
module_node =
|
||||
grub_fdt_find_subnode (xen_boot_fdt, chosen_node, module_name);
|
||||
if (module_node < 0)
|
||||
module_node =
|
||||
grub_fdt_add_subnode (xen_boot_fdt, chosen_node, module_name);
|
||||
|
||||
retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "compatible",
|
||||
module->node_info.compat_string,
|
||||
(grub_uint32_t) module->
|
||||
node_info.compat_string_size);
|
||||
if (retval)
|
||||
return grub_error (GRUB_ERR_IO, "failed to update FDT");
|
||||
|
||||
grub_dprintf ("xen_loader", "Module %s compatible = %s size = 0x%lx\n",
|
||||
module->name, module->node_info.compat_string,
|
||||
module->node_info.compat_string_size);
|
||||
|
||||
retval = grub_fdt_set_reg64 (xen_boot_fdt, module_node,
|
||||
xen_boot_address_align (module->start,
|
||||
module->align),
|
||||
module->size);
|
||||
if (retval)
|
||||
return grub_error (GRUB_ERR_IO, "failed to update FDT");
|
||||
|
||||
if (module->cmdline && module->cmdline_size > 0)
|
||||
{
|
||||
grub_dprintf ("xen_loader",
|
||||
"Module %s cmdline : %s @ %p size:%d\n", module->name,
|
||||
module->cmdline, module->cmdline, module->cmdline_size);
|
||||
|
||||
retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "bootargs",
|
||||
module->cmdline, module->cmdline_size + 1);
|
||||
if (retval)
|
||||
return grub_error (GRUB_ERR_IO, "failed to update FDT");
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_dprintf ("xen_loader", "Module %s has not bootargs!\n",
|
||||
module->name);
|
||||
}
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
finalize_params_xen_boot (void)
|
||||
{
|
||||
struct xen_boot_binary *module;
|
||||
void *xen_boot_fdt;
|
||||
grub_size_t additional_size = 0x1000;
|
||||
|
||||
/* Hypervisor. */
|
||||
additional_size += FDT_NODE_NAME_MAX_SIZE + xen_hypervisor->cmdline_size;
|
||||
FOR_LIST_ELEMENTS (module, module_head)
|
||||
{
|
||||
additional_size += 6 * FDT_NODE_NAME_MAX_SIZE + module->
|
||||
node_info.compat_string_size + module->cmdline_size;
|
||||
}
|
||||
|
||||
xen_boot_fdt = grub_fdt_load (additional_size);
|
||||
if (!xen_boot_fdt)
|
||||
return grub_error (GRUB_ERR_IO, "failed to get FDT");
|
||||
|
||||
if (xen_hypervisor)
|
||||
{
|
||||
if (prepare_xen_hypervisor_params (xen_boot_fdt) != GRUB_ERR_NONE)
|
||||
goto fail;
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_dprintf ("xen_loader", "Failed to get Xen Hypervisor info!\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Set module params info */
|
||||
FOR_LIST_ELEMENTS (module, module_head)
|
||||
{
|
||||
if (module->start && module->size > 0)
|
||||
{
|
||||
grub_dprintf ("xen_loader", "Module %s @ 0x%lx size:0x%lx\n",
|
||||
module->name,
|
||||
xen_boot_address_align (module->start, module->align),
|
||||
module->size);
|
||||
if (prepare_xen_module_params (module, xen_boot_fdt) != GRUB_ERR_NONE)
|
||||
goto fail;
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_dprintf ("xen_loader", "Module info error: %s!\n", module->name);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (grub_fdt_install() == GRUB_ERR_NONE)
|
||||
return GRUB_ERR_NONE;
|
||||
|
||||
fail:
|
||||
grub_fdt_unload ();
|
||||
|
||||
return grub_error (GRUB_ERR_IO, "failed to install/update FDT");
|
||||
}
|
||||
|
||||
|
||||
static grub_err_t
|
||||
xen_boot (void)
|
||||
{
|
||||
grub_err_t err = finalize_params_xen_boot ();
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return grub_arm64_uefi_boot_image (xen_hypervisor->start,
|
||||
xen_hypervisor->size,
|
||||
xen_hypervisor->cmdline);
|
||||
}
|
||||
|
||||
static void
|
||||
single_binary_unload (struct xen_boot_binary *binary)
|
||||
{
|
||||
if (!binary)
|
||||
return;
|
||||
|
||||
if (binary->start && binary->size > 0)
|
||||
{
|
||||
grub_efi_free_pages ((grub_efi_physical_address_t) binary->start,
|
||||
GRUB_EFI_BYTES_TO_PAGES (binary->size + binary->align));
|
||||
}
|
||||
|
||||
if (binary->cmdline && binary->cmdline_size > 0)
|
||||
{
|
||||
grub_free (binary->cmdline);
|
||||
grub_dprintf ("xen_loader",
|
||||
"Module %s cmdline memory free @ %p size: %d\n",
|
||||
binary->name, binary->cmdline, binary->cmdline_size);
|
||||
}
|
||||
|
||||
if (binary->node_info.type == MODULE_CUSTOM)
|
||||
grub_free ((void *) binary->node_info.compat_string);
|
||||
|
||||
if (grub_strcmp (binary->name, XEN_HYPERVISOR_NAME))
|
||||
grub_list_remove (GRUB_AS_LIST (binary));
|
||||
|
||||
grub_dprintf ("xen_loader",
|
||||
"Module %s struct memory free @ %p size: 0x%lx\n",
|
||||
binary->name, binary, sizeof (binary));
|
||||
grub_free (binary);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
all_binaries_unload (void)
|
||||
{
|
||||
struct xen_boot_binary *binary;
|
||||
|
||||
FOR_LIST_ELEMENTS (binary, module_head)
|
||||
{
|
||||
single_binary_unload (binary);
|
||||
}
|
||||
|
||||
if (xen_hypervisor)
|
||||
single_binary_unload (xen_hypervisor);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
xen_unload (void)
|
||||
{
|
||||
loaded = 0;
|
||||
all_binaries_unload ();
|
||||
grub_fdt_unload ();
|
||||
grub_dl_unref (my_mod);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static void
|
||||
xen_boot_binary_load (struct xen_boot_binary *binary, grub_file_t file,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
binary->size = grub_file_size (file);
|
||||
grub_dprintf ("xen_loader", "Xen_boot %s file size: 0x%lx\n",
|
||||
binary->name, binary->size);
|
||||
|
||||
binary->start
|
||||
= (grub_addr_t) grub_efi_allocate_pages (0,
|
||||
GRUB_EFI_BYTES_TO_PAGES
|
||||
(binary->size +
|
||||
binary->align));
|
||||
if (!binary->start)
|
||||
{
|
||||
grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
|
||||
return;
|
||||
}
|
||||
|
||||
grub_dprintf ("xen_loader", "Xen_boot %s numpages: 0x%lx\n",
|
||||
binary->name, GRUB_EFI_BYTES_TO_PAGES (binary->size + binary->align));
|
||||
|
||||
if (grub_file_read (file, (void *) xen_boot_address_align (binary->start,
|
||||
binary->align),
|
||||
binary->size) != (grub_ssize_t) binary->size)
|
||||
{
|
||||
single_binary_unload (binary);
|
||||
grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), argv[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (argc > 1)
|
||||
{
|
||||
binary->cmdline_size = grub_loader_cmdline_size (argc - 1, argv + 1);
|
||||
binary->cmdline = grub_zalloc (binary->cmdline_size);
|
||||
if (!binary->cmdline)
|
||||
{
|
||||
single_binary_unload (binary);
|
||||
grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
|
||||
return;
|
||||
}
|
||||
grub_create_loader_cmdline (argc - 1, argv + 1, binary->cmdline,
|
||||
binary->cmdline_size);
|
||||
grub_dprintf ("xen_loader",
|
||||
"Xen_boot %s cmdline @ %p %s, size: %d\n", binary->name,
|
||||
binary->cmdline, binary->cmdline, binary->cmdline_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
binary->cmdline_size = 0;
|
||||
binary->cmdline = NULL;
|
||||
}
|
||||
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
return;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_xen_module (grub_command_t cmd, int argc, char *argv[])
|
||||
{
|
||||
|
||||
struct xen_boot_binary *module = NULL;
|
||||
grub_file_t file = 0;
|
||||
|
||||
if (!argc)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!loaded)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
N_("you need to load the Xen Hypervisor first"));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
module =
|
||||
(struct xen_boot_binary *) grub_zalloc (sizeof (struct xen_boot_binary));
|
||||
if (!module)
|
||||
return grub_errno;
|
||||
|
||||
/* process all the options and get module type */
|
||||
if (set_module_type (cmd, module) != GRUB_ERR_NONE)
|
||||
goto fail;
|
||||
switch (module->node_info.type)
|
||||
{
|
||||
case MODULE_IMAGE:
|
||||
case MODULE_INITRD:
|
||||
case MODULE_XSM:
|
||||
module->node_info.compat_string =
|
||||
default_compat_string[module->node_info.type].compat_string;
|
||||
module->node_info.compat_string_size =
|
||||
default_compat_string[module->node_info.type].size;
|
||||
break;
|
||||
|
||||
case MODULE_CUSTOM:
|
||||
/* we have set the node_info in set_module_type */
|
||||
break;
|
||||
|
||||
default:
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid argument"));
|
||||
}
|
||||
module->name = module->node_info.compat_string;
|
||||
module->align = module_default_align[module->node_info.type];
|
||||
|
||||
grub_dprintf ("xen_loader", "Init %s module and node info:\n"
|
||||
"compatible %s\ncompat_string_size 0x%lx\n",
|
||||
module->name, module->node_info.compat_string,
|
||||
module->node_info.compat_string_size);
|
||||
|
||||
file = grub_file_open (argv[0]);
|
||||
if (!file)
|
||||
goto fail;
|
||||
|
||||
xen_boot_binary_load (module, file, argc, argv);
|
||||
if (grub_errno == GRUB_ERR_NONE)
|
||||
grub_list_push (GRUB_AS_LIST_P (&module_head), GRUB_AS_LIST (module));
|
||||
|
||||
fail:
|
||||
if (file)
|
||||
grub_file_close (file);
|
||||
if (grub_errno != GRUB_ERR_NONE)
|
||||
single_binary_unload (module);
|
||||
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_xen_hypervisor (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc, char *argv[])
|
||||
{
|
||||
struct xen_hypervisor_header sh;
|
||||
grub_file_t file = NULL;
|
||||
|
||||
grub_dl_ref (my_mod);
|
||||
|
||||
if (!argc)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
file = grub_file_open (argv[0]);
|
||||
if (!file)
|
||||
goto fail;
|
||||
|
||||
if (grub_file_read (file, &sh, sizeof (sh)) != (long) sizeof (sh))
|
||||
goto fail;
|
||||
if (grub_arm64_uefi_check_image
|
||||
((struct grub_arm64_linux_kernel_header *) &sh) != GRUB_ERR_NONE)
|
||||
goto fail;
|
||||
grub_file_seek (file, 0);
|
||||
|
||||
/* if another module has called grub_loader_set,
|
||||
we need to make sure that another module is unloaded properly */
|
||||
grub_loader_unset ();
|
||||
|
||||
xen_hypervisor =
|
||||
(struct xen_boot_binary *) grub_zalloc (sizeof (struct xen_boot_binary));
|
||||
if (!xen_hypervisor)
|
||||
return grub_errno;
|
||||
|
||||
xen_hypervisor->name = XEN_HYPERVISOR_NAME;
|
||||
xen_hypervisor->align = (grub_size_t) sh.optional_header.section_alignment;
|
||||
|
||||
xen_boot_binary_load (xen_hypervisor, file, argc, argv);
|
||||
if (grub_errno == GRUB_ERR_NONE)
|
||||
{
|
||||
grub_loader_set (xen_boot, xen_unload, 0);
|
||||
loaded = 1;
|
||||
}
|
||||
|
||||
fail:
|
||||
if (file)
|
||||
grub_file_close (file);
|
||||
if (grub_errno != GRUB_ERR_NONE)
|
||||
{
|
||||
loaded = 0;
|
||||
all_binaries_unload ();
|
||||
grub_dl_unref (my_mod);
|
||||
}
|
||||
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static grub_command_t cmd_xen_hypervisor;
|
||||
static grub_command_t cmd_xen_linux, cmd_xen_initrd, cmd_xen_xsm;
|
||||
|
||||
GRUB_MOD_INIT (xen_boot)
|
||||
{
|
||||
cmd_xen_hypervisor =
|
||||
grub_register_command ("xen_hypervisor", grub_cmd_xen_hypervisor, 0,
|
||||
N_("Load a xen hypervisor."));
|
||||
cmd_xen_linux =
|
||||
grub_register_command ("xen_linux", grub_cmd_xen_module, 0,
|
||||
N_("Load a xen linux kernel for dom0."));
|
||||
cmd_xen_initrd =
|
||||
grub_register_command ("xen_initrd", grub_cmd_xen_module, 0,
|
||||
N_("Load a xen initrd for dom0."));
|
||||
cmd_xen_xsm =
|
||||
grub_register_command ("xen_xsm", grub_cmd_xen_module, 0,
|
||||
N_("Load a xen security module."));
|
||||
my_mod = mod;
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI (xen_boot)
|
||||
{
|
||||
grub_unregister_command (cmd_xen_hypervisor);
|
||||
grub_unregister_command (cmd_xen_linux);
|
||||
grub_unregister_command (cmd_xen_initrd);
|
||||
grub_unregister_command (cmd_xen_xsm);
|
||||
}
|
|
@ -73,6 +73,9 @@ load_kernel (grub_file_t file, const char *filename,
|
|||
if (grub_multiboot_quirks & GRUB_MULTIBOOT_QUIRK_BAD_KLUDGE)
|
||||
{
|
||||
err = grub_multiboot_load_elf (file, filename, buffer);
|
||||
if (err == GRUB_ERR_NONE) {
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
if (err == GRUB_ERR_UNKNOWN_OS && (header->flags & MULTIBOOT_AOUT_KLUDGE))
|
||||
grub_errno = err = GRUB_ERR_NONE;
|
||||
}
|
||||
|
|
|
@ -240,20 +240,27 @@ grub_cmd_multiboot (grub_command_t cmd __attribute__ ((unused)),
|
|||
|
||||
#ifndef GRUB_USE_MULTIBOOT2
|
||||
grub_multiboot_quirks = GRUB_MULTIBOOT_QUIRKS_NONE;
|
||||
int option_found = 0;
|
||||
|
||||
if (argc != 0 && grub_strcmp (argv[0], "--quirk-bad-kludge") == 0)
|
||||
do
|
||||
{
|
||||
argc--;
|
||||
argv++;
|
||||
grub_multiboot_quirks |= GRUB_MULTIBOOT_QUIRK_BAD_KLUDGE;
|
||||
}
|
||||
option_found = 0;
|
||||
if (argc != 0 && grub_strcmp (argv[0], "--quirk-bad-kludge") == 0)
|
||||
{
|
||||
argc--;
|
||||
argv++;
|
||||
option_found = 1;
|
||||
grub_multiboot_quirks |= GRUB_MULTIBOOT_QUIRK_BAD_KLUDGE;
|
||||
}
|
||||
|
||||
if (argc != 0 && grub_strcmp (argv[0], "--quirk-modules-after-kernel") == 0)
|
||||
{
|
||||
argc--;
|
||||
argv++;
|
||||
grub_multiboot_quirks |= GRUB_MULTIBOOT_QUIRK_MODULES_AFTER_KERNEL;
|
||||
}
|
||||
if (argc != 0 && grub_strcmp (argv[0], "--quirk-modules-after-kernel") == 0)
|
||||
{
|
||||
argc--;
|
||||
argv++;
|
||||
option_found = 1;
|
||||
grub_multiboot_quirks |= GRUB_MULTIBOOT_QUIRK_MODULES_AFTER_KERNEL;
|
||||
}
|
||||
} while (option_found);
|
||||
#endif
|
||||
|
||||
if (argc == 0)
|
||||
|
|
|
@ -196,7 +196,7 @@ alloc_phys_choose (grub_uint64_t addr, grub_uint64_t len,
|
|||
struct alloc_phys_ctx *ctx = data;
|
||||
grub_addr_t end = addr + len;
|
||||
|
||||
if (type != 1)
|
||||
if (type != GRUB_MEMORY_AVAILABLE)
|
||||
return 0;
|
||||
|
||||
addr = ALIGN_UP (addr, FOUR_MB);
|
||||
|
@ -430,7 +430,7 @@ static int
|
|||
get_physbase (grub_uint64_t addr, grub_uint64_t len __attribute__ ((unused)),
|
||||
grub_memory_type_t type, void *data __attribute__ ((unused)))
|
||||
{
|
||||
if (type != 1)
|
||||
if (type != GRUB_MEMORY_AVAILABLE)
|
||||
return 0;
|
||||
if (addr < phys_base)
|
||||
phys_base = addr;
|
||||
|
|
|
@ -73,6 +73,7 @@ grub_efi_mmap_iterate (grub_memory_hook_t hook, void *hook_data,
|
|||
GRUB_MEMORY_AVAILABLE, hook_data);
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case GRUB_EFI_RUNTIME_SERVICES_CODE:
|
||||
hook (desc->physical_start, desc->num_pages * 4096,
|
||||
GRUB_MEMORY_CODE, hook_data);
|
||||
|
@ -83,10 +84,6 @@ grub_efi_mmap_iterate (grub_memory_hook_t hook, void *hook_data,
|
|||
GRUB_MEMORY_BADRAM, hook_data);
|
||||
break;
|
||||
|
||||
default:
|
||||
grub_printf ("Unknown memory type %d, considering reserved\n",
|
||||
desc->type);
|
||||
|
||||
case GRUB_EFI_BOOT_SERVICES_DATA:
|
||||
if (!avoid_efi_boot_services)
|
||||
{
|
||||
|
@ -94,6 +91,7 @@ grub_efi_mmap_iterate (grub_memory_hook_t hook, void *hook_data,
|
|||
GRUB_MEMORY_AVAILABLE, hook_data);
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case GRUB_EFI_RESERVED_MEMORY_TYPE:
|
||||
case GRUB_EFI_RUNTIME_SERVICES_DATA:
|
||||
case GRUB_EFI_MEMORY_MAPPED_IO:
|
||||
|
@ -119,6 +117,18 @@ grub_efi_mmap_iterate (grub_memory_hook_t hook, void *hook_data,
|
|||
hook (desc->physical_start, desc->num_pages * 4096,
|
||||
GRUB_MEMORY_NVS, hook_data);
|
||||
break;
|
||||
|
||||
case GRUB_EFI_PERSISTENT_MEMORY:
|
||||
hook (desc->physical_start, desc->num_pages * 4096,
|
||||
GRUB_MEMORY_PERSISTENT, hook_data);
|
||||
break;
|
||||
|
||||
default:
|
||||
grub_printf ("Unknown memory type %d, considering reserved\n",
|
||||
desc->type);
|
||||
hook (desc->physical_start, desc->num_pages * 4096,
|
||||
GRUB_MEMORY_RESERVED, hook_data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -142,6 +152,13 @@ make_efi_memtype (int type)
|
|||
/* No way to remove a chunk of memory from EFI mmap.
|
||||
So mark it as unusable. */
|
||||
case GRUB_MEMORY_HOLE:
|
||||
/*
|
||||
* AllocatePages() does not support GRUB_EFI_PERSISTENT_MEMORY,
|
||||
* so no translation for GRUB_MEMORY_PERSISTENT or
|
||||
* GRUB_MEMORY_PERSISTENT_LEGACY.
|
||||
*/
|
||||
case GRUB_MEMORY_PERSISTENT:
|
||||
case GRUB_MEMORY_PERSISTENT_LEGACY:
|
||||
case GRUB_MEMORY_RESERVED:
|
||||
return GRUB_EFI_UNUSABLE_MEMORY;
|
||||
|
||||
|
|
|
@ -437,7 +437,7 @@ grub_net_dns_lookup (const char *name,
|
|||
struct recv_data data = {naddresses, addresses, cache,
|
||||
grub_cpu_to_be16 (id++), 0, 0, name, 0};
|
||||
grub_uint8_t *nbd;
|
||||
int have_server = 0;
|
||||
grub_size_t try_server = 0;
|
||||
|
||||
if (!servers)
|
||||
{
|
||||
|
@ -543,38 +543,35 @@ grub_net_dns_lookup (const char *name,
|
|||
for (i = 0; i < n_servers * 4; i++)
|
||||
{
|
||||
/* Connect to a next server. */
|
||||
while (!(i & 1) && send_servers < n_servers)
|
||||
while (!(i & 1) && try_server < n_servers)
|
||||
{
|
||||
sockets[send_servers] = grub_net_udp_open (servers[send_servers],
|
||||
sockets[send_servers] = grub_net_udp_open (servers[try_server++],
|
||||
DNS_PORT,
|
||||
recv_hook,
|
||||
&data);
|
||||
send_servers++;
|
||||
if (!sockets[send_servers - 1])
|
||||
if (!sockets[send_servers])
|
||||
{
|
||||
err = grub_errno;
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
have_server = 1;
|
||||
send_servers++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!have_server)
|
||||
if (!send_servers)
|
||||
goto out;
|
||||
if (*data.naddresses)
|
||||
goto out;
|
||||
for (j = 0; j < send_servers; j++)
|
||||
{
|
||||
grub_err_t err2;
|
||||
if (!sockets[j])
|
||||
continue;
|
||||
nb->data = nbd;
|
||||
|
||||
grub_size_t t = 0;
|
||||
do
|
||||
{
|
||||
nb->data = nbd;
|
||||
if (servers[j].option == DNS_OPTION_IPV4 ||
|
||||
((servers[j].option == DNS_OPTION_PREFER_IPV4) && (t++ == 0)) ||
|
||||
((servers[j].option == DNS_OPTION_PREFER_IPV6) && (t++ == 1)))
|
||||
|
|
|
@ -47,19 +47,19 @@ send_card_buffer (struct grub_net_card *dev,
|
|||
if (st != GRUB_EFI_SUCCESS)
|
||||
return grub_error (GRUB_ERR_IO,
|
||||
N_("couldn't send network packet"));
|
||||
if (txbuf == dev->txbuf)
|
||||
/*
|
||||
Some buggy firmware could return an arbitrary address instead of the
|
||||
txbuf address we trasmitted, so just check that txbuf is non NULL
|
||||
for success. This is ok because we open the SNP protocol in
|
||||
exclusive mode so we know we're the only ones transmitting on this
|
||||
box and since we only transmit one packet at a time we know our
|
||||
transmit was successfull.
|
||||
*/
|
||||
if (txbuf)
|
||||
{
|
||||
dev->txbusy = 0;
|
||||
break;
|
||||
}
|
||||
if (txbuf)
|
||||
{
|
||||
st = efi_call_7 (net->transmit, net, 0, dev->last_pkt_size,
|
||||
dev->txbuf, NULL, NULL, NULL);
|
||||
if (st != GRUB_EFI_SUCCESS)
|
||||
return grub_error (GRUB_ERR_IO,
|
||||
N_("couldn't send network packet"));
|
||||
}
|
||||
if (limit_time < grub_get_time_ms ())
|
||||
return grub_error (GRUB_ERR_TIMEOUT,
|
||||
N_("couldn't send network packet"));
|
||||
|
@ -84,8 +84,9 @@ send_card_buffer (struct grub_net_card *dev,
|
|||
we run in the GRUB_ERR_TIMEOUT case above.
|
||||
Perhaps a timeout in the FW has discarded the recycle buffer.
|
||||
*/
|
||||
txbuf = NULL;
|
||||
st = efi_call_3 (net->get_status, net, 0, &txbuf);
|
||||
dev->txbusy = !(st == GRUB_EFI_SUCCESS && txbuf == dev->txbuf);
|
||||
dev->txbusy = !(st == GRUB_EFI_SUCCESS && txbuf);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
|
|
@ -305,6 +305,7 @@ search_net_devices (struct grub_ieee1275_devalias *alias)
|
|||
grub_uint64_t prop;
|
||||
grub_uint8_t *pprop;
|
||||
char *shortname;
|
||||
char need_suffix = 1;
|
||||
|
||||
if (grub_strcmp (alias->type, "network") != 0)
|
||||
return 0;
|
||||
|
@ -325,7 +326,43 @@ search_net_devices (struct grub_ieee1275_devalias *alias)
|
|||
|
||||
#define SUFFIX ":speed=auto,duplex=auto,1.1.1.1,dummy,1.1.1.1,1.1.1.1,5,5,1.1.1.1,512"
|
||||
|
||||
if (!grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_OFNET_SUFFIX))
|
||||
if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_OFNET_SUFFIX))
|
||||
need_suffix = 0;
|
||||
|
||||
/* sun4v vnet devices do not support setting duplex/speed */
|
||||
{
|
||||
char *ptr;
|
||||
|
||||
grub_ieee1275_finddevice (alias->path, &devhandle);
|
||||
|
||||
grub_ieee1275_get_property_length (devhandle, "compatible", &prop_size);
|
||||
if (prop_size > 0)
|
||||
{
|
||||
pprop = grub_malloc (prop_size);
|
||||
if (!pprop)
|
||||
{
|
||||
grub_free (card);
|
||||
grub_free (ofdata);
|
||||
grub_print_error ();
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!grub_ieee1275_get_property (devhandle, "compatible",
|
||||
pprop, prop_size, NULL))
|
||||
{
|
||||
for (ptr = (char *) pprop; ptr - (char *) pprop < prop_size;
|
||||
ptr += grub_strlen (ptr) + 1)
|
||||
{
|
||||
if (!grub_strcmp(ptr, "SUNW,sun4v-network"))
|
||||
need_suffix = 0;
|
||||
}
|
||||
}
|
||||
|
||||
grub_free (pprop);
|
||||
}
|
||||
}
|
||||
|
||||
if (need_suffix)
|
||||
ofdata->path = grub_malloc (grub_strlen (alias->path) + sizeof (SUFFIX));
|
||||
else
|
||||
ofdata->path = grub_malloc (grub_strlen (alias->path) + 1);
|
||||
|
@ -335,7 +372,7 @@ search_net_devices (struct grub_ieee1275_devalias *alias)
|
|||
return 0;
|
||||
}
|
||||
ofdata->suffix = grub_stpcpy (ofdata->path, alias->path);
|
||||
if (!grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_OFNET_SUFFIX))
|
||||
if (need_suffix)
|
||||
grub_memcpy (ofdata->suffix, SUFFIX, sizeof (SUFFIX));
|
||||
else
|
||||
*ofdata->suffix = '\0';
|
||||
|
|
|
@ -1341,6 +1341,43 @@ grub_net_open_real (const char *name)
|
|||
}
|
||||
if (try == 0)
|
||||
{
|
||||
const char *prefix, *root;
|
||||
char *prefdev, *comma;
|
||||
int skip = 0;
|
||||
grub_size_t devlen;
|
||||
|
||||
/* Do not attempt to load module if it requires protocol provided
|
||||
by this module - it results in infinite recursion. Just continue,
|
||||
fail and cleanup on next iteration.
|
||||
*/
|
||||
prefix = grub_env_get ("prefix");
|
||||
if (!prefix)
|
||||
continue;
|
||||
|
||||
prefdev = grub_file_get_device_name (prefix);
|
||||
if (!prefdev)
|
||||
{
|
||||
root = grub_env_get ("root");
|
||||
if (!root)
|
||||
continue;
|
||||
prefdev = grub_strdup (root);
|
||||
if (!prefdev)
|
||||
continue;
|
||||
}
|
||||
|
||||
comma = grub_strchr (prefdev, ',');
|
||||
if (comma)
|
||||
*comma = '\0';
|
||||
devlen = grub_strlen (prefdev);
|
||||
|
||||
if (protnamelen == devlen && grub_memcmp (prefdev, protname, devlen) == 0)
|
||||
skip = 1;
|
||||
|
||||
grub_free (prefdev);
|
||||
|
||||
if (skip)
|
||||
continue;
|
||||
|
||||
if (sizeof ("http") - 1 == protnamelen
|
||||
&& grub_memcmp ("http", protname, protnamelen) == 0)
|
||||
{
|
||||
|
|
|
@ -498,11 +498,22 @@ grub_net_tcp_accept (grub_net_tcp_socket_t sock,
|
|||
struct grub_net_buff *nb_ack;
|
||||
struct tcphdr *tcph;
|
||||
grub_err_t err;
|
||||
grub_net_network_level_address_t gateway;
|
||||
struct grub_net_network_level_interface *inf;
|
||||
|
||||
sock->recv_hook = recv_hook;
|
||||
sock->error_hook = error_hook;
|
||||
sock->fin_hook = fin_hook;
|
||||
sock->hook_data = hook_data;
|
||||
|
||||
err = grub_net_route_address (sock->out_nla, &gateway, &inf);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = grub_net_link_layer_resolve (sock->inf, &gateway, &(sock->ll_target_addr));
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
nb_ack = grub_netbuff_alloc (sizeof (*tcph)
|
||||
+ GRUB_NET_OUR_MAX_IP_HEADER_SIZE
|
||||
+ GRUB_NET_MAX_LINK_HEADER_SIZE);
|
||||
|
@ -882,7 +893,10 @@ grub_net_recv_tcp_packet (struct grub_net_buff *nb,
|
|||
grub_priority_queue_pop (sock->pq);
|
||||
}
|
||||
if (grub_be_to_cpu32 (tcph->seqnr) != sock->their_cur_seq)
|
||||
return GRUB_ERR_NONE;
|
||||
{
|
||||
ack (sock);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
while (1)
|
||||
{
|
||||
nb_top_p = grub_priority_queue_top (sock->pq);
|
||||
|
|
|
@ -174,8 +174,11 @@ grub_username_get (char buf[], unsigned buf_size)
|
|||
|
||||
if (key == '\b')
|
||||
{
|
||||
cur_len--;
|
||||
grub_printf ("\b");
|
||||
if (cur_len)
|
||||
{
|
||||
cur_len--;
|
||||
grub_printf ("\b \b");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -208,8 +208,7 @@ grub_util_devmapper_part_to_disk (struct stat *st,
|
|||
&major, &minor, 0))
|
||||
{
|
||||
*is_part = 1;
|
||||
return grub_find_device ("/dev",
|
||||
(major << 8) | minor);
|
||||
return grub_find_device ("/dev", makedev (major, minor));
|
||||
}
|
||||
*is_part = 0;
|
||||
return xstrdup (path);
|
||||
|
|
|
@ -45,12 +45,6 @@
|
|||
#ifdef __linux__
|
||||
#include <sys/ioctl.h> /* ioctl */
|
||||
#include <sys/mount.h>
|
||||
#ifndef MAJOR
|
||||
# ifndef MINORBITS
|
||||
# define MINORBITS 8
|
||||
# endif /* ! MINORBITS */
|
||||
# define MAJOR(dev) ((unsigned) ((dev) >> MINORBITS))
|
||||
#endif /* ! MAJOR */
|
||||
#ifndef FLOPPY_MAJOR
|
||||
# define FLOPPY_MAJOR 2
|
||||
#endif /* ! FLOPPY_MAJOR */
|
||||
|
@ -73,7 +67,6 @@
|
|||
#include <grub/emu/getroot.h>
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||
# define MAJOR(dev) major(dev)
|
||||
# define FLOPPY_MAJOR 2
|
||||
#endif
|
||||
|
||||
|
@ -90,7 +83,6 @@
|
|||
#endif /* defined(__NetBSD__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) */
|
||||
|
||||
#if defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
# define MAJOR(dev) major(dev)
|
||||
# ifdef HAVE_GETRAWPARTITION
|
||||
# include <util.h> /* getrawpartition */
|
||||
# endif /* HAVE_GETRAWPARTITION */
|
||||
|
|
|
@ -54,7 +54,8 @@ grub_password_get (char buf[], unsigned buf_size)
|
|||
grub_memset (buf, 0, buf_size);
|
||||
if (!fgets (buf, buf_size, stdin))
|
||||
{
|
||||
fclose (in);
|
||||
if (in != stdin)
|
||||
fclose (in);
|
||||
return 0;
|
||||
}
|
||||
ptr = buf + strlen (buf) - 1;
|
||||
|
@ -67,7 +68,8 @@ grub_password_get (char buf[], unsigned buf_size)
|
|||
grub_xputs ("\n");
|
||||
grub_refresh ();
|
||||
|
||||
fclose (in);
|
||||
if (in != stdin)
|
||||
fclose (in);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -249,7 +249,7 @@ pc_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors,
|
|||
|
||||
if (embed_type != GRUB_EMBED_PCBIOS)
|
||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||
"PC-style partitions curently support "
|
||||
"PC-style partitions currently support "
|
||||
"only PC-BIOS embedding");
|
||||
|
||||
if (disk->partition)
|
||||
|
|
|
@ -104,26 +104,12 @@ const unsigned efi_codes[] =
|
|||
GRUB_TERM_KEY_DC, GRUB_TERM_KEY_PPAGE, GRUB_TERM_KEY_NPAGE, GRUB_TERM_KEY_F1,
|
||||
GRUB_TERM_KEY_F2, GRUB_TERM_KEY_F3, GRUB_TERM_KEY_F4, GRUB_TERM_KEY_F5,
|
||||
GRUB_TERM_KEY_F6, GRUB_TERM_KEY_F7, GRUB_TERM_KEY_F8, GRUB_TERM_KEY_F9,
|
||||
GRUB_TERM_KEY_F10, 0, 0, '\e'
|
||||
GRUB_TERM_KEY_F10, GRUB_TERM_KEY_F11, GRUB_TERM_KEY_F12, '\e'
|
||||
};
|
||||
|
||||
|
||||
static int
|
||||
grub_console_getkey (struct grub_term_input *term __attribute__ ((unused)))
|
||||
grub_efi_translate_key (grub_efi_input_key_t key)
|
||||
{
|
||||
grub_efi_simple_input_interface_t *i;
|
||||
grub_efi_input_key_t key;
|
||||
grub_efi_status_t status;
|
||||
|
||||
if (grub_efi_is_finished)
|
||||
return 0;
|
||||
|
||||
i = grub_efi_system_table->con_in;
|
||||
status = efi_call_2 (i->read_key_stroke, i, &key);
|
||||
|
||||
if (status != GRUB_EFI_SUCCESS)
|
||||
return GRUB_TERM_NO_KEY;
|
||||
|
||||
if (key.scan_code == 0)
|
||||
{
|
||||
/* Some firmware implementations use VT100-style codes against the spec.
|
||||
|
@ -139,9 +125,100 @@ grub_console_getkey (struct grub_term_input *term __attribute__ ((unused)))
|
|||
else if (key.scan_code < ARRAY_SIZE (efi_codes))
|
||||
return efi_codes[key.scan_code];
|
||||
|
||||
if ((key.unicode_char >= 0x20 && key.unicode_char <= 0x7f)
|
||||
|| key.unicode_char == '\t' || key.unicode_char == '\b'
|
||||
|| key.unicode_char == '\n' || key.unicode_char == '\r')
|
||||
return key.unicode_char;
|
||||
|
||||
return GRUB_TERM_NO_KEY;
|
||||
}
|
||||
|
||||
static int
|
||||
grub_console_getkey_con (struct grub_term_input *term __attribute__ ((unused)))
|
||||
{
|
||||
grub_efi_simple_input_interface_t *i;
|
||||
grub_efi_input_key_t key;
|
||||
grub_efi_status_t status;
|
||||
|
||||
i = grub_efi_system_table->con_in;
|
||||
status = efi_call_2 (i->read_key_stroke, i, &key);
|
||||
|
||||
if (status != GRUB_EFI_SUCCESS)
|
||||
return GRUB_TERM_NO_KEY;
|
||||
|
||||
return grub_efi_translate_key(key);
|
||||
}
|
||||
|
||||
static int
|
||||
grub_console_getkey_ex(struct grub_term_input *term)
|
||||
{
|
||||
grub_efi_key_data_t key_data;
|
||||
grub_efi_status_t status;
|
||||
grub_efi_uint32_t kss;
|
||||
int key = -1;
|
||||
|
||||
grub_efi_simple_text_input_ex_interface_t *text_input = term->data;
|
||||
|
||||
status = efi_call_2 (text_input->read_key_stroke, text_input, &key_data);
|
||||
|
||||
if (status != GRUB_EFI_SUCCESS)
|
||||
return GRUB_TERM_NO_KEY;
|
||||
|
||||
kss = key_data.key_state.key_shift_state;
|
||||
key = grub_efi_translate_key(key_data.key);
|
||||
|
||||
if (key == GRUB_TERM_NO_KEY)
|
||||
return GRUB_TERM_NO_KEY;
|
||||
|
||||
if (kss & GRUB_EFI_SHIFT_STATE_VALID)
|
||||
{
|
||||
if ((kss & GRUB_EFI_LEFT_SHIFT_PRESSED
|
||||
|| kss & GRUB_EFI_RIGHT_SHIFT_PRESSED)
|
||||
&& (key & GRUB_TERM_EXTENDED))
|
||||
key |= GRUB_TERM_SHIFT;
|
||||
if (kss & GRUB_EFI_LEFT_ALT_PRESSED || kss & GRUB_EFI_RIGHT_ALT_PRESSED)
|
||||
key |= GRUB_TERM_ALT;
|
||||
if (kss & GRUB_EFI_LEFT_CONTROL_PRESSED
|
||||
|| kss & GRUB_EFI_RIGHT_CONTROL_PRESSED)
|
||||
key |= GRUB_TERM_CTRL;
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_efi_console_input_init (struct grub_term_input *term)
|
||||
{
|
||||
grub_efi_guid_t text_input_ex_guid =
|
||||
GRUB_EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID;
|
||||
|
||||
if (grub_efi_is_finished)
|
||||
return 0;
|
||||
|
||||
grub_efi_simple_text_input_ex_interface_t *text_input = term->data;
|
||||
if (text_input)
|
||||
return 0;
|
||||
|
||||
text_input = grub_efi_open_protocol(grub_efi_system_table->console_in_handler,
|
||||
&text_input_ex_guid,
|
||||
GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
|
||||
term->data = (void *)text_input;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
grub_console_getkey (struct grub_term_input *term)
|
||||
{
|
||||
if (grub_efi_is_finished)
|
||||
return 0;
|
||||
|
||||
if (term->data)
|
||||
return grub_console_getkey_ex(term);
|
||||
else
|
||||
return grub_console_getkey_con(term);
|
||||
}
|
||||
|
||||
static struct grub_term_coordinate
|
||||
grub_console_getwh (struct grub_term_output *term __attribute__ ((unused)))
|
||||
{
|
||||
|
@ -243,7 +320,7 @@ grub_console_setcursor (struct grub_term_output *term __attribute__ ((unused)),
|
|||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_efi_console_init (struct grub_term_output *term)
|
||||
grub_efi_console_output_init (struct grub_term_output *term)
|
||||
{
|
||||
grub_efi_set_text_mode (1);
|
||||
grub_console_setcursor (term, 1);
|
||||
|
@ -251,7 +328,7 @@ grub_efi_console_init (struct grub_term_output *term)
|
|||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_efi_console_fini (struct grub_term_output *term)
|
||||
grub_efi_console_output_fini (struct grub_term_output *term)
|
||||
{
|
||||
grub_console_setcursor (term, 0);
|
||||
grub_efi_set_text_mode (0);
|
||||
|
@ -262,13 +339,14 @@ static struct grub_term_input grub_console_term_input =
|
|||
{
|
||||
.name = "console",
|
||||
.getkey = grub_console_getkey,
|
||||
.init = grub_efi_console_input_init,
|
||||
};
|
||||
|
||||
static struct grub_term_output grub_console_term_output =
|
||||
{
|
||||
.name = "console",
|
||||
.init = grub_efi_console_init,
|
||||
.fini = grub_efi_console_fini,
|
||||
.init = grub_efi_console_output_init,
|
||||
.fini = grub_efi_console_output_fini,
|
||||
.putchar = grub_console_putchar,
|
||||
.getwh = grub_console_getwh,
|
||||
.getxy = grub_console_getxy,
|
||||
|
@ -291,8 +369,8 @@ grub_console_init (void)
|
|||
return;
|
||||
}
|
||||
|
||||
grub_term_register_input ("console", &grub_console_term_input);
|
||||
grub_term_register_output ("console", &grub_console_term_output);
|
||||
grub_term_register_input ("console", &grub_console_term_input);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue