Merge branch 'master' of git://git.savannah.gnu.org/grub

This commit is contained in:
Michael Marineau 2015-12-17 12:01:00 -08:00
commit 286f1b63df
95 changed files with 6481 additions and 522 deletions

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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;

View file

@ -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");
}

View file

@ -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

View file

@ -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")
};

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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);

View file

@ -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),

View file

@ -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;
}

View file

@ -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;

View file

@ -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
View 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;
}

View file

@ -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"

View file

@ -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;
}

View file

@ -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

View 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;
}

View file

@ -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);
}

View 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;
}

View 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;
}
}
}

View 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;
}

View file

@ -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))

View file

@ -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)

View file

@ -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

View file

@ -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;

View file

@ -470,7 +470,8 @@ grub_password_get (char buf[], unsigned buf_size)
if (key == '\b')
{
cur_len--;
if (cur_len)
cur_len--;
continue;
}

View file

@ -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

View file

@ -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

View file

@ -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

View 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);
}

View file

@ -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);
}

View 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);
}

View file

@ -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;
}

View file

@ -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)

View file

@ -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;

View file

@ -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;

View file

@ -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)))

View file

@ -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;
}

View file

@ -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';

View file

@ -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)
{

View file

@ -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);

View file

@ -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;
}

View file

@ -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);

View file

@ -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 */

View file

@ -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;
}

View file

@ -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)

View file

@ -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