merge my and Abranches' branches

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2011-04-01 11:25:48 +02:00
commit ecb2a8b656
215 changed files with 10573 additions and 1733 deletions

View file

@ -30,7 +30,7 @@ CCASFLAGS_LIBRARY += $(CCASFLAGS_PLATFORM)
# gentrigtables
gentrigtables: gentrigtables.c
$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(CPPFLAGS) -lm $<
$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(CPPFLAGS) $< -lm
CLEANFILES += gentrigtables
# trigtables.c
@ -50,7 +50,7 @@ grub_script.yy.h: script/yylex.l
grub_script.yy.c: grub_script.yy.h
rs_decoder.S: $(srcdir)/lib/reed_solomon.c
$(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) -I$(top_builddir) -S -DSTANDALONE -o $@ $< -g0 -mregparm=3
$(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) -Os -I$(top_builddir) -S -DSTANDALONE -o $@ $< -g0 -mregparm=3
kern/i386/pc/startup.S: $(builddir)/rs_decoder.S
@ -113,6 +113,7 @@ endif
if COND_i386_ieee1275
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ofnet.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h
@ -148,6 +149,7 @@ endif
if COND_powerpc_ieee1275
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ofnet.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h
@ -155,6 +157,7 @@ endif
if COND_sparc64_ieee1275
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ofnet.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/sparc64/ieee1275/ieee1275.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
@ -238,9 +241,9 @@ command.lst: $(MARKER_FILES)
(for pp in $^; do \
b=`basename $$pp .marker`; \
sed -n \
-e "/COMMAND_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/\1: $$b/;p;}" \
-e "/EXTCOMMAND_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/*\1: $$b/;p;}" \
-e "/P1COMMAND_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/*\1: $$b/;p;}" $$pp; \
-e "/P1COMMAND_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/*\1: $$b/;p;}" \
-e "/COMMAND_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/\1: $$b/;p;}" $$pp; \
done) | sort -u > $@
platform_DATA += command.lst
CLEANFILES += command.lst
@ -304,7 +307,7 @@ platform_DATA += moddep.lst
CLEANFILES += config.log syminfo.lst moddep.lst
$(MOD_FILES): %.mod : genmod.sh moddep.lst %.module$(EXEEXT)
sh $^ $@
TARGET_OBJ2ELF=@TARGET_OBJ2ELF@ sh $^ $@
platform_DATA += $(MOD_FILES)
CLEANFILES += $(MOD_FILES)

View file

@ -27,6 +27,8 @@ kernel = {
i386_qemu_ldflags = '$(TARGET_IMG_LDFLAGS)';
i386_qemu_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x8200';
ldadd = '$(LDADD_KERNEL)';
i386_coreboot_ldflags = '-Wl,-Ttext=0x8200';
i386_multiboot_ldflags = '-Wl,-Ttext=0x8200';
i386_ieee1275_ldflags = '-Wl,-Ttext=0x10000';
@ -39,10 +41,6 @@ kernel = {
emu_cflags = '$(CFLAGS_GNULIB)';
emu_cppflags = '$(CPPFLAGS_GNULIB)';
mips_ldadd = '-lgcc';
powerpc_ldadd = '-lgcc';
sparc64_ldadd = '-lgcc';
i386_pc_startup = kern/i386/pc/startup.S;
i386_efi_startup = kern/i386/efi/startup.S;
x86_64_efi_startup = kern/x86_64/efi/startup.S;
@ -164,6 +162,7 @@ kernel = {
emu = disk/host.c;
emu = gnulib/progname.c;
emu = gnulib/error.c;
emu = kern/emu/cache.S;
emu = kern/emu/console.c;
emu = kern/emu/getroot.c;
emu = kern/emu/hostdisk.c;
@ -201,7 +200,7 @@ program = {
ldadd = 'kernel.img$(EXEEXT)';
ldadd = '$(MODULE_FILES)';
ldadd = '$(LIBUTIL) $(LIBCURSES) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR)';
ldadd = '$(LIBUTIL) $(LIBCURSES) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
enable = emu;
};
@ -210,11 +209,10 @@ program = {
name = grub-emu-lite;
emu = kern/emu/lite.c;
emu = kern/emu/cache.S;
emu_nodist = symlist.c;
ldadd = 'kernel.img$(EXEEXT)';
ldadd = '$(LIBUTIL) $(LIBCURSES) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR)';
ldadd = '$(LIBUTIL) $(LIBCURSES) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
enable = emu;
};
@ -302,7 +300,8 @@ image = {
mips_cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/xzembed -DGRUB_EMBED_DECOMPRESSOR=1 -DGRUB_MACHINE_LINK_ADDR=0x80200000';
objcopyflags = '-O binary';
ldflags = '-lgcc -static-libgcc -Wl,-Ttext,0x80100000';
ldflags = '-static-libgcc -Wl,-Ttext,0x80100000';
ldadd = '-lgcc';
cflags = '-static-libgcc';
enable = mips;
};
@ -315,7 +314,8 @@ image = {
mips_cppflags = '-DGRUB_EMBED_DECOMPRESSOR=1 -DGRUB_MACHINE_LINK_ADDR=0x80200000';
objcopyflags = '-O binary';
ldflags = '-lgcc -static-libgcc -Wl,-Ttext,0x80100000';
ldflags = '-static-libgcc -Wl,-Ttext,0x80100000';
ldadd = '-lgcc';
cflags = '-static-libgcc';
enable = mips;
};
@ -324,6 +324,7 @@ image = {
name = fwstart;
mips_yeeloong = boot/mips/yeeloong/fwstart.S;
objcopyflags = '-O binary';
ldflags = '-static-libgcc -lgcc -Wl,-N,-S,-Ttext,0xbfc00000,-Bstatic';
enable = mips_yeeloong;
};
@ -1007,6 +1008,19 @@ module = {
common = fs/xfs.c;
};
module = {
name = zfs;
common = fs/zfs/zfs.c;
common = fs/zfs/zfs_lzjb.c;
common = fs/zfs/zfs_sha256.c;
common = fs/zfs/zfs_fletcher.c;
};
module = {
name = zfsinfo;
common = fs/zfs/zfsinfo.c;
};
module = {
name = pxe;
i386_pc = net/i386/pc/pxe.c;
@ -1136,6 +1150,7 @@ module = {
module = {
name = linux16;
i386_pc = loader/i386/pc/linux.c;
i386_pc = lib/cmdline.c;
enable = i386_pc;
};
@ -1170,6 +1185,7 @@ module = {
mips = loader/mips/linux.c;
powerpc_ieee1275 = loader/powerpc/ieee1275/linux.c;
sparc64_ieee1275 = loader/sparc64/ieee1275/linux.c;
common = lib/cmdline.c;
enable = noemu;
};
@ -1448,7 +1464,6 @@ module = {
name = ieee1275_fb;
ieee1275 = video/ieee1275.c;
enable = powerpc;
enable = sparc64;
};
module = {

View file

@ -459,6 +459,8 @@ fd_probe_error_string: .asciz "Floppy"
1:
/* perform read */
movw $GRUB_BOOT_MACHINE_BUFFER_SEG, %bx
movw %bx, %es
xorw %bx, %bx
movw $0x201, %ax
movb $0, %ch
movb $0, %dh

View file

@ -178,8 +178,13 @@ real_code_2:
pushw %es
popw %ds
#if GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART + 4 < 0x200
movl $0x200, %ecx
addl %ecx, %esi
#else
movl $(GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART + 4), %ecx
addl $0x200, %esi
#endif
movl $DATA_ADDR, %edi
call LOCAL(move_memory)
@ -196,7 +201,11 @@ real_code_2:
1:
movl %ss:(DATA_ADDR + GRUB_KERNEL_MACHINE_COMPRESSED_SIZE), %ecx
#if GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART + 4 < 0x200
addl $(GRUB_KERNEL_MACHINE_RAW_SIZE - 0x200), %ecx
#else
addl $(GRUB_KERNEL_MACHINE_RAW_SIZE - (GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART + 4)), %ecx
#endif
2:
call LOCAL(move_memory)

View file

@ -38,7 +38,7 @@ write_bases (void)
for (i = 0; i < GRUB_MACHINE_PCI_NUM_WIN; i++)
reg |= (((base_win[i] >> GRUB_MACHINE_PCI_WIN_SHIFT)
& GRUB_MACHINE_PCI_WIN_MASK)
>> (i * GRUB_MACHINE_PCI_WIN_MASK_SIZE));
<< (i * GRUB_MACHINE_PCI_WIN_MASK_SIZE));
GRUB_MACHINE_PCI_IO_CTRL_REG = reg;
}

View file

@ -90,7 +90,14 @@ grub_pci_iterate (grub_pci_iteratefunc_t hook)
/* Check if there is a device present. */
if (id >> 16 == 0xFFFF)
continue;
{
if (dev.function == 0)
/* Devices are required to implement function 0, so if
it's missing then there is no device here. */
break;
else
continue;
}
#ifdef GRUB_MACHINE_MIPS_YEELOONG
/* Skip ghosts. */

View file

@ -749,8 +749,7 @@ grub_uhci_detect_dev (grub_usb_controller_t dev, int port, int *changed)
else if (port == 1)
reg = GRUB_UHCI_REG_PORTSC2;
else
return grub_error (GRUB_ERR_OUT_OF_RANGE,
"UHCI Root Hub port does not exist");
return GRUB_USB_SPEED_NONE;
status = grub_uhci_readreg16 (u, reg);

View file

@ -25,7 +25,7 @@
#include <grub/term.h>
static grub_usb_controller_dev_t grub_usb_list;
struct grub_usb_attach_desc *attach_hooks;
static struct grub_usb_attach_desc *attach_hooks;
void
grub_usb_controller_dev_register (grub_usb_controller_dev_t usb)

View file

@ -39,7 +39,7 @@ struct grub_usb_hub
grub_usb_device_t dev;
};
struct grub_usb_hub *hubs;
static struct grub_usb_hub *hubs;
/* Add a device that currently has device number 0 and resides on
CONTROLLER, the Hub reported that the device speed is SPEED. */
@ -110,7 +110,7 @@ static grub_usb_err_t
grub_usb_add_hub (grub_usb_device_t dev)
{
struct grub_usb_usb_hubdesc hubdesc;
grub_err_t err;
grub_usb_err_t err;
int i;
err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN

View file

@ -97,7 +97,7 @@ grub_usb_control_msg (grub_usb_device_t dev,
if (! transfer)
{
grub_dma_free (data_chunk);
return grub_errno;
return GRUB_USB_ERR_INTERNAL;
}
setupdata_chunk = grub_memalign_dma32 (32, sizeof (*setupdata));
@ -105,7 +105,7 @@ grub_usb_control_msg (grub_usb_device_t dev,
{
grub_free (transfer);
grub_dma_free (data_chunk);
return grub_errno;
return GRUB_USB_ERR_INTERNAL;
}
setupdata = grub_dma_get_virt (setupdata_chunk);
@ -139,7 +139,7 @@ grub_usb_control_msg (grub_usb_device_t dev,
grub_free (transfer);
grub_dma_free (setupdata_chunk);
grub_dma_free (data_chunk);
return grub_errno;
return GRUB_USB_ERR_INTERNAL;
}
/* Build a Setup packet. XXX: Endianness. */

View file

@ -36,6 +36,7 @@ typedef uint8_t grub_uint8_t;
#ifndef GRUB_DSDT_TEST
#include <grub/misc.h>
#include <grub/time.h>
#include <grub/cpu/io.h>
#endif
@ -324,6 +325,8 @@ grub_acpi_halt (void)
}
}
grub_millisleep (1500);
grub_printf ("ACPI shutdown failed\n");
}
#endif

View file

@ -1,7 +1,7 @@
/* echo.c - Command to display a line of text */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2006,2007 Free Software Foundation, Inc.
* Copyright (C) 2006,2007,2010 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
@ -21,6 +21,7 @@
#include <grub/misc.h>
#include <grub/extcmd.h>
#include <grub/i18n.h>
#include <grub/term.h>
static const struct grub_arg_option options[] =
{
@ -43,8 +44,14 @@ grub_cmd_echo (grub_extcmd_context_t ctxt, int argc, char **args)
for (i = 0; i < argc; i++)
{
char *arg = *args;
/* Unescaping results in a string no longer than the original. */
char *unescaped = grub_malloc (grub_strlen (arg) + 1);
char *p = unescaped;
args++;
if (!unescaped)
return grub_errno;
while (*arg)
{
/* In case `-e' is used, parse backslashes. */
@ -57,11 +64,11 @@ grub_cmd_echo (grub_extcmd_context_t ctxt, int argc, char **args)
switch (*arg)
{
case '\\':
grub_printf ("\\");
*p++ = '\\';
break;
case 'a':
grub_printf ("\a");
*p++ = '\a';
break;
case 'c':
@ -69,23 +76,23 @@ grub_cmd_echo (grub_extcmd_context_t ctxt, int argc, char **args)
break;
case 'f':
grub_printf ("\f");
*p++ = '\f';
break;
case 'n':
grub_printf ("\n");
*p++ = '\n';
break;
case 'r':
grub_printf ("\r");
*p++ = '\r';
break;
case 't':
grub_printf ("\t");
*p++ = '\t';
break;
case 'v':
grub_printf ("\v");
*p++ = '\v';
break;
}
arg++;
@ -94,10 +101,14 @@ grub_cmd_echo (grub_extcmd_context_t ctxt, int argc, char **args)
/* This was not an escaped character, or escaping is not
enabled. */
grub_printf ("%c", *arg);
*p++ = *arg;
arg++;
}
*p = '\0';
grub_xputs (unescaped);
grub_free (unescaped);
/* If another argument follows, insert a space. */
if (i != argc - 1)
grub_printf (" " );
@ -106,6 +117,8 @@ grub_cmd_echo (grub_extcmd_context_t ctxt, int argc, char **args)
if (newline)
grub_printf ("\n");
grub_refresh ();
return 0;
}

View file

@ -36,7 +36,7 @@ static const struct grub_arg_option options[] = {
{0, 0, 0, 0, 0, 0}
};
struct { const char *name; const char *hashname; } aliases[] =
static struct { const char *name; const char *hashname; } aliases[] =
{
{"sha256sum", "sha256"},
{"sha512sum", "sha512"},

View file

@ -83,9 +83,13 @@ legacy_file (const char *filename)
{
char *oldname = NULL;
char *newsuffix;
char *ptr;
for (ptr = buf; *ptr && grub_isspace (*ptr); ptr++);
oldname = entryname;
parsed = grub_legacy_parse (buf, &entryname, &newsuffix);
parsed = grub_legacy_parse (ptr, &entryname, &newsuffix);
grub_free (buf);
buf = NULL;
if (newsuffix)
{
@ -177,9 +181,6 @@ legacy_file (const char *filename)
grub_free (suffix);
grub_free (entrysrc);
if (menu && menu->size)
grub_show_menu (menu, 1);
return GRUB_ERR_NONE;
}
@ -194,8 +195,8 @@ grub_cmd_legacy_source (struct grub_command *cmd,
return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
extractor = (cmd->name[0] == 'e');
new_env = (cmd->name[extractor ? sizeof ("extract_legacy_entries_") - 1
: sizeof ("legacy_") - 1] == 'c');
new_env = (cmd->name[extractor ? (sizeof ("extract_legacy_entries_") - 1)
: (sizeof ("legacy_") - 1)] == 'c');
if (new_env)
grub_cls ();
@ -207,8 +208,15 @@ grub_cmd_legacy_source (struct grub_command *cmd,
ret = legacy_file (args[0]);
if (new_env && !extractor)
grub_env_context_close ();
if (new_env)
{
grub_menu_t menu;
menu = grub_env_get_menu ();
if (menu && menu->size)
grub_show_menu (menu, 1, 0);
if (!extractor)
grub_env_context_close ();
}
if (extractor)
grub_env_extractor_close (!new_env);
@ -761,12 +769,12 @@ GRUB_MOD_INIT(legacycfg)
= grub_register_command ("extract_legacy_entries_source",
grub_cmd_legacy_source,
N_("FILE"),
N_("Parse legacy config in same context taking onl entries"));
N_("Parse legacy config in same context taking only menu entries"));
cmd_configfile_extract
= grub_register_command ("extract_legacy_entries_configfile",
grub_cmd_legacy_source,
N_("FILE"),
N_("Parse legacy config in new context taking onl entries"));
N_("Parse legacy config in new context taking only menu entries"));
cmd_kernel = grub_register_command ("legacy_kernel",
grub_cmd_legacy_kernel,

View file

@ -206,20 +206,6 @@ setparams_prefix (int argc, char **args)
char *p;
char *result;
grub_size_t len = 10;
static const char *escape_characters = "\"\\";
auto char *strescpy (char *, const char *, const char *);
char * strescpy (char *d, const char *s, const char *escapes)
{
while (*s)
{
if (grub_strchr (escapes, *s))
*d++ = '\\';
*d++ = *s++;
}
*d = '\0';
return d;
}
/* Count resulting string length */
for (i = 0; i < argc; i++)
@ -227,7 +213,7 @@ setparams_prefix (int argc, char **args)
len += 3; /* 3 = 1 space + 2 quotes */
p = args[i];
while (*p)
len += grub_strchr (escape_characters, *p++) ? 2 : 1;
len += (*p++ == '\'' ? 3 : 1);
}
result = grub_malloc (len + 2);
@ -235,17 +221,17 @@ setparams_prefix (int argc, char **args)
return 0;
grub_strcpy (result, "setparams");
i = 9;
p = result + 9;
for (j = 0; j < argc; j++)
{
result[i++] = ' ';
result[i++] = '"';
i = strescpy (result + i, args[j], escape_characters) - result;
result[i++] = '"';
*p++ = ' ';
*p++ = '\'';
p = grub_strchrsub (p, args[j], '\'', "'\\''");
*p++ = '\'';
}
result[i++] = '\n';
result[i] = '\0';
*p++ = '\n';
*p = '\0';
return result;
}

View file

@ -87,7 +87,6 @@ set_matches (char **varnames, char *str, grub_size_t nmatches,
static grub_err_t
grub_cmd_regexp (grub_extcmd_context_t ctxt, int argc, char **args)
{
int argn = 0;
regex_t regex;
int ret;
grub_size_t s;

View file

@ -32,7 +32,7 @@ struct pci_register
unsigned size;
};
struct pci_register pci_registers[] =
static struct pci_register pci_registers[] =
{
{"VENDOR_ID", GRUB_PCI_REG_VENDOR , 2},
{"DEVICE_ID", GRUB_PCI_REG_DEVICE , 2},

View file

@ -210,11 +210,11 @@ grub_cmd_terminal_input (grub_command_t cmd __attribute__ ((unused)),
(void) GRUB_FIELD_MATCH (grub_term_inputs, struct abstract_terminal *, init);
(void) GRUB_FIELD_MATCH (grub_term_inputs, struct abstract_terminal *, fini);
return handle_command (argc, args,
(struct abstract_terminal **) &grub_term_inputs,
(struct abstract_terminal **) &grub_term_inputs_disabled,
grub_term_input_autoload,
N_ ("Active input terminals:"),
N_ ("Available input terminals:"));
(struct abstract_terminal **) (void *) &grub_term_inputs,
(struct abstract_terminal **) (void *) &grub_term_inputs_disabled,
grub_term_input_autoload,
N_ ("Active input terminals:"),
N_ ("Available input terminals:"));
}
static grub_err_t
@ -225,11 +225,12 @@ grub_cmd_terminal_output (grub_command_t cmd __attribute__ ((unused)),
(void) GRUB_FIELD_MATCH (grub_term_outputs, struct abstract_terminal *, name);
(void) GRUB_FIELD_MATCH (grub_term_outputs, struct abstract_terminal *, init);
(void) GRUB_FIELD_MATCH (grub_term_outputs, struct abstract_terminal *, fini);
return handle_command (argc, args, (struct abstract_terminal **) &grub_term_outputs,
(struct abstract_terminal **) &grub_term_outputs_disabled,
grub_term_output_autoload,
N_ ("Active output terminals:"),
N_ ("Available output terminals:"));
return handle_command (argc, args,
(struct abstract_terminal **) (void *) &grub_term_outputs,
(struct abstract_terminal **) (void *) &grub_term_outputs_disabled,
grub_term_output_autoload,
N_ ("Active output terminals:"),
N_ ("Available output terminals:"));
}
static grub_command_t cmd_terminal_input, cmd_terminal_output;

View file

@ -266,7 +266,6 @@ match_files (const char *prefix, const char *suffix, const char *end,
const regex_t *regexp)
{
int i;
int error;
char **files;
unsigned nfile;
char *dir;
@ -440,8 +439,6 @@ wildcard_expand (const char *s, char ***strs)
else if (*start == '/') /* no device part */
{
char **r;
unsigned n;
char *root;
char *prefix;

View file

@ -624,6 +624,11 @@ GRUB_MOD_INIT(biosdisk)
((cdrp->media_type & GRUB_BIOSDISK_CDTYPE_MASK)
== GRUB_BIOSDISK_CDTYPE_NO_EMUL))
cd_drive = cdrp->drive_no;
/* Since diskboot.S rejects devices over 0x90 it must be a CD booted with
cdboot.S
*/
if (grub_boot_drive >= 0x90)
cd_drive = grub_boot_drive;
grub_disk_dev_register (&grub_biosdisk_dev);
}

View file

@ -62,11 +62,10 @@ ofdisk_hash_find (const char *devpath)
}
static struct ofdisk_hash_ent *
ofdisk_hash_add (char *devpath)
ofdisk_hash_add_real (char *devpath)
{
struct ofdisk_hash_ent *p;
struct ofdisk_hash_ent **head = &ofdisk_hash[ofdisk_hash_fn(devpath)];
struct ofdisk_hash_ent *p, *pcan;
char *curcan;
p = grub_malloc(sizeof (*p));
if (!p)
@ -76,17 +75,27 @@ ofdisk_hash_add (char *devpath)
p->next = *head;
p->shortest = 0;
*head = p;
return p;
}
static struct ofdisk_hash_ent *
ofdisk_hash_add (char *devpath, char *curcan)
{
struct ofdisk_hash_ent *p, *pcan;
p = ofdisk_hash_add_real (devpath);
grub_dprintf ("disk", "devpath = %s, canonical = %s\n", devpath, curcan);
curcan = grub_ieee1275_canonicalise_devname (devpath);
if (!curcan)
{
grub_errno = GRUB_ERR_NONE;
p->shortest = devpath;
return p;
}
pcan = ofdisk_hash_find (curcan);
if (!pcan)
pcan = ofdisk_hash_add (curcan);
pcan = ofdisk_hash_add_real (curcan);
else
grub_free (curcan);
@ -118,17 +127,22 @@ scan (void)
return 0;
grub_dprintf ("disk", "disk name = %s\n", alias->name);
grub_dprintf ("disk", "disk name = %s, path = %s\n", alias->name,
alias->path);
op = ofdisk_hash_find (alias->path);
op = ofdisk_hash_find (alias->name);
if (!op)
{
char *name = grub_strdup (alias->name);
if (!name)
char *can = grub_strdup (alias->path);
if (!name || !can)
{
grub_errno = GRUB_ERR_NONE;
grub_free (name);
grub_free (can);
return 0;
}
op = ofdisk_hash_add (name);
op = ofdisk_hash_add (name, can);
}
return 0;
}
@ -247,7 +261,7 @@ grub_ofdisk_open (const char *name, grub_disk_t disk)
struct ofdisk_hash_ent *op;
op = ofdisk_hash_find (devpath);
if (!op)
op = ofdisk_hash_add (devpath);
op = ofdisk_hash_add (devpath, NULL);
else
grub_free (devpath);
if (!op)

View file

@ -222,7 +222,7 @@ static grub_extcmd_t cmd;
GRUB_MOD_INIT(loopback)
{
cmd = grub_register_extcmd ("loopback", grub_cmd_loopback, 0,
N_("[-d|-p] DEVICENAME FILE."),
N_("[-d] DEVICENAME FILE."),
N_("Make a device of a file."), options);
grub_disk_dev_register (&grub_loopback_dev);
}

View file

@ -45,6 +45,7 @@ grub_lvm_getvalue (char **p, char *str)
return grub_strtoul (*p, NULL, 10);
}
#if 0
static int
grub_lvm_checkvalue (char **p, char *str, char *tmpl)
{
@ -57,6 +58,7 @@ grub_lvm_checkvalue (char **p, char *str, char *tmpl)
return 0;
return (grub_memcmp (*p + 1, tmpl, tmpllen) == 0 && (*p)[tmpllen + 1] == '"');
}
#endif
static int
grub_lvm_check_flag (char *p, char *str, char *flag)
@ -100,7 +102,7 @@ grub_lvm_iterate (int (*hook) (const char *name))
struct grub_lvm_lv *lv;
if (vg->lvs)
for (lv = vg->lvs; lv; lv = lv->next)
if (hook (lv->name))
if (lv->visible && hook (lv->name))
return 1;
}
@ -164,11 +166,10 @@ grub_lvm_close (grub_disk_t disk __attribute ((unused)))
}
static grub_err_t
grub_lvm_read (grub_disk_t disk, grub_disk_addr_t sector,
grub_size_t size, char *buf)
read_lv (struct grub_lvm_lv *lv, grub_disk_addr_t sector,
grub_size_t size, char *buf)
{
grub_err_t err = 0;
struct grub_lvm_lv *lv = disk->data;
struct grub_lvm_vg *vg = lv->vg;
struct grub_lvm_segment *seg = lv->segments;
struct grub_lvm_pv *pv;
@ -176,6 +177,9 @@ grub_lvm_read (grub_disk_t disk, grub_disk_addr_t sector,
grub_uint64_t extent;
unsigned int i;
if (!lv)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown volume");
extent = grub_divmod64 (sector, vg->extent_size, NULL);
/* Find the right segment. */
@ -190,59 +194,88 @@ grub_lvm_read (grub_disk_t disk, grub_disk_addr_t sector,
seg++;
}
if (seg->stripe_count == 1)
if (i == lv->segment_count)
return grub_error (GRUB_ERR_READ_ERROR, "incorrect segment");
switch (seg->type)
{
/* This segment is linear, so that's easy. We just need to find
out the offset in the physical volume and read SIZE bytes
from that. */
struct grub_lvm_stripe *stripe = seg->stripes;
grub_uint64_t seg_offset; /* Offset of the segment in PV device. */
case GRUB_LVM_STRIPED:
if (seg->stripe_count == 1)
{
/* This segment is linear, so that's easy. We just need to find
out the offset in the physical volume and read SIZE bytes
from that. */
struct grub_lvm_stripe *stripe = seg->stripes;
grub_uint64_t seg_offset; /* Offset of the segment in PV device. */
pv = stripe->pv;
seg_offset = ((grub_uint64_t) stripe->start
* (grub_uint64_t) vg->extent_size) + pv->start;
pv = stripe->pv;
seg_offset = ((grub_uint64_t) stripe->start
* (grub_uint64_t) vg->extent_size) + pv->start;
offset = sector - ((grub_uint64_t) seg->start_extent
* (grub_uint64_t) vg->extent_size) + seg_offset;
offset = sector - ((grub_uint64_t) seg->start_extent
* (grub_uint64_t) vg->extent_size) + seg_offset;
}
else
{
/* This is a striped segment. We have to find the right PV
similar to RAID0. */
struct grub_lvm_stripe *stripe = seg->stripes;
grub_uint32_t a, b;
grub_uint64_t seg_offset; /* Offset of the segment in PV device. */
unsigned int stripenr;
offset = sector - ((grub_uint64_t) seg->start_extent
* (grub_uint64_t) vg->extent_size);
a = grub_divmod64 (offset, seg->stripe_size, NULL);
grub_divmod64 (a, seg->stripe_count, &stripenr);
a = grub_divmod64 (offset, seg->stripe_size * seg->stripe_count, NULL);
grub_divmod64 (offset, seg->stripe_size, &b);
offset = a * seg->stripe_size + b;
stripe += stripenr;
pv = stripe->pv;
seg_offset = ((grub_uint64_t) stripe->start
* (grub_uint64_t) vg->extent_size) + pv->start;
offset += seg_offset;
}
/* Check whether we actually know the physical volume we want to
read from. */
if (pv->disk)
err = grub_disk_read (pv->disk, offset, 0,
size << GRUB_DISK_SECTOR_BITS, buf);
else
err = grub_error (GRUB_ERR_UNKNOWN_DEVICE,
"physical volume %s not found", pv->name);
return err;
case GRUB_LVM_MIRROR:
i = 0;
while (1)
{
if (!seg->mirrors[i].lv)
err = grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown volume '%s'",
seg->mirrors[i].lvname);
else
err = read_lv (seg->mirrors[i].lv, sector, size, buf);
if (!err)
return err;
if (++i >= seg->mirror_count)
return err;
grub_errno = GRUB_ERR_NONE;
}
}
else
{
/* This is a striped segment. We have to find the right PV
similar to RAID0. */
struct grub_lvm_stripe *stripe = seg->stripes;
grub_uint32_t a, b;
grub_uint64_t seg_offset; /* Offset of the segment in PV device. */
unsigned int stripenr;
return grub_error (GRUB_ERR_IO, "unknown LVM segment");
}
offset = sector - ((grub_uint64_t) seg->start_extent
* (grub_uint64_t) vg->extent_size);
a = grub_divmod64 (offset, seg->stripe_size, NULL);
grub_divmod64 (a, seg->stripe_count, &stripenr);
a = grub_divmod64 (offset, seg->stripe_size * seg->stripe_count, NULL);
grub_divmod64 (offset, seg->stripe_size, &b);
offset = a * seg->stripe_size + b;
stripe += stripenr;
pv = stripe->pv;
seg_offset = ((grub_uint64_t) stripe->start
* (grub_uint64_t) vg->extent_size) + pv->start;
offset += seg_offset;
}
/* Check whether we actually know the physical volume we want to
read from. */
if (pv->disk)
err = grub_disk_read (pv->disk, offset, 0,
size << GRUB_DISK_SECTOR_BITS, buf);
else
err = grub_error (GRUB_ERR_UNKNOWN_DEVICE,
"physical volume %s not found", pv->name);
return err;
static grub_err_t
grub_lvm_read (grub_disk_t disk, grub_disk_addr_t sector,
grub_size_t size, char *buf)
{
return read_lv (disk->data, sector, size, buf);
}
static grub_err_t
@ -303,7 +336,7 @@ grub_lvm_scan_device (const char *name)
if (i == GRUB_LVM_LABEL_SCAN_SECTORS)
{
#ifdef GRUB_UTIL
grub_util_info ("no LVM signature found\n");
grub_util_info ("no LVM signature found");
#endif
goto fail;
}
@ -533,11 +566,7 @@ grub_lvm_scan_device (const char *name)
lv->size = 0;
if (!grub_lvm_check_flag (p, "status", "VISIBLE"))
{
skip_lv = 1;
goto lv_parsed;
}
lv->visible = grub_lvm_check_flag (p, "status", "VISIBLE");
lv->segment_count = grub_lvm_getvalue (&p, "segment_count = ");
if (p == NULL)
@ -552,7 +581,6 @@ grub_lvm_scan_device (const char *name)
for (i = 0; i < lv->segment_count; i++)
{
struct grub_lvm_stripe *stripe;
p = grub_strstr (p, "segment");
if (p == NULL)
@ -580,78 +608,147 @@ grub_lvm_scan_device (const char *name)
goto lvs_segment_fail;
}
if (grub_lvm_checkvalue (&p, "type = ", "snapshot"))
{
/* Found a snapshot, give up and move on. */
skip_lv = 1;
break;
}
seg->stripe_count = grub_lvm_getvalue (&p, "stripe_count = ");
p = grub_strstr (p, "type = \"");
if (p == NULL)
{
#ifdef GRUB_UTIL
grub_util_info ("unknown stripe_count\n");
#endif
goto lvs_segment_fail;
}
goto lvs_segment_fail;
p += sizeof("type = \"") - 1;
lv->size += seg->extent_count * vg->extent_size;
if (seg->stripe_count != 1)
seg->stripe_size = grub_lvm_getvalue (&p, "stripe_size = ");
if (grub_memcmp (p, "striped\"",
sizeof ("striped\"") - 1) == 0)
{
struct grub_lvm_stripe *stripe;
seg->stripes = grub_malloc (sizeof (*stripe)
* seg->stripe_count);
stripe = seg->stripes;
seg->type = GRUB_LVM_STRIPED;
seg->stripe_count = grub_lvm_getvalue (&p, "stripe_count = ");
if (p == NULL)
{
#ifdef GRUB_UTIL
grub_util_info ("unknown stripe_count\n");
#endif
goto lvs_segment_fail;
}
p = grub_strstr (p, "stripes = [");
if (p == NULL)
if (seg->stripe_count != 1)
seg->stripe_size = grub_lvm_getvalue (&p, "stripe_size = ");
seg->stripes = grub_malloc (sizeof (*stripe)
* seg->stripe_count);
stripe = seg->stripes;
p = grub_strstr (p, "stripes = [");
if (p == NULL)
{
#ifdef GRUB_UTIL
grub_util_info ("unknown stripes\n");
#endif
goto lvs_segment_fail2;
}
p += sizeof("stripes = [") - 1;
for (j = 0; j < seg->stripe_count; j++)
{
char *pvname;
p = grub_strchr (p, '"');
if (p == NULL)
continue;
q = ++p;
while (*q != '"')
q++;
s = q - p;
pvname = grub_malloc (s + 1);
if (pvname == NULL)
goto lvs_segment_fail2;
grub_memcpy (pvname, p, s);
pvname[s] = '\0';
if (vg->pvs)
for (pv = vg->pvs; pv; pv = pv->next)
{
if (! grub_strcmp (pvname, pv->name))
{
stripe->pv = pv;
break;
}
}
grub_free(pvname);
stripe->start = grub_lvm_getvalue (&p, ",");
if (p == NULL)
continue;
stripe++;
}
}
else if (grub_memcmp (p, "mirror\"", sizeof ("mirror\"") - 1)
== 0)
{
seg->type = GRUB_LVM_MIRROR;
seg->mirror_count = grub_lvm_getvalue (&p, "mirror_count = ");
if (p == NULL)
{
#ifdef GRUB_UTIL
grub_util_info ("unknown mirror_count\n");
#endif
goto lvs_segment_fail;
}
seg->mirrors = grub_zalloc (sizeof (seg->mirrors[0])
* seg->mirror_count);
p = grub_strstr (p, "mirrors = [");
if (p == NULL)
{
#ifdef GRUB_UTIL
grub_util_info ("unknown mirrors\n");
#endif
goto lvs_segment_fail2;
}
p += sizeof("mirrors = [") - 1;
for (j = 0; j < seg->mirror_count; j++)
{
char *lvname;
p = grub_strchr (p, '"');
if (p == NULL)
continue;
q = ++p;
while (*q != '"')
q++;
s = q - p;
lvname = grub_malloc (s + 1);
if (lvname == NULL)
goto lvs_segment_fail2;
grub_memcpy (lvname, p, s);
lvname[s] = '\0';
seg->mirrors[j].lvname = lvname;
p = q + 1;
}
}
else
{
#ifdef GRUB_UTIL
grub_util_info ("unknown stripes\n");
char *p2;
p2 = grub_strchr (p, '"');
if (p2)
*p2 = 0;
grub_util_info ("unknown LVM type %s\n", p);
if (p2)
*p2 ='"';
#endif
goto lvs_segment_fail2;
}
p += sizeof("stripes = [") - 1;
for (j = 0; j < seg->stripe_count; j++)
{
char *pvname;
p = grub_strchr (p, '"');
if (p == NULL)
continue;
q = ++p;
while (*q != '"')
q++;
s = q - p;
pvname = grub_malloc (s + 1);
if (pvname == NULL)
goto lvs_segment_fail2;
grub_memcpy (pvname, p, s);
pvname[s] = '\0';
if (vg->pvs)
for (pv = vg->pvs; pv; pv = pv->next)
{
if (! grub_strcmp (pvname, pv->name))
{
stripe->pv = pv;
break;
}
}
grub_free(pvname);
stripe->start = grub_lvm_getvalue (&p, ",");
if (p == NULL)
continue;
stripe++;
/* Found a non-supported type, give up and move on. */
skip_lv = 1;
break;
}
seg++;
@ -663,7 +760,6 @@ grub_lvm_scan_device (const char *name)
goto fail4;
}
lv_parsed:
if (p != NULL)
p = grub_strchr (p, '}');
if (p == NULL)
@ -690,6 +786,20 @@ grub_lvm_scan_device (const char *name)
}
}
/* Match mirrors */
{
struct grub_lvm_lv *lv1;
struct grub_lvm_lv *lv2;
for (lv1 = vg->lvs; lv1; lv1 = lv1->next)
for (i = 0; i < lv1->segment_count; i++)
if (lv1->segments[i].type == GRUB_LVM_MIRROR)
for (j = 0; j < lv1->segments[i].mirror_count; j++)
for (lv2 = vg->lvs; lv2; lv2 = lv2->next)
if (grub_strcmp (lv2->name + grub_strlen (vg->name) + 1,
lv1->segments[i].mirrors[j].lvname) == 0)
lv1->segments[i].mirrors[j].lv = lv2;
}
vg->next = vg_list;
vg_list = vg;
}
@ -762,5 +872,6 @@ GRUB_MOD_INIT(lvm)
GRUB_MOD_FINI(lvm)
{
grub_disk_dev_unregister (&grub_lvm_dev);
vg_list = NULL;
/* FIXME: free the lvm list. */
}

View file

@ -105,12 +105,11 @@ static grub_err_t
grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array,
grub_disk_addr_t *start_sector)
{
grub_disk_addr_t sector;
grub_disk_addr_t sector = 0;
grub_uint64_t size;
struct grub_raid_super_1x sb;
grub_uint8_t minor_version;
/* The sector where the mdraid 0.90 superblock is stored, if available. */
size = grub_disk_get_size (disk);
/* Check for an 1.x superblock.
@ -123,6 +122,9 @@ grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array,
for (minor_version = 0; minor_version < 3; ++minor_version)
{
if (size == GRUB_DISK_SIZE_UNKNOWN && minor_version == 0)
continue;
switch (minor_version)
{
case 0:
@ -140,24 +142,28 @@ grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array,
&sb))
return grub_errno;
if (sb.magic != SB_MAGIC)
if (grub_le_to_cpu32 (sb.magic) != SB_MAGIC
|| grub_le_to_cpu64 (sb.super_offset) != sector)
continue;
{
grub_uint64_t sb_size;
struct grub_raid_super_1x *real_sb;
grub_uint32_t level;
if (sb.major_version != 1)
if (grub_le_to_cpu32 (sb.major_version) != 1)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"Unsupported RAID version: %d",
sb.major_version);
grub_le_to_cpu32 (sb.major_version));
level = grub_le_to_cpu32 (sb.level);
/* Multipath. */
if ((int) sb.level == -4)
sb.level = 1;
if ((int) level == -4)
level = 1;
if (sb.level != 0 && sb.level != 1 && sb.level != 4 &&
sb.level != 5 && sb.level != 6 && sb.level != 10)
if (level != 0 && level != 1 && level != 4 &&
level != 5 && level != 6 && level != 10)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"Unsupported RAID level: %d", sb.level);
@ -186,14 +192,19 @@ grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array,
array->level = grub_le_to_cpu32 (real_sb->level);
array->layout = grub_le_to_cpu32 (real_sb->layout);
array->total_devs = grub_le_to_cpu32 (real_sb->raid_disks);
array->disk_size = grub_le_to_cpu64 (real_sb->size);
array->chunk_size = grub_le_to_cpu32 (real_sb->chunksize);
if (grub_le_to_cpu32 (real_sb->dev_number) <
grub_le_to_cpu32 (real_sb->max_dev))
array->index = grub_le_to_cpu16
(real_sb->dev_roles[grub_le_to_cpu32 (real_sb->dev_number)]);
if (real_sb->size)
array->disk_size = grub_le_to_cpu64 (real_sb->size);
else
array->index = 0xffff; /* disk will be later not used! */
array->disk_size = grub_le_to_cpu64 (real_sb->data_size);
array->chunk_size = grub_le_to_cpu32 (real_sb->chunksize);
if (grub_le_to_cpu32 (real_sb->dev_number) >=
grub_le_to_cpu32 (real_sb->max_dev))
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"spares aren't implemented");
array->index = grub_le_to_cpu16
(real_sb->dev_roles[grub_le_to_cpu32 (real_sb->dev_number)]);
array->uuid_len = 16;
array->uuid = grub_malloc (16);
if (!array->uuid)
@ -204,7 +215,7 @@ grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array,
grub_memcpy (array->uuid, real_sb->set_uuid, 16);
*start_sector = real_sb->data_offset;
*start_sector = grub_le_to_cpu64 (real_sb->data_offset);
grub_free (real_sb);
return 0;

View file

@ -167,42 +167,52 @@ grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array,
grub_uint64_t size;
struct grub_raid_super_09 sb;
grub_uint32_t *uuid;
grub_uint32_t level;
/* The sector where the mdraid 0.90 superblock is stored, if available. */
size = grub_disk_get_size (disk);
if (size == GRUB_DISK_SIZE_UNKNOWN)
return grub_error (GRUB_ERR_OUT_OF_RANGE, "not 0.9x raid");
sector = NEW_SIZE_SECTORS (size);
if (grub_disk_read (disk, sector, 0, SB_BYTES, &sb))
return grub_errno;
/* Look whether there is a mdraid 0.90 superblock. */
if (sb.md_magic != SB_MAGIC)
if (grub_le_to_cpu32 (sb.md_magic) != SB_MAGIC)
return grub_error (GRUB_ERR_OUT_OF_RANGE, "not 0.9x raid");
if (sb.major_version != 0 || sb.minor_version != 90)
if (grub_le_to_cpu32 (sb.major_version) != 0
|| grub_le_to_cpu32 (sb.minor_version) != 90)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"unsupported RAID version: %d.%d",
sb.major_version, sb.minor_version);
grub_le_to_cpu32 (sb.major_version),
grub_le_to_cpu32 (sb.minor_version));
/* FIXME: Check the checksum. */
level = grub_le_to_cpu32 (sb.level);
/* Multipath. */
if ((int) sb.level == -4)
sb.level = 1;
if ((int) level == -4)
level = 1;
if (sb.level != 0 && sb.level != 1 && sb.level != 4 &&
sb.level != 5 && sb.level != 6 && sb.level != 10)
if (level != 0 && level != 1 && level != 4 &&
level != 5 && level != 6 && level != 10)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"unsupported RAID level: %d", sb.level);
"unsupported RAID level: %d", level);
if (grub_le_to_cpu32 (sb.this_disk.number) == 0xffff
|| grub_le_to_cpu32 (sb.this_disk.number) == 0xfffe)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"spares aren't implemented");
array->name = NULL;
array->number = sb.md_minor;
array->level = sb.level;
array->layout = sb.layout;
array->total_devs = sb.raid_disks;
array->disk_size = (sb.size) ? sb.size * 2 : sector;
array->chunk_size = sb.chunk_size >> 9;
array->index = sb.this_disk.number;
array->number = grub_le_to_cpu32 (sb.md_minor);
array->level = level;
array->layout = grub_le_to_cpu32 (sb.layout);
array->total_devs = grub_le_to_cpu32 (sb.raid_disks);
array->disk_size = (sb.size) ? grub_le_to_cpu32 (sb.size) * 2 : sector;
array->chunk_size = grub_le_to_cpu32 (sb.chunk_size) >> 9;
array->index = grub_le_to_cpu32 (sb.this_disk.number);
array->uuid_len = 16;
array->uuid = grub_malloc (16);
if (!array->uuid)

View file

@ -97,10 +97,10 @@ grub_raid_memberlist (grub_disk_t disk)
unsigned int i;
for (i = 0; i < array->total_devs; i++)
if (array->device[i])
if (array->members[i].device)
{
tmp = grub_malloc (sizeof (*tmp));
tmp->disk = array->device[i];
tmp->disk = array->members[i].device;
tmp->next = list;
list = tmp;
}
@ -255,13 +255,13 @@ grub_raid_read (grub_disk_t disk, grub_disk_addr_t sector,
k = disknr;
for (j = 0; j < far; j++)
{
if (array->device[k])
if (array->members[k].device)
{
if (grub_errno == GRUB_ERR_READ_ERROR)
grub_errno = GRUB_ERR_NONE;
err = grub_disk_read (array->device[k],
array->start_sector[k] +
err = grub_disk_read (array->members[k].device,
array->members[k].start_sector +
read_sector + j * far_ofs + b,
0,
read_size << GRUB_DISK_SECTOR_BITS,
@ -367,14 +367,14 @@ grub_raid_read (grub_disk_t disk, grub_disk_addr_t sector,
read_size = size;
e = 0;
if (array->device[disknr])
if (array->members[disknr].device)
{
/* Reset read error. */
if (grub_errno == GRUB_ERR_READ_ERROR)
grub_errno = GRUB_ERR_NONE;
err = grub_disk_read (array->device[disknr],
array->start_sector[disknr] +
err = grub_disk_read (array->members[disknr].device,
array->members[disknr].start_sector +
read_sector + b, 0,
read_size << GRUB_DISK_SECTOR_BITS,
buf);
@ -500,6 +500,21 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
/* Do some checks before adding the device to the array. */
if (new_array->index >= array->allocated_devs)
{
void *tmp;
unsigned int newnum = 2 * (new_array->index + 1);
tmp = grub_realloc (array->members, newnum
* sizeof (array->members[0]));
if (!tmp)
return grub_errno;
array->members = tmp;
grub_memset (array->members + array->allocated_devs,
0, (newnum - array->allocated_devs)
* sizeof (array->members[0]));
array->allocated_devs = newnum;
}
/* FIXME: Check whether the update time of the superblocks are
the same. */
@ -507,14 +522,16 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
/* We found more members of the array than the array
actually has according to its superblock. This shouldn't
happen normally. */
grub_dprintf ("raid", "array->nr_devs > array->total_devs (%d)?!?",
array->total_devs);
return grub_error (GRUB_ERR_BAD_DEVICE,
"superfluous RAID member (%d found)",
array->total_devs);
if (array->device[new_array->index] != NULL)
if (array->members[new_array->index].device != NULL)
/* We found multiple devices with the same number. Again,
this shouldn't happen. */
grub_dprintf ("raid", "Found two disks with the number %d?!?",
new_array->number);
return grub_error (GRUB_ERR_BAD_DEVICE,
"found two disks with the index %d for RAID %s",
new_array->index, array->name);
if (new_array->disk_size < array->disk_size)
array->disk_size = new_array->disk_size;
@ -536,14 +553,24 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
#ifdef GRUB_UTIL
array->driver = raid;
#endif
grub_memset (&array->device, 0, sizeof (array->device));
grub_memset (&array->start_sector, 0, sizeof (array->start_sector));
array->allocated_devs = 32;
if (new_array->index >= array->allocated_devs)
array->allocated_devs = 2 * (new_array->index + 1);
array->members = grub_zalloc (array->allocated_devs
* sizeof (array->members[0]));
if (!array->members)
{
grub_free (new_array->uuid);
return grub_errno;
}
if (! array->name)
{
for (p = array_list; p != NULL; p = p->next)
{
if (! p->name && p->number == array->number)
if (p->number == array->number)
break;
}
}
@ -582,6 +609,7 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
array->name = grub_xasprintf ("md%d", array->number);
if (! array->name)
{
grub_free (array->members);
grub_free (array->uuid);
grub_free (array);
@ -597,6 +625,7 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
if (! new_name)
{
grub_free (array->members);
grub_free (array->uuid);
grub_free (array);
@ -609,6 +638,10 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
grub_dprintf ("raid", "Found array %s (%s)\n", array->name,
scanner_name);
#ifdef GRUB_UTIL
grub_util_info ("Found array %s (%s)", array->name,
scanner_name);
#endif
/* Add our new array to the list. */
array->next = array_list;
@ -621,8 +654,8 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
}
/* Add the device to the array. */
array->device[new_array->index] = disk;
array->start_sector[new_array->index] = start_sector;
array->members[new_array->index].device = disk;
array->members[new_array->index].start_sector = start_sector;
array->nr_devs++;
return 0;
@ -639,14 +672,15 @@ free_array (void)
while (array)
{
struct grub_raid_array *p;
int i;
unsigned int i;
p = array;
array = array->next;
for (i = 0; i < GRUB_RAID_MAX_DEVICES; i++)
if (p->device[i])
grub_disk_close (p->device[i]);
for (i = 0; i < p->allocated_devs; i++)
if (p->members[i].device)
grub_disk_close (p->members[i].device);
grub_free (p->members);
grub_free (p->uuid);
grub_free (p->name);
@ -666,7 +700,12 @@ grub_raid_register (grub_raid_t raid)
struct grub_raid_array array;
grub_disk_addr_t start_sector;
grub_dprintf ("raid", "Scanning for RAID devices on disk %s\n", name);
grub_dprintf ("raid", "Scanning for %s RAID devices on disk %s\n",
grub_raid_list->name, name);
#ifdef GRUB_UTIL
grub_util_info ("Scanning for %s RAID devices on disk %s",
grub_raid_list->name, name);
#endif
disk = grub_disk_open (name);
if (!disk)

View file

@ -45,7 +45,9 @@ grub_raid5_recover (struct grub_raid_array *array, int disknr,
if (i == disknr)
continue;
err = grub_disk_read (array->device[i], sector, 0, size, buf2);
err = grub_disk_read (array->members[i].device,
array->members[i].start_sector + sector,
0, size, buf2);
if (err)
{

View file

@ -118,8 +118,10 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p,
bad1 = i;
else
{
if ((array->device[pos]) &&
(! grub_disk_read (array->device[pos], sector, 0, size, buf)))
if ((array->members[pos].device) &&
(! grub_disk_read (array->members[pos].device,
array->members[i].start_sector + sector,
0, size, buf)))
{
grub_raid_block_xor (pbuf, buf, size);
grub_raid_block_mul (raid6_table2[i][i], buf, size);
@ -148,21 +150,24 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p,
if (bad2 < 0)
{
/* One bad device */
if ((array->device[p]) &&
(! grub_disk_read (array->device[p], sector, 0, size, buf)))
if ((array->members[p].device) &&
(! grub_disk_read (array->members[p].device,
array->members[i].start_sector + sector,
0, size, buf)))
{
grub_raid_block_xor (buf, pbuf, size);
goto quit;
}
if (! array->device[q])
if (! array->members[q].device)
{
grub_error (GRUB_ERR_READ_ERROR, "not enough disk to restore");
goto quit;
}
grub_errno = GRUB_ERR_NONE;
if (grub_disk_read (array->device[q], sector, 0, size, buf))
if (grub_disk_read (array->members[q].device,
array->members[i].start_sector + sector, 0, size, buf))
goto quit;
grub_raid_block_xor (buf, qbuf, size);
@ -174,18 +179,22 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p,
/* Two bad devices */
grub_uint8_t c;
if ((! array->device[p]) || (! array->device[q]))
if ((! array->members[p].device) || (! array->members[q].device))
{
grub_error (GRUB_ERR_READ_ERROR, "not enough disk to restore");
goto quit;
}
if (grub_disk_read (array->device[p], sector, 0, size, buf))
if (grub_disk_read (array->members[p].device,
array->members[i].start_sector + sector,
0, size, buf))
goto quit;
grub_raid_block_xor (pbuf, buf, size);
if (grub_disk_read (array->device[q], sector, 0, size, buf))
if (grub_disk_read (array->members[q].device,
array->members[i].start_sector + sector,
0, size, buf))
goto quit;
grub_raid_block_xor (qbuf, buf, size);

View file

@ -506,7 +506,7 @@ grub_scsi_read (grub_disk_t disk, grub_disk_addr_t sector,
if (scsi->blocksize != GRUB_DISK_SECTOR_SIZE)
{
unsigned spb = scsi->blocksize >> GRUB_DISK_SECTOR_BITS;
if (! (spb != 0 && (scsi->blocksize & GRUB_DISK_SECTOR_SIZE) == 0))
if (spb == 0 || (scsi->blocksize & (GRUB_DISK_SECTOR_SIZE - 1)) != 0)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"unsupported SCSI block size");

View file

@ -70,7 +70,11 @@ static int first_available_slot = 0;
static grub_err_t
grub_usbms_reset (grub_usb_device_t dev, int interface)
{
return grub_usb_control_msg (dev, 0x21, 255, 0, interface, 0, 0);
grub_usb_err_t u;
u = grub_usb_control_msg (dev, 0x21, 255, 0, interface, 0, 0);
if (u)
return grub_error (GRUB_ERR_IO, "USB error %d", u);
return GRUB_ERR_NONE;
}
static void
@ -408,7 +412,7 @@ static struct grub_scsi_dev grub_usbms_dev =
.write = grub_usbms_write
};
struct grub_usb_attach_desc attach_hook =
static struct grub_usb_attach_desc attach_hook =
{
.class = GRUB_USB_CLASS_MASS_STORAGE,
.hook = grub_usbms_attach

View file

@ -24,7 +24,7 @@
#include <grub/acpi.h>
grub_err_t
grub_machine_efiemu_init_tables ()
grub_machine_efiemu_init_tables (void)
{
grub_uint8_t *ptr;
void *table;

View file

@ -208,7 +208,7 @@ grub_affs_mount (grub_disk_t disk)
rblock = (struct grub_affs_rblock *) rootblock;
/* Read the rootblock. */
grub_disk_read (disk, (disk->total_sectors >> 1) + blocksize, 0,
grub_disk_read (disk, grub_be_to_cpu32 (data->bblock.rootblock), 0,
GRUB_DISK_SECTOR_SIZE * 16, rootblock);
if (grub_errno)
goto fail;
@ -240,7 +240,7 @@ grub_affs_mount (grub_disk_t disk)
data->disk = disk;
data->htsize = grub_be_to_cpu32 (rblock->htsize);
data->diropen.data = data;
data->diropen.block = (disk->total_sectors >> 1);
data->diropen.block = grub_be_to_cpu32 (data->bblock.rootblock);
grub_free (rootblock);
@ -507,7 +507,7 @@ grub_affs_label (grub_device_t device, char **label)
{
/* The rootblock maps quite well on a file header block, it's
something we can use here. */
grub_disk_read (data->disk, disk->total_sectors >> 1,
grub_disk_read (data->disk, grub_be_to_cpu32 (data->bblock.rootblock),
data->blocksize * (GRUB_DISK_SECTOR_SIZE
- GRUB_AFFS_FILE_LOCATION),
sizeof (file), &file);
@ -535,6 +535,9 @@ static struct grub_fs grub_affs_fs =
.read = grub_affs_read,
.close = grub_affs_close,
.label = grub_affs_label,
#ifdef GRUB_UTIL
.reserved_first_sector = 0,
#endif
.next = 0
};

View file

@ -51,7 +51,7 @@ grub_btrfs_mount (grub_disk_t disk)
&data->sblock) != GRUB_ERR_NONE)
goto fail;
if (grub_strncmp ((char *) data->sblock.signature, BTRFS_SIGNATURE, sizeof (BTRFS_SIGNATURE) - 1))
if (grub_memcmp ((char *) data->sblock.signature, BTRFS_SIGNATURE, sizeof (BTRFS_SIGNATURE) - 1))
{
grub_error (GRUB_ERR_BAD_FS, "not a Btrfs filesystem");
goto fail;
@ -60,6 +60,9 @@ grub_btrfs_mount (grub_disk_t disk)
return data;
fail:
if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
grub_error (GRUB_ERR_BAD_FS, "not a Btrfs filesystem");
grub_free (data);
return NULL;
}

View file

@ -354,6 +354,9 @@ static struct grub_fs grub_cpio_fs = {
.open = grub_cpio_open,
.read = grub_cpio_read,
.close = grub_cpio_close,
#ifdef GRUB_UTIL
.reserved_first_sector = 0,
#endif
};
#ifdef MODE_USTAR

View file

@ -229,7 +229,7 @@ struct grub_ext2_inode
};
grub_uint32_t version;
grub_uint32_t acl;
grub_uint32_t dir_acl;
grub_uint32_t size_high;
grub_uint32_t fragment_addr;
grub_uint32_t osd2[3];
};
@ -470,10 +470,41 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
blknr = grub_le_to_cpu32 (indir[rblock % perblock]);
}
/* triple indirect. */
else if (fileblock < INDIRECT_BLOCKS + blksz / 4 * (blksz / 4 + 1)
+ (blksz / 4) * (blksz / 4) * (blksz / 4 + 1))
{
unsigned int perblock = blksz / 4;
unsigned int rblock = fileblock - (INDIRECT_BLOCKS + blksz / 4
* (blksz / 4 + 1));
grub_uint32_t indir[blksz / 4];
if (grub_disk_read (data->disk,
((grub_disk_addr_t)
grub_le_to_cpu32 (inode->blocks.triple_indir_block))
<< log2_blksz,
0, blksz, indir))
return grub_errno;
if (grub_disk_read (data->disk,
((grub_disk_addr_t)
grub_le_to_cpu32 (indir[(rblock / perblock) / perblock]))
<< log2_blksz,
0, blksz, indir))
return grub_errno;
if (grub_disk_read (data->disk,
((grub_disk_addr_t)
grub_le_to_cpu32 (indir[(rblock / perblock) % perblock]))
<< log2_blksz,
0, blksz, indir))
return grub_errno;
blknr = grub_le_to_cpu32 (indir[rblock % perblock]);
}
else
{
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"ext2fs doesn't support triple indirect blocks");
"ext2fs doesn't support quadruple indirect blocks");
}
return blknr;
@ -485,11 +516,12 @@ static grub_ssize_t
grub_ext2_read_file (grub_fshelp_node_t node,
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
unsigned offset, unsigned length),
int pos, grub_size_t len, char *buf)
grub_off_t pos, grub_size_t len, char *buf)
{
return grub_fshelp_read_file (node->data->disk, node, read_hook,
pos, len, buf, grub_ext2_read_block,
node->inode.size,
grub_cpu_to_le32 (node->inode.size)
| (((grub_off_t) grub_cpu_to_le32 (node->inode.size_high)) << 32),
LOG2_EXT2_BLOCK_SIZE (node->data));
}
@ -523,7 +555,7 @@ grub_ext2_read_inode (struct grub_ext2_data *data,
/* Read the inode. */
if (grub_disk_read (data->disk,
((grub_le_to_cpu32 (blkgrp.inode_table_id) + blkno)
(((grub_disk_addr_t) grub_le_to_cpu32 (blkgrp.inode_table_id) + blkno)
<< LOG2_EXT2_BLOCK_SIZE (data)),
EXT2_INODE_SIZE (data) * blkoff,
sizeof (struct grub_ext2_inode), inode))
@ -756,6 +788,7 @@ grub_ext2_open (struct grub_file *file, const char *name)
grub_free (fdiro);
file->size = grub_le_to_cpu32 (data->inode->size);
file->size |= ((grub_off_t) grub_le_to_cpu32 (data->inode->size_high)) << 32;
file->data = data;
file->offset = 0;

View file

@ -178,7 +178,7 @@ enum grub_hfsplus_filetype
/* Internal representation of a catalog key. */
struct grub_hfsplus_catkey_internal
{
int parent;
grub_uint32_t parent;
char *name;
};
@ -520,9 +520,12 @@ grub_hfsplus_cmp_catkey (struct grub_hfsplus_key *keya,
int i;
int diff;
diff = grub_be_to_cpu32 (catkey_a->parent) - catkey_b->parent;
if (diff)
return diff;
/* Safe unsigned comparison */
grub_uint32_t aparent = grub_be_to_cpu32 (catkey_a->parent);
if (aparent > catkey_b->parent)
return 1;
if (aparent < catkey_b->parent)
return -1;
/* Change the filename in keya so the endianness is correct. */
for (i = 0; i < grub_be_to_cpu16 (catkey_a->namelen); i++)
@ -555,15 +558,21 @@ grub_hfsplus_cmp_extkey (struct grub_hfsplus_key *keya,
{
struct grub_hfsplus_extkey *extkey_a = &keya->extkey;
struct grub_hfsplus_extkey_internal *extkey_b = &keyb->extkey;
int diff;
grub_uint32_t akey;
diff = grub_be_to_cpu32 (extkey_a->fileid) - extkey_b->fileid;
if (diff)
return diff;
diff = grub_be_to_cpu32 (extkey_a->start) - extkey_b->start;
return diff;
/* Safe unsigned comparison */
akey = grub_be_to_cpu32 (extkey_a->fileid);
if (akey > extkey_b->fileid)
return 1;
if (akey < extkey_b->fileid)
return -1;
akey = grub_be_to_cpu32 (extkey_a->start);
if (akey > extkey_b->start)
return 1;
if (akey < extkey_b->start)
return -1;
return 0;
}
static char *

View file

@ -808,6 +808,15 @@ grub_iso9660_label (grub_device_t device, char **label)
((grub_uint16_t *) &data->voldesc.volname, 16);
else
*label = grub_strndup ((char *) data->voldesc.volname, 32);
if (*label)
{
char *ptr;
for (ptr = *label; *ptr;ptr++);
ptr--;
while (ptr >= *label && *ptr == ' ')
*ptr-- = 0;
}
grub_free (data);
}
else

View file

@ -1072,7 +1072,11 @@ grub_ntfs_uuid (grub_device_t device, char **uuid)
data = grub_ntfs_mount (disk);
if (data)
{
char *ptr;
*uuid = grub_xasprintf ("%016llx", (unsigned long long) data->uuid);
if (*uuid)
for (ptr = *uuid; *ptr; ptr++)
*ptr = grub_toupper (*ptr);
}
else
*uuid = NULL;

View file

@ -579,6 +579,9 @@ static struct grub_fs grub_sfs_fs =
.read = grub_sfs_read,
.close = grub_sfs_close,
.label = grub_sfs_label,
#ifdef GRUB_UTIL
.reserved_first_sector = 0,
#endif
.next = 0
};

View file

@ -34,9 +34,6 @@
#define U32 grub_le_to_cpu32
#define U64 grub_le_to_cpu64
#define GRUB_UDF_LOG2_BLKSZ 2
#define GRUB_UDF_BLKSZ 2048
#define GRUB_UDF_TAG_IDENT_PVD 0x0001
#define GRUB_UDF_TAG_IDENT_AVDP 0x0002
#define GRUB_UDF_TAG_IDENT_VDP 0x0003
@ -336,6 +333,13 @@ struct grub_udf_lvd
grub_uint8_t part_maps[1608];
} __attribute__ ((packed));
struct grub_udf_aed
{
struct grub_udf_tag tag;
grub_uint32_t prev_ae;
grub_uint32_t ae_len;
} __attribute__ ((packed));
struct grub_udf_data
{
grub_disk_t disk;
@ -343,7 +347,7 @@ struct grub_udf_data
struct grub_udf_pd pds[GRUB_UDF_MAX_PDS];
struct grub_udf_partmap *pms[GRUB_UDF_MAX_PMS];
struct grub_udf_long_ad root_icb;
int npd, npm;
int npd, npm, lbshift;
};
struct grub_fshelp_node
@ -389,7 +393,7 @@ grub_udf_read_icb (struct grub_udf_data *data,
if (grub_errno)
return grub_errno;
if (grub_disk_read (data->disk, block << GRUB_UDF_LOG2_BLKSZ, 0,
if (grub_disk_read (data->disk, block << data->lbshift, 0,
sizeof (struct grub_udf_file_entry),
&node->fe))
return grub_errno;
@ -406,19 +410,26 @@ grub_udf_read_icb (struct grub_udf_data *data,
static grub_disk_addr_t
grub_udf_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
{
char *buf = NULL;
char *ptr;
int len;
grub_ssize_t len;
grub_disk_addr_t filebytes;
if (U16 (node->fe.tag.tag_ident) == GRUB_UDF_TAG_IDENT_FE)
switch (U16 (node->fe.tag.tag_ident))
{
case GRUB_UDF_TAG_IDENT_FE:
ptr = (char *) &node->fe.ext_attr[0] + U32 (node->fe.ext_attr_length);
len = U32 (node->fe.alloc_descs_length);
}
else
{
break;
case GRUB_UDF_TAG_IDENT_EFE:
ptr = (char *) &node->efe.ext_attr[0] + U32 (node->efe.ext_attr_length);
len = U32 (node->efe.alloc_descs_length);
break;
default:
grub_error (GRUB_ERR_BAD_FS, "invalid file entry");
return 0;
}
if ((U16 (node->fe.icbtag.flags) & GRUB_UDF_ICBTAG_FLAG_AD_MASK)
@ -426,43 +437,115 @@ grub_udf_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
{
struct grub_udf_short_ad *ad = (struct grub_udf_short_ad *) ptr;
len /= sizeof (struct grub_udf_short_ad);
filebytes = fileblock * GRUB_UDF_BLKSZ;
while (len > 0)
filebytes = fileblock * U32 (node->data->lvd.bsize);
while (len >= (grub_ssize_t) sizeof (struct grub_udf_short_ad))
{
if (filebytes < U32 (ad->length))
return ((U32 (ad->position) & GRUB_UDF_EXT_MASK) ? 0 :
(grub_udf_get_block (node->data,
node->part_ref,
ad->position)
+ (filebytes / GRUB_UDF_BLKSZ)));
grub_uint32_t adlen = U32 (ad->length) & 0x3fffffff;
grub_uint32_t adtype = U32 (ad->length) >> 30;
if (adtype == 3)
{
struct grub_udf_aed *extension;
grub_disk_addr_t sec = grub_udf_get_block(node->data,
node->part_ref,
ad->position);
if (!buf)
{
buf = grub_malloc (U32 (node->data->lvd.bsize));
if (!buf)
return 0;
}
if (grub_disk_read (node->data->disk, sec << node->data->lbshift,
0, adlen, buf))
goto fail;
filebytes -= U32 (ad->length);
extension = (struct grub_udf_aed *) buf;
if (U16 (extension->tag.tag_ident) != GRUB_UDF_TAG_IDENT_AED)
{
grub_error (GRUB_ERR_BAD_FS, "invalid aed tag");
goto fail;
}
len = U32 (extension->ae_len);
ad = (struct grub_udf_short_ad *)
(buf + sizeof (struct grub_udf_aed));
continue;
}
if (filebytes < adlen)
{
grub_uint32_t ad_pos = ad->position;
grub_free (buf);
return ((U32 (ad_pos) & GRUB_UDF_EXT_MASK) ? 0 :
(grub_udf_get_block (node->data, node->part_ref, ad_pos)
+ (filebytes >> (GRUB_DISK_SECTOR_BITS
+ node->data->lbshift))));
}
filebytes -= adlen;
ad++;
len--;
len -= sizeof (struct grub_udf_short_ad);
}
}
else
{
struct grub_udf_long_ad *ad = (struct grub_udf_long_ad *) ptr;
len /= sizeof (struct grub_udf_long_ad);
filebytes = fileblock * GRUB_UDF_BLKSZ;
while (len > 0)
filebytes = fileblock * U32 (node->data->lvd.bsize);
while (len >= (grub_ssize_t) sizeof (struct grub_udf_long_ad))
{
if (filebytes < U32 (ad->length))
return ((U32 (ad->block.block_num) & GRUB_UDF_EXT_MASK) ? 0 :
(grub_udf_get_block (node->data,
ad->block.part_ref,
ad->block.block_num)
+ (filebytes / GRUB_UDF_BLKSZ)));
grub_uint32_t adlen = U32 (ad->length) & 0x3fffffff;
grub_uint32_t adtype = U32 (ad->length) >> 30;
if (adtype == 3)
{
struct grub_udf_aed *extension;
grub_disk_addr_t sec = grub_udf_get_block(node->data,
ad->block.part_ref,
ad->block.block_num);
if (!buf)
{
buf = grub_malloc (U32 (node->data->lvd.bsize));
if (!buf)
return 0;
}
if (grub_disk_read (node->data->disk, sec << node->data->lbshift,
0, adlen, buf))
goto fail;
filebytes -= U32 (ad->length);
extension = (struct grub_udf_aed *) buf;
if (U16 (extension->tag.tag_ident) != GRUB_UDF_TAG_IDENT_AED)
{
grub_error (GRUB_ERR_BAD_FS, "invalid aed tag");
goto fail;
}
len = U32 (extension->ae_len);
ad = (struct grub_udf_long_ad *)
(buf + sizeof (struct grub_udf_aed));
continue;
}
if (filebytes < adlen)
{
grub_uint32_t ad_block_num = ad->block.block_num;
grub_uint32_t ad_part_ref = ad->block.part_ref;
grub_free (buf);
return ((U32 (ad_block_num) & GRUB_UDF_EXT_MASK) ? 0 :
(grub_udf_get_block (node->data, ad_part_ref,
ad_block_num)
+ (filebytes >> (GRUB_DISK_SECTOR_BITS
+ node->data->lbshift))));
}
filebytes -= adlen;
ad++;
len--;
len -= sizeof (struct grub_udf_long_ad);
}
}
fail:
if (buf)
grub_free (buf);
return 0;
}
@ -471,7 +554,7 @@ grub_udf_read_file (grub_fshelp_node_t node,
void NESTED_FUNC_ATTR
(*read_hook) (grub_disk_addr_t sector,
unsigned offset, unsigned length),
int pos, grub_size_t len, char *buf)
grub_off_t pos, grub_size_t len, char *buf)
{
switch (U16 (node->fe.icbtag.flags) & GRUB_UDF_ICBTAG_FLAG_AD_MASK)
{
@ -496,21 +579,21 @@ grub_udf_read_file (grub_fshelp_node_t node,
}
return grub_fshelp_read_file (node->data->disk, node, read_hook,
pos, len, buf, grub_udf_read_block,
U64 (node->fe.file_size),
GRUB_UDF_LOG2_BLKSZ);
pos, len, buf, grub_udf_read_block,
U64 (node->fe.file_size),
node->data->lbshift);
}
static int sblocklist[] = { 256, 512, 0 };
static unsigned sblocklist[] = { 256, 512, 0 };
static struct grub_udf_data *
grub_udf_mount (grub_disk_t disk)
{
struct grub_udf_data *data = 0;
struct grub_udf_fileset root_fs;
int *sblklist = sblocklist;
grub_uint32_t block;
int i;
unsigned *sblklist;
grub_uint32_t block, vblock;
int i, lbshift;
data = grub_malloc (sizeof (struct grub_udf_data));
if (!data)
@ -518,12 +601,48 @@ grub_udf_mount (grub_disk_t disk)
data->disk = disk;
/* Search for Anchor Volume Descriptor Pointer (AVDP)
* and determine logical block size. */
block = 0;
for (lbshift = 0; lbshift < 4; lbshift++)
{
for (sblklist = sblocklist; *sblklist; sblklist++)
{
struct grub_udf_avdp avdp;
if (grub_disk_read (disk, *sblklist << lbshift, 0,
sizeof (struct grub_udf_avdp), &avdp))
{
grub_error (GRUB_ERR_BAD_FS, "not an UDF filesystem");
goto fail;
}
if (U16 (avdp.tag.tag_ident) == GRUB_UDF_TAG_IDENT_AVDP &&
U32 (avdp.tag.tag_location) == *sblklist)
{
block = U32 (avdp.vds.start);
break;
}
}
if (block)
break;
}
if (!block)
{
grub_error (GRUB_ERR_BAD_FS, "not an UDF filesystem");
goto fail;
}
data->lbshift = lbshift;
/* Search for Volume Recognition Sequence (VRS). */
for (block = 16;; block++)
for (vblock = (32767 >> (lbshift + GRUB_DISK_SECTOR_BITS)) + 1;;
vblock += (2047 >> (lbshift + GRUB_DISK_SECTOR_BITS)) + 1)
{
struct grub_udf_vrs vrs;
if (grub_disk_read (disk, block << GRUB_UDF_LOG2_BLKSZ, 0,
if (grub_disk_read (disk, vblock << lbshift, 0,
sizeof (struct grub_udf_vrs), &vrs))
{
grub_error (GRUB_ERR_BAD_FS, "not an UDF filesystem");
@ -545,39 +664,13 @@ grub_udf_mount (grub_disk_t disk)
}
}
/* Search for Anchor Volume Descriptor Pointer (AVDP). */
while (1)
{
struct grub_udf_avdp avdp;
if (grub_disk_read (disk, *sblklist << GRUB_UDF_LOG2_BLKSZ, 0,
sizeof (struct grub_udf_avdp), &avdp))
{
grub_error (GRUB_ERR_BAD_FS, "not an UDF filesystem");
goto fail;
}
if (U16 (avdp.tag.tag_ident) == GRUB_UDF_TAG_IDENT_AVDP)
{
block = U32 (avdp.vds.start);
break;
}
sblklist++;
if (*sblklist == 0)
{
grub_error (GRUB_ERR_BAD_FS, "not an UDF filesystem");
goto fail;
}
}
data->npd = data->npm = 0;
/* Locate Partition Descriptor (PD) and Logical Volume Descriptor (LVD). */
while (1)
{
struct grub_udf_tag tag;
if (grub_disk_read (disk, block << GRUB_UDF_LOG2_BLKSZ, 0,
if (grub_disk_read (disk, block << lbshift, 0,
sizeof (struct grub_udf_tag), &tag))
{
grub_error (GRUB_ERR_BAD_FS, "not an UDF filesystem");
@ -593,7 +686,7 @@ grub_udf_mount (grub_disk_t disk)
goto fail;
}
if (grub_disk_read (disk, block << GRUB_UDF_LOG2_BLKSZ, 0,
if (grub_disk_read (disk, block << lbshift, 0,
sizeof (struct grub_udf_pd),
&data->pds[data->npd]))
{
@ -609,7 +702,7 @@ grub_udf_mount (grub_disk_t disk)
struct grub_udf_partmap *ppm;
if (grub_disk_read (disk, block << GRUB_UDF_LOG2_BLKSZ, 0,
if (grub_disk_read (disk, block << lbshift, 0,
sizeof (struct grub_udf_lvd),
&data->lvd))
{
@ -673,7 +766,7 @@ grub_udf_mount (grub_disk_t disk)
if (grub_errno)
goto fail;
if (grub_disk_read (disk, block << GRUB_UDF_LOG2_BLKSZ, 0,
if (grub_disk_read (disk, block << lbshift, 0,
sizeof (struct grub_udf_fileset), &root_fs))
{
grub_error (GRUB_ERR_BAD_FS, "not an UDF filesystem");
@ -695,6 +788,43 @@ fail:
return 0;
}
static char *
read_string (grub_uint8_t *raw, grub_size_t sz)
{
grub_uint16_t *utf16 = NULL;
char *ret;
grub_size_t utf16len = 0;
if (raw[0] != 8 && raw[0] != 16)
return NULL;
if (raw[0] == 8)
{
unsigned i;
utf16len = sz - 1;
utf16 = grub_malloc (utf16len * sizeof (utf16[0]));
if (!utf16)
return NULL;
for (i = 0; i < utf16len; i++)
utf16[i] = raw[i + 1];
}
if (raw[0] == 16)
{
unsigned i;
utf16len = (sz - 1) / 2;
utf16 = grub_malloc (utf16len * sizeof (utf16[0]));
if (!utf16)
return NULL;
for (i = 0; i < utf16len; i++)
utf16[i] = (raw[2 * i + 1] << 8) | raw[2*i + 2];
}
ret = grub_malloc (utf16len * 3 + 1);
if (ret)
*grub_utf16_to_utf8 ((grub_uint8_t *) ret, utf16, utf16len) = '\0';
grub_free (utf16);
return ret;
}
static int
grub_udf_iterate_dir (grub_fshelp_node_t dir,
int NESTED_FUNC_ATTR
@ -704,7 +834,7 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir,
{
grub_fshelp_node_t child;
struct grub_udf_file_ident dirent;
grub_uint32_t offset = 0;
grub_off_t offset = 0;
child = grub_malloc (sizeof (struct grub_fshelp_node));
if (!child)
@ -729,57 +859,47 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir,
return 0;
}
child = grub_malloc (sizeof (struct grub_fshelp_node));
if (!child)
return 0;
if (grub_udf_read_icb (dir->data, &dirent.icb, child))
return 0;
offset += sizeof (dirent) + U16 (dirent.imp_use_length);
if (dirent.characteristics & GRUB_UDF_FID_CHAR_PARENT)
if (!(dirent.characteristics & GRUB_UDF_FID_CHAR_DELETED))
{
/* This is the parent directory. */
if (hook ("..", GRUB_FSHELP_DIR, child))
return 1;
}
else
{
enum grub_fshelp_filetype type;
grub_uint8_t raw[dirent.file_ident_length];
grub_uint16_t utf16[dirent.file_ident_length - 1];
grub_uint8_t filename[dirent.file_ident_length * 2];
grub_size_t utf16len = 0;
type = ((dirent.characteristics & GRUB_UDF_FID_CHAR_DIRECTORY) ?
(GRUB_FSHELP_DIR) : (GRUB_FSHELP_REG));
if ((grub_udf_read_file (dir, 0, offset,
dirent.file_ident_length,
(char *) raw))
!= dirent.file_ident_length)
child = grub_malloc (sizeof (struct grub_fshelp_node));
if (!child)
return 0;
if (raw[0] == 8)
if (grub_udf_read_icb (dir->data, &dirent.icb, child))
return 0;
if (dirent.characteristics & GRUB_UDF_FID_CHAR_PARENT)
{
unsigned i;
utf16len = dirent.file_ident_length - 1;
for (i = 0; i < utf16len; i++)
utf16[i] = raw[i + 1];
/* This is the parent directory. */
if (hook ("..", GRUB_FSHELP_DIR, child))
return 1;
}
if (raw[0] == 16)
else
{
unsigned i;
utf16len = (dirent.file_ident_length - 1) / 2;
for (i = 0; i < utf16len; i++)
utf16[i] = (raw[2 * i + 1] << 8) | raw[2*i + 2];
}
if (raw[0] == 8 || raw[0] == 16)
{
*grub_utf16_to_utf8 (filename, utf16, utf16len) = '\0';
if (hook ((char *) filename, type, child))
return 1;
enum grub_fshelp_filetype type;
char *filename;
grub_uint8_t raw[dirent.file_ident_length];
type = ((dirent.characteristics & GRUB_UDF_FID_CHAR_DIRECTORY) ?
(GRUB_FSHELP_DIR) : (GRUB_FSHELP_REG));
if ((grub_udf_read_file (dir, 0, offset,
dirent.file_ident_length,
(char *) raw))
!= dirent.file_ident_length)
return 0;
filename = read_string (raw, dirent.file_ident_length);
if (!filename)
grub_print_error ();
if (filename && hook (filename, type, child))
{
grub_free (filename);
return 1;
}
grub_free (filename);
}
}
@ -908,7 +1028,7 @@ grub_udf_label (grub_device_t device, char **label)
if (data)
{
*label = grub_strdup ((char *) &data->lvd.ident[1]);
*label = read_string (data->lvd.ident, sizeof (data->lvd.ident));
grub_free (data);
}
else

View file

@ -451,18 +451,27 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
for (i = 0; i < diro->inode.data.dir.dirhead.count; i++)
{
grub_uint64_t ino;
void *inopos = (((char *) de)
grub_uint8_t *inopos = (((grub_uint8_t *) de)
+ sizeof (struct grub_xfs_dir_entry)
+ de->len - 1);
char name[de->len + 1];
/* inopos might be unaligned. */
if (smallino)
{
ino = grub_be_to_cpu32 (*(grub_uint32_t *) inopos);
ino = grub_cpu_to_be64 (ino);
}
ino = (((grub_uint32_t) inopos[0]) << 24)
| (((grub_uint32_t) inopos[1]) << 16)
| (((grub_uint32_t) inopos[2]) << 8)
| (((grub_uint32_t) inopos[3]) << 0);
else
ino = *(grub_uint64_t *) inopos;
ino = (((grub_uint64_t) inopos[0]) << 56)
| (((grub_uint64_t) inopos[1]) << 48)
| (((grub_uint64_t) inopos[2]) << 40)
| (((grub_uint64_t) inopos[3]) << 32)
| (((grub_uint64_t) inopos[4]) << 24)
| (((grub_uint64_t) inopos[5]) << 16)
| (((grub_uint64_t) inopos[6]) << 8)
| (((grub_uint64_t) inopos[7]) << 0);
ino = grub_cpu_to_be64 (ino);
grub_memcpy (name, de->name, de->len);
name[de->len] = '\0';
@ -808,6 +817,9 @@ static struct grub_fs grub_xfs_fs =
.close = grub_xfs_close,
.label = grub_xfs_label,
.uuid = grub_xfs_uuid,
#ifdef GRUB_UTIL
.reserved_first_sector = 0,
#endif
.next = 0
};

2548
grub-core/fs/zfs/zfs.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,84 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2004,2009 Free Software Foundation, Inc.
* Copyright 2007 Sun Microsystems, 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/err.h>
#include <grub/file.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/disk.h>
#include <grub/dl.h>
#include <grub/types.h>
#include <grub/zfs/zfs.h>
#include <grub/zfs/zio.h>
#include <grub/zfs/dnode.h>
#include <grub/zfs/uberblock_impl.h>
#include <grub/zfs/vdev_impl.h>
#include <grub/zfs/zio_checksum.h>
#include <grub/zfs/zap_impl.h>
#include <grub/zfs/zap_leaf.h>
#include <grub/zfs/zfs_znode.h>
#include <grub/zfs/dmu.h>
#include <grub/zfs/dmu_objset.h>
#include <grub/zfs/dsl_dir.h>
#include <grub/zfs/dsl_dataset.h>
void
fletcher_2(const void *buf, grub_uint64_t size, grub_zfs_endian_t endian,
zio_cksum_t *zcp)
{
const grub_uint64_t *ip = buf;
const grub_uint64_t *ipend = ip + (size / sizeof (grub_uint64_t));
grub_uint64_t a0, b0, a1, b1;
for (a0 = b0 = a1 = b1 = 0; ip < ipend; ip += 2)
{
a0 += grub_zfs_to_cpu64 (ip[0], endian);
a1 += grub_zfs_to_cpu64 (ip[1], endian);
b0 += a0;
b1 += a1;
}
zcp->zc_word[0] = grub_cpu_to_zfs64 (a0, endian);
zcp->zc_word[1] = grub_cpu_to_zfs64 (a1, endian);
zcp->zc_word[2] = grub_cpu_to_zfs64 (b0, endian);
zcp->zc_word[3] = grub_cpu_to_zfs64 (b1, endian);
}
void
fletcher_4 (const void *buf, grub_uint64_t size, grub_zfs_endian_t endian,
zio_cksum_t *zcp)
{
const grub_uint32_t *ip = buf;
const grub_uint32_t *ipend = ip + (size / sizeof (grub_uint32_t));
grub_uint64_t a, b, c, d;
for (a = b = c = d = 0; ip < ipend; ip++)
{
a += grub_zfs_to_cpu32 (ip[0], endian);;
b += a;
c += b;
d += c;
}
zcp->zc_word[0] = grub_cpu_to_zfs64 (a, endian);
zcp->zc_word[1] = grub_cpu_to_zfs64 (b, endian);
zcp->zc_word[2] = grub_cpu_to_zfs64 (c, endian);
zcp->zc_word[3] = grub_cpu_to_zfs64 (d, endian);
}

View file

@ -0,0 +1,93 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2004,2009 Free Software Foundation, Inc.
* Copyright 2007 Sun Microsystems, 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/err.h>
#include <grub/file.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/disk.h>
#include <grub/dl.h>
#include <grub/types.h>
#include <grub/zfs/zfs.h>
#include <grub/zfs/zio.h>
#include <grub/zfs/dnode.h>
#include <grub/zfs/uberblock_impl.h>
#include <grub/zfs/vdev_impl.h>
#include <grub/zfs/zio_checksum.h>
#include <grub/zfs/zap_impl.h>
#include <grub/zfs/zap_leaf.h>
#include <grub/zfs/zfs_znode.h>
#include <grub/zfs/dmu.h>
#include <grub/zfs/dmu_objset.h>
#include <grub/zfs/dsl_dir.h>
#include <grub/zfs/dsl_dataset.h>
#define MATCH_BITS 6
#define MATCH_MIN 3
#define OFFSET_MASK ((1 << (16 - MATCH_BITS)) - 1)
/*
* Decompression Entry - lzjb
*/
#ifndef NBBY
#define NBBY 8
#endif
grub_err_t
lzjb_decompress (void *s_start, void *d_start, grub_size_t s_len,
grub_size_t d_len);
grub_err_t
lzjb_decompress (void *s_start, void *d_start, grub_size_t s_len,
grub_size_t d_len)
{
grub_uint8_t *src = s_start;
grub_uint8_t *dst = d_start;
grub_uint8_t *d_end = (grub_uint8_t *) d_start + d_len;
grub_uint8_t *s_end = (grub_uint8_t *) s_start + s_len;
grub_uint8_t *cpy, copymap = 0;
int copymask = 1 << (NBBY - 1);
while (dst < d_end && src < s_end)
{
if ((copymask <<= 1) == (1 << NBBY))
{
copymask = 1;
copymap = *src++;
}
if (src >= s_end)
return grub_error (GRUB_ERR_BAD_FS, "lzjb decompression failed");
if (copymap & copymask)
{
int mlen = (src[0] >> (NBBY - MATCH_BITS)) + MATCH_MIN;
int offset = ((src[0] << NBBY) | src[1]) & OFFSET_MASK;
src += 2;
cpy = dst - offset;
if (src > s_end || cpy < (grub_uint8_t *) d_start)
return grub_error (GRUB_ERR_BAD_FS, "lzjb decompression failed");
while (--mlen >= 0 && dst < d_end)
*dst++ = *cpy++;
}
else
*dst++ = *src++;
}
if (dst < d_end)
return grub_error (GRUB_ERR_BAD_FS, "lzjb decompression failed");
return GRUB_ERR_NONE;
}

View file

@ -0,0 +1,143 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2004,2009 Free Software Foundation, Inc.
* Copyright 2007 Sun Microsystems, 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/err.h>
#include <grub/file.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/disk.h>
#include <grub/dl.h>
#include <grub/types.h>
#include <grub/zfs/zfs.h>
#include <grub/zfs/zio.h>
#include <grub/zfs/dnode.h>
#include <grub/zfs/uberblock_impl.h>
#include <grub/zfs/vdev_impl.h>
#include <grub/zfs/zio_checksum.h>
#include <grub/zfs/zap_impl.h>
#include <grub/zfs/zap_leaf.h>
#include <grub/zfs/zfs_znode.h>
#include <grub/zfs/dmu.h>
#include <grub/zfs/dmu_objset.h>
#include <grub/zfs/dsl_dir.h>
#include <grub/zfs/dsl_dataset.h>
/*
* SHA-256 checksum, as specified in FIPS 180-2, available at:
* http://csrc.nist.gov/cryptval
*
* This is a very compact implementation of SHA-256.
* It is designed to be simple and portable, not to be fast.
*/
/*
* The literal definitions according to FIPS180-2 would be:
*
* Ch(x, y, z) (((x) & (y)) ^ ((~(x)) & (z)))
* Maj(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
*
* We use logical equivalents which require one less op.
*/
#define Ch(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
#define Maj(x, y, z) (((x) & (y)) ^ ((z) & ((x) ^ (y))))
#define Rot32(x, s) (((x) >> s) | ((x) << (32 - s)))
#define SIGMA0(x) (Rot32(x, 2) ^ Rot32(x, 13) ^ Rot32(x, 22))
#define SIGMA1(x) (Rot32(x, 6) ^ Rot32(x, 11) ^ Rot32(x, 25))
#define sigma0(x) (Rot32(x, 7) ^ Rot32(x, 18) ^ ((x) >> 3))
#define sigma1(x) (Rot32(x, 17) ^ Rot32(x, 19) ^ ((x) >> 10))
static const grub_uint32_t SHA256_K[64] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};
static void
SHA256Transform(grub_uint32_t *H, const grub_uint8_t *cp)
{
grub_uint32_t a, b, c, d, e, f, g, h, t, T1, T2, W[64];
for (t = 0; t < 16; t++, cp += 4)
W[t] = (cp[0] << 24) | (cp[1] << 16) | (cp[2] << 8) | cp[3];
for (t = 16; t < 64; t++)
W[t] = sigma1(W[t - 2]) + W[t - 7] +
sigma0(W[t - 15]) + W[t - 16];
a = H[0]; b = H[1]; c = H[2]; d = H[3];
e = H[4]; f = H[5]; g = H[6]; h = H[7];
for (t = 0; t < 64; t++) {
T1 = h + SIGMA1(e) + Ch(e, f, g) + SHA256_K[t] + W[t];
T2 = SIGMA0(a) + Maj(a, b, c);
h = g; g = f; f = e; e = d + T1;
d = c; c = b; b = a; a = T1 + T2;
}
H[0] += a; H[1] += b; H[2] += c; H[3] += d;
H[4] += e; H[5] += f; H[6] += g; H[7] += h;
}
void
zio_checksum_SHA256(const void *buf, grub_uint64_t size,
grub_zfs_endian_t endian, zio_cksum_t *zcp)
{
grub_uint32_t H[8] = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 };
grub_uint8_t pad[128];
unsigned padsize = size & 63;
unsigned i;
for (i = 0; i < size - padsize; i += 64)
SHA256Transform(H, (grub_uint8_t *)buf + i);
for (i = 0; i < padsize; i++)
pad[i] = ((grub_uint8_t *)buf)[i];
for (pad[padsize++] = 0x80; (padsize & 63) != 56; padsize++)
pad[padsize] = 0;
for (i = 0; i < 8; i++)
pad[padsize++] = (size << 3) >> (56 - 8 * i);
for (i = 0; i < padsize; i += 64)
SHA256Transform(H, pad + i);
zcp->zc_word[0] = grub_cpu_to_zfs64 ((grub_uint64_t)H[0] << 32 | H[1],
endian);
zcp->zc_word[1] = grub_cpu_to_zfs64 ((grub_uint64_t)H[2] << 32 | H[3],
endian);
zcp->zc_word[2] = grub_cpu_to_zfs64 ((grub_uint64_t)H[4] << 32 | H[5],
endian);
zcp->zc_word[3] = grub_cpu_to_zfs64 ((grub_uint64_t)H[6] << 32 | H[7],
endian);
}

407
grub-core/fs/zfs/zfsinfo.c Normal file
View file

@ -0,0 +1,407 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2004,2009 Free Software Foundation, Inc.
* Copyright 2008 Sun Microsystems, 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/zfs/zfs.h>
#include <grub/device.h>
#include <grub/file.h>
#include <grub/command.h>
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/dl.h>
#include <grub/env.h>
static inline void
print_tabs (int n)
{
int i;
for (i = 0; i < n; i++)
grub_printf (" ");
}
static grub_err_t
print_state (char *nvlist, int tab)
{
grub_uint64_t ival;
int isok = 1;
print_tabs (tab);
grub_printf ("State: ");
if (grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_REMOVED, &ival))
{
grub_printf ("removed ");
isok = 0;
}
if (grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_FAULTED, &ival))
{
grub_printf ("faulted ");
isok = 0;
}
if (grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_OFFLINE, &ival))
{
grub_printf ("offline ");
isok = 0;
}
if (grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_FAULTED, &ival))
grub_printf ("degraded ");
if (isok)
grub_printf ("online");
grub_printf ("\n");
return GRUB_ERR_NONE;
}
static grub_err_t
print_vdev_info (char *nvlist, int tab)
{
char *type = 0;
type = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_TYPE);
if (!type)
{
print_tabs (tab);
grub_printf ("Incorrect VDEV: no type available\n");
return grub_errno;
}
if (grub_strcmp (type, VDEV_TYPE_DISK) == 0)
{
char *bootpath = 0;
char *path = 0;
char *devid = 0;
print_tabs (tab);
grub_printf ("Leaf VDEV\n");
print_state (nvlist, tab);
bootpath =
grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_PHYS_PATH);
print_tabs (tab);
if (!bootpath)
grub_printf ("Bootpath: unavailable\n");
else
grub_printf ("Bootpath: %s\n", bootpath);
path = grub_zfs_nvlist_lookup_string (nvlist, "path");
print_tabs (tab);
if (!path)
grub_printf ("Path: unavailable\n");
else
grub_printf ("Path: %s\n", path);
devid = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_DEVID);
print_tabs (tab);
if (!devid)
grub_printf ("Devid: unavailable\n");
else
grub_printf ("Devid: %s\n", devid);
grub_free (bootpath);
grub_free (devid);
grub_free (path);
return GRUB_ERR_NONE;
}
if (grub_strcmp (type, VDEV_TYPE_MIRROR) == 0)
{
int nelm, i;
nelm = grub_zfs_nvlist_lookup_nvlist_array_get_nelm
(nvlist, ZPOOL_CONFIG_CHILDREN);
print_tabs (tab);
if (nelm <= 0)
{
grub_printf ("Incorrect mirror VDEV\n");
return GRUB_ERR_NONE;
}
grub_printf ("Mirror VDEV with %d children\n", nelm);
print_state (nvlist, tab);
for (i = 0; i < nelm; i++)
{
char *child;
child = grub_zfs_nvlist_lookup_nvlist_array
(nvlist, ZPOOL_CONFIG_CHILDREN, i);
print_tabs (tab);
if (!child)
{
grub_printf ("Mirror VDEV element %d isn't correct\n", i);
continue;
}
grub_printf ("Mirror VDEV element %d:\n", i);
print_vdev_info (child, tab + 1);
grub_free (child);
}
}
print_tabs (tab);
grub_printf ("Unknown VDEV type: %s\n", type);
return GRUB_ERR_NONE;
}
static grub_err_t
get_bootpath (char *nvlist, char **bootpath, char **devid)
{
char *type = 0;
type = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_TYPE);
if (!type)
return grub_errno;
if (grub_strcmp (type, VDEV_TYPE_DISK) == 0)
{
*bootpath = grub_zfs_nvlist_lookup_string (nvlist,
ZPOOL_CONFIG_PHYS_PATH);
*devid = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_DEVID);
if (!*bootpath || !*devid)
{
grub_free (*bootpath);
grub_free (*devid);
*bootpath = 0;
*devid = 0;
}
return GRUB_ERR_NONE;
}
if (grub_strcmp (type, VDEV_TYPE_MIRROR) == 0)
{
int nelm, i;
nelm = grub_zfs_nvlist_lookup_nvlist_array_get_nelm
(nvlist, ZPOOL_CONFIG_CHILDREN);
for (i = 0; i < nelm; i++)
{
char *child;
child = grub_zfs_nvlist_lookup_nvlist_array (nvlist,
ZPOOL_CONFIG_CHILDREN,
i);
get_bootpath (child, bootpath, devid);
grub_free (child);
if (*bootpath && *devid)
return GRUB_ERR_NONE;
}
}
return GRUB_ERR_NONE;
}
static char *poolstates[] = {
[POOL_STATE_ACTIVE] = "active",
[POOL_STATE_EXPORTED] = "exported",
[POOL_STATE_DESTROYED] = "destroyed",
[POOL_STATE_SPARE] = "reserved for hot spare",
[POOL_STATE_L2CACHE] = "level 2 ARC device",
[POOL_STATE_UNINITIALIZED] = "uninitialized",
[POOL_STATE_UNAVAIL] = "unavailable",
[POOL_STATE_POTENTIALLY_ACTIVE] = "potentially active"
};
static grub_err_t
grub_cmd_zfsinfo (grub_command_t cmd __attribute__ ((unused)), int argc,
char **args)
{
grub_device_t dev;
char *devname;
grub_err_t err;
char *nvlist = 0;
char *nv = 0;
char *poolname;
grub_uint64_t guid;
grub_uint64_t pool_state;
int found;
if (argc < 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required");
if (args[0][0] == '(' && args[0][grub_strlen (args[0]) - 1] == ')')
{
devname = grub_strdup (args[0] + 1);
if (devname)
devname[grub_strlen (devname) - 1] = 0;
}
else
devname = grub_strdup (args[0]);
if (!devname)
return grub_errno;
dev = grub_device_open (devname);
grub_free (devname);
if (!dev)
return grub_errno;
err = grub_zfs_fetch_nvlist (dev, &nvlist);
grub_device_close (dev);
if (err)
return err;
poolname = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_POOL_NAME);
if (!poolname)
grub_printf ("Pool name: unavailable\n");
else
grub_printf ("Pool name: %s\n", poolname);
found =
grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_POOL_GUID, &guid);
if (!found)
grub_printf ("Pool GUID: unavailable\n");
else
grub_printf ("Pool GUID: %016llx\n", (long long unsigned) guid);
found = grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_POOL_STATE,
&pool_state);
if (!found)
grub_printf ("Unable to retrieve pool state\n");
else if (pool_state >= ARRAY_SIZE (poolstates))
grub_printf ("Unrecognized pool state\n");
else
grub_printf ("Pool state: %s\n", poolstates[pool_state]);
nv = grub_zfs_nvlist_lookup_nvlist (nvlist, ZPOOL_CONFIG_VDEV_TREE);
if (!nv)
grub_printf ("No vdev tree available\n");
else
print_vdev_info (nv, 1);
grub_free (nv);
grub_free (nvlist);
return GRUB_ERR_NONE;
}
static grub_err_t
grub_cmd_zfs_bootfs (grub_command_t cmd __attribute__ ((unused)), int argc,
char **args)
{
grub_device_t dev;
char *devname;
grub_err_t err;
char *nvlist = 0;
char *nv = 0;
char *bootpath = 0, *devid = 0;
char *fsname;
char *bootfs;
char *poolname;
grub_uint64_t mdnobj;
if (argc < 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "filesystem name required");
devname = grub_file_get_device_name (args[0]);
if (grub_errno)
return grub_errno;
dev = grub_device_open (devname);
grub_free (devname);
if (!dev)
return grub_errno;
err = grub_zfs_fetch_nvlist (dev, &nvlist);
fsname = grub_strchr (args[0], ')');
if (fsname)
fsname++;
else
fsname = args[0];
if (!err)
err = grub_zfs_getmdnobj (dev, fsname, &mdnobj);
grub_device_close (dev);
if (err)
return err;
poolname = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_POOL_NAME);
if (!poolname)
{
if (!grub_errno)
grub_error (GRUB_ERR_BAD_FS, "No poolname found");
return grub_errno;
}
nv = grub_zfs_nvlist_lookup_nvlist (nvlist, ZPOOL_CONFIG_VDEV_TREE);
if (nv)
get_bootpath (nv, &bootpath, &devid);
grub_free (nv);
grub_free (nvlist);
bootfs = grub_xasprintf ("zfs-bootfs=%s/%llu%s%s%s%s%s%s",
poolname, (unsigned long long) mdnobj,
bootpath ? ",bootpath=\"" : "",
bootpath ? : "",
bootpath ? "\"" : "",
devid ? ",diskdevid=\"" : "",
devid ? : "",
devid ? "\"" : "");
if (!bootfs)
return grub_errno;
if (argc >= 2)
grub_env_set (args[1], bootfs);
else
grub_printf ("%s\n", bootfs);
grub_free (bootfs);
grub_free (poolname);
grub_free (bootpath);
grub_free (devid);
return GRUB_ERR_NONE;
}
static grub_command_t cmd_info, cmd_bootfs;
GRUB_MOD_INIT (zfsinfo)
{
cmd_info = grub_register_command ("zfsinfo", grub_cmd_zfsinfo,
"zfsinfo DEVICE",
"Print ZFS info about DEVICE.");
cmd_bootfs = grub_register_command ("zfs-bootfs", grub_cmd_zfs_bootfs,
"zfs-bootfs FILESYSTEM [VARIABLE]",
"Print ZFS-BOOTFSOBJ or set it to VARIABLE");
}
GRUB_MOD_FINI (zfsinfo)
{
grub_unregister_command (cmd_info);
grub_unregister_command (cmd_bootfs);
}

View file

@ -35,7 +35,7 @@ deps=`grep ^$modname: $moddep | sed s@^.*:@@`
rm -f $tmpfile $outfile
# stripout .modname and .moddeps sections from input module
objcopy -R .modname -R .moddeps $infile $tmpfile
@OBJCOPY@ -R .modname -R .moddeps $infile $tmpfile
# Attach .modname and .moddeps sections
t1=`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1
@ -45,15 +45,15 @@ t2=`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1
for dep in $deps; do printf "$dep\0" >> $t2; done
if test -n "$deps"; then
objcopy --add-section .modname=$t1 --add-section .moddeps=$t2 $tmpfile
@OBJCOPY@ --add-section .modname=$t1 --add-section .moddeps=$t2 $tmpfile
else
objcopy --add-section .modname=$t1 $tmpfile
@OBJCOPY@ --add-section .modname=$t1 $tmpfile
fi
rm -f $t1 $t2
if test x@TARGET_APPLE_CC@ != x1; then
if ! test -z "@TARGET_OBJ2ELF@"; then
./@TARGET_OBJ2ELF@ $tmpfile || exit 1
if ! test -z "${TARGET_OBJ2ELF}"; then
./${TARGET_OBJ2ELF} $tmpfile || exit 1
fi
if test x@platform@ != xemu; then
@STRIP@ --strip-unneeded \

View file

@ -49,7 +49,7 @@ struct grub_gettext_msg
const char *translated;
};
struct grub_gettext_msg *grub_gettext_msg_list = NULL;
static struct grub_gettext_msg *grub_gettext_msg_list = NULL;
#define GETTEXT_MAGIC_NUMBER 0
#define GETTEXT_FILE_FORMAT 4
@ -261,24 +261,16 @@ grub_mofile_open (const char *filename)
return fd_mo;
}
/* Returning grub_file_t would be more natural, but grub_mofile_open assigns
to fd_mo anyway ... */
static void
grub_gettext_init_ext (const char *lang)
grub_mofile_open_lang (const char *locale_dir, const char *locale)
{
char *mo_file;
char *locale_dir;
locale_dir = grub_env_get ("locale_dir");
if (locale_dir == NULL)
{
grub_dprintf ("gettext", "locale_dir variable is not set up.\n");
return;
}
fd_mo = NULL;
/* mo_file e.g.: /boot/grub/locale/ca.mo */
mo_file = grub_xasprintf ("%s/%s.mo", locale_dir, lang);
mo_file = grub_xasprintf ("%s/%s.mo", locale_dir, locale);
if (!mo_file)
return;
@ -295,6 +287,38 @@ grub_gettext_init_ext (const char *lang)
return;
fd_mo = grub_mofile_open (mo_file);
}
}
static void
grub_gettext_init_ext (const char *locale)
{
char *locale_dir;
locale_dir = grub_env_get ("locale_dir");
if (locale_dir == NULL)
{
grub_dprintf ("gettext", "locale_dir variable is not set up.\n");
return;
}
fd_mo = NULL;
grub_mofile_open_lang (locale_dir, locale);
/* ll_CC didn't work, so try ll. */
if (fd_mo == NULL)
{
char *lang = grub_strdup (locale);
char *underscore = grub_strchr (lang, '_');
if (underscore)
{
*underscore = '\0';
grub_mofile_open_lang (locale_dir, lang);
}
grub_free (lang);
}
if (fd_mo)
{

View file

@ -37,7 +37,7 @@
#include <grub/gfxmenu_view.h>
#include <grub/time.h>
grub_gfxmenu_view_t cached_view;
static grub_gfxmenu_view_t cached_view;
static void
grub_gfxmenu_viewer_fini (void *data __attribute__ ((unused)))

View file

@ -86,18 +86,21 @@ grub_read_hook_datetime (struct grub_env_var *var,
GRUB_MOD_INIT(datehook)
{
int i;
unsigned i;
for (i = 0; i < 7; i++)
grub_register_variable_hook (grub_datetime_names[i],
grub_read_hook_datetime, 0);
for (i = 0; i < ARRAY_SIZE (grub_datetime_names); i++)
{
grub_register_variable_hook (grub_datetime_names[i],
grub_read_hook_datetime, 0);
grub_env_export (grub_datetime_names[i]);
}
}
GRUB_MOD_FINI(datehook)
{
int i;
unsigned i;
for (i = 0; i < 7; i++)
for (i = 0; i < ARRAY_SIZE (grub_datetime_names); i++)
{
grub_register_variable_hook (grub_datetime_names[i], 0, 0);
grub_env_unset (grub_datetime_names[i]);

View file

@ -74,7 +74,7 @@ grub_bufio_open (grub_file_t io, int size)
file->data = bufio;
file->read_hook = 0;
file->fs = &grub_bufio_fs;
file->not_easly_seekable = io->not_easly_seekable;
file->not_easily_seekable = io->not_easily_seekable;
return file;
}

View file

@ -212,19 +212,18 @@ test_header (grub_file_t file)
gzio->data_offset = grub_file_tell (gzio->file);
grub_file_seek (gzio->file, grub_file_size (gzio->file) - 4);
if (grub_file_seekable (gzio->file))
{
if (grub_file_read (gzio->file, &orig_len, 4) != 4)
{
grub_error (GRUB_ERR_BAD_FILE_TYPE, "unsupported gzip format");
return 0;
}
}
/* FIXME: this does not handle files whose original size is over 4GB.
But how can we know the real original size? */
file->size = grub_le_to_cpu32 (orig_len);
/* FIXME: don't do this on not easily seekable files. */
{
grub_file_seek (gzio->file, grub_file_size (gzio->file) - 4);
if (grub_file_read (gzio->file, &orig_len, 4) != 4)
{
grub_error (GRUB_ERR_BAD_FILE_TYPE, "unsupported gzip format");
return 0;
}
/* FIXME: this does not handle files whose original size is over 4GB.
But how can we know the real original size? */
file->size = grub_le_to_cpu32 (orig_len);
}
initialize_tables (file);
@ -1137,7 +1136,7 @@ grub_gzio_open (grub_file_t io)
file->data = gzio;
file->read_hook = 0;
file->fs = &grub_gzio_fs;
file->not_easly_seekable = 1;
file->not_easily_seekable = 1;
if (! test_header (file))
{

View file

@ -200,7 +200,7 @@ grub_xzio_open (grub_file_t io)
file->read_hook = 0;
file->fs = &grub_xzio_fs;
file->size = GRUB_FILE_SIZE_UNKNOWN;
file->not_easly_seekable = 1;
file->not_easily_seekable = 1;
if (grub_file_tell (xzio->file) != 0)
grub_file_seek (xzio->file, 0);
@ -222,7 +222,8 @@ grub_xzio_open (grub_file_t io)
xzio->buf.out_pos = 0;
xzio->buf.out_size = XZBUFSIZ;
if (!test_header (file) || !(grub_file_seekable (io) && test_footer (file)))
/* FIXME: don't test footer on not easily seekable files. */
if (!test_header (file) || !test_footer (file))
{
grub_errno = GRUB_ERR_NONE;
grub_file_seek (io, 0);

View file

@ -52,13 +52,13 @@ grub_efi_allocate_pages (grub_efi_physical_address_t address,
grub_efi_status_t status;
grub_efi_boot_services_t *b;
#if GRUB_TARGET_SIZEOF_VOID_P < 8
#if 1
/* Limit the memory access to less than 4GB for 32-bit platforms. */
if (address > 0xffffffff)
return 0;
#endif
#if GRUB_TARGET_SIZEOF_VOID_P < 8 || defined (MCMODEL_SMALL)
#if 1
if (address == 0)
{
type = GRUB_EFI_ALLOCATE_MAX_ADDRESS;
@ -251,7 +251,7 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map,
desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
{
if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY
#if GRUB_TARGET_SIZEOF_VOID_P < 8 || defined (MCMODEL_SMALL)
#if 1
&& desc->physical_start <= 0xffffffff
#endif
&& desc->physical_start + PAGES_TO_BYTES (desc->num_pages) > 0x100000
@ -267,7 +267,7 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map,
desc->physical_start = 0x100000;
}
#if GRUB_TARGET_SIZEOF_VOID_P < 8 || defined (MCMODEL_SMALL)
#if 1
if (BYTES_TO_PAGES (filtered_desc->physical_start)
+ filtered_desc->num_pages
> BYTES_TO_PAGES (0x100000000LL))

View file

@ -171,11 +171,12 @@ grub_elf32_phdr_iterate (grub_elf_t elf,
/* Calculate the amount of memory spanned by the segments. */
grub_size_t
grub_elf32_size (grub_elf_t elf, Elf32_Addr *base)
grub_elf32_size (grub_elf_t elf, Elf32_Addr *base, grub_uint32_t *max_align)
{
Elf32_Addr segments_start = (Elf32_Addr) -1;
Elf32_Addr segments_end = 0;
int nr_phdrs = 0;
grub_uint32_t curr_align = 1;
/* Run through the program headers to calculate the total memory size we
* should claim. */
@ -192,6 +193,8 @@ grub_elf32_size (grub_elf_t elf, Elf32_Addr *base)
segments_start = phdr->p_paddr;
if (phdr->p_paddr + phdr->p_memsz > segments_end)
segments_end = phdr->p_paddr + phdr->p_memsz;
if (curr_align < phdr->p_align)
curr_align = phdr->p_align;
return 0;
}
@ -215,7 +218,8 @@ grub_elf32_size (grub_elf_t elf, Elf32_Addr *base)
if (base)
*base = segments_start;
if (max_align)
*max_align = curr_align;
return segments_end - segments_start;
}
@ -290,7 +294,6 @@ grub_elf32_load (grub_elf_t _elf, grub_elf32_load_hook_t _load_hook,
return err;
}
/* 64-bit */
@ -357,16 +360,17 @@ grub_elf64_phdr_iterate (grub_elf_t elf,
/* Calculate the amount of memory spanned by the segments. */
grub_size_t
grub_elf64_size (grub_elf_t elf, Elf64_Addr *base)
grub_elf64_size (grub_elf_t elf, Elf64_Addr *base, grub_uint64_t *max_align)
{
Elf64_Addr segments_start = (Elf64_Addr) -1;
Elf64_Addr segments_end = 0;
int nr_phdrs = 0;
grub_uint64_t curr_align = 1;
/* Run through the program headers to calculate the total memory size we
* should claim. */
auto int NESTED_FUNC_ATTR calcsize (grub_elf_t _elf, Elf64_Phdr *phdr, void *_arg);
int NESTED_FUNC_ATTR calcsize (grub_elf_t _elf __attribute__ ((unused)),
int NESTED_FUNC_ATTR calcsize (grub_elf_t _elf __attribute__ ((unused)),
Elf64_Phdr *phdr,
void *_arg __attribute__ ((unused)))
{
@ -378,6 +382,8 @@ grub_elf64_size (grub_elf_t elf, Elf64_Addr *base)
segments_start = phdr->p_paddr;
if (phdr->p_paddr + phdr->p_memsz > segments_end)
segments_end = phdr->p_paddr + phdr->p_memsz;
if (curr_align < phdr->p_align)
curr_align = phdr->p_align;
return 0;
}
@ -401,11 +407,11 @@ grub_elf64_size (grub_elf_t elf, Elf64_Addr *base)
if (base)
*base = segments_start;
if (max_align)
*max_align = curr_align;
return segments_end - segments_start;
}
/* Load every loadable segment into memory specified by `_load_hook'. */
grub_err_t
grub_elf64_load (grub_elf_t _elf, grub_elf64_load_hook_t _load_hook,

View file

@ -17,7 +17,9 @@
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config-util.h>
#include <config.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <assert.h>
@ -135,8 +137,12 @@ find_root_device_from_mountinfo (const char *dir)
continue; /* only a subtree is mounted */
enc_path_len = strlen (enc_path);
/* Check that enc_path is a prefix of dir. The prefix must either be
the entire string, or end with a slash, or be immediately followed
by a slash. */
if (strncmp (dir, enc_path, enc_path_len) != 0 ||
(dir[enc_path_len] && dir[enc_path_len] != '/'))
(enc_path_len && dir[enc_path_len - 1] != '/' &&
dir[enc_path_len] && dir[enc_path_len] != '/'))
continue;
/* This is a parent of the requested directory. /proc/self/mountinfo
@ -178,7 +184,7 @@ find_root_device_from_mountinfo (const char *dir)
static char *
find_root_device_from_libzfs (const char *dir)
{
char *device;
char *device = NULL;
char *poolname;
char *poolfs;
@ -219,7 +225,10 @@ find_root_device_from_libzfs (const char *dir)
struct stat st;
if (stat (device, &st) == 0)
break;
{
device = xstrdup (device);
break;
}
device = NULL;
}
@ -582,6 +591,8 @@ grub_util_is_dmraid (const char *os_dev)
return 1;
else if (! strncmp (os_dev, "/dev/mapper/sil_", 16))
return 1;
else if (! strncmp (os_dev, "/dev/mapper/ddf1_", 17))
return 1;
return 0;
}
@ -792,11 +803,36 @@ grub_util_get_grub_dev (const char *os_dev)
#ifdef __linux__
{
char *mdadm_name = get_mdadm_name (os_dev);
struct stat st;
if (mdadm_name)
{
free (grub_dev);
grub_dev = xasprintf ("md/%s", mdadm_name);
char *newname;
char *q;
for (q = os_dev + strlen (os_dev) - 1; q >= os_dev && isdigit (*q);
q--);
if (q >= os_dev && *q == 'p')
{
newname = xasprintf ("/dev/md/%sp%s", mdadm_name, q + 1);
if (stat (newname, &st) == 0)
{
free (grub_dev);
grub_dev = xasprintf ("md/%s,%s", mdadm_name, q + 1);
goto done;
}
free (newname);
}
newname = xasprintf ("/dev/md/%s", mdadm_name);
if (stat (newname, &st) == 0)
{
free (grub_dev);
grub_dev = xasprintf ("md/%s", mdadm_name);
}
done:
free (newname);
free (mdadm_name);
}
}

View file

@ -92,6 +92,8 @@ struct hd_geometry
# include <sys/disk.h> /* DIOCGMEDIASIZE */
# include <sys/param.h>
# include <sys/sysctl.h>
# define MAJOR(dev) major(dev)
# define FLOPPY_MAJOR 2
#endif
#if defined(__APPLE__)
@ -102,7 +104,9 @@ struct hd_geometry
# include <libdevmapper.h>
#endif
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
#include <libgeom.h>
#elif defined(__NetBSD__)
# define HAVE_DIOCGDINFO
# include <sys/ioctl.h>
# include <sys/disklabel.h> /* struct disklabel */
@ -337,7 +341,68 @@ device_is_mapped (const char *dev)
}
#endif /* HAVE_DEVICE_MAPPER */
#if defined(__linux__) || defined(__CYGWIN__) || defined(HAVE_DIOCGDINFO)
#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
/* FIXME: geom actually gives us the whole container hierarchy.
It can be used more efficiently than this. */
static void
follow_geom_up (const char *name, grub_disk_addr_t *off_out, char **name_out)
{
struct gmesh mesh;
struct gclass *class;
int error;
struct ggeom *geom;
grub_util_info ("following geom '%s'", name);
error = geom_gettree (&mesh);
if (error != 0)
grub_util_error ("couldn't open geom");
LIST_FOREACH (class, &mesh.lg_class, lg_class)
if (strcasecmp (class->lg_name, "part") == 0)
break;
if (!class)
grub_util_error ("couldn't open geom part");
LIST_FOREACH (geom, &class->lg_geom, lg_geom)
{
struct gprovider *provider;
LIST_FOREACH (provider, &geom->lg_provider, lg_provider)
if (strcmp (provider->lg_name, name) == 0)
{
char *name_tmp = xstrdup (geom->lg_name);
grub_disk_addr_t off = 0;
struct gconfig *config;
grub_util_info ("geom '%s' has parent '%s'", name, geom->lg_name);
follow_geom_up (name_tmp, &off, name_out);
free (name_tmp);
LIST_FOREACH (config, &provider->lg_config, lg_config)
if (strcasecmp (config->lg_name, "start") == 0)
off += strtoull (config->lg_val, 0, 10);
if (off_out)
*off_out = off;
return;
}
}
grub_util_info ("geom '%s' has no parent", name);
if (name_out)
*name_out = xstrdup (name);
if (off_out)
*off_out = 0;
}
static grub_disk_addr_t
find_partition_start (const char *dev)
{
grub_disk_addr_t out;
if (strncmp (dev, "/dev/", sizeof ("/dev/") - 1) != 0)
return 0;
follow_geom_up (dev + sizeof ("/dev/") - 1, &out, NULL);
return out;
}
#elif defined(__linux__) || defined(__CYGWIN__) || defined(HAVE_DIOCGDINFO)
static grub_disk_addr_t
find_partition_start (const char *dev)
{
@ -453,9 +518,12 @@ devmapper_fail:
# if !defined(HAVE_DIOCGDINFO)
return hdg.start;
# else /* defined(HAVE_DIOCGDINFO) */
p_index = dev[strlen(dev) - 1] - 'a';
if (p_index >= label.d_npartitions)
if (dev[0])
p_index = dev[strlen(dev) - 1] - 'a';
else
p_index = -1;
if (p_index >= label.d_npartitions || p_index < 0)
{
grub_error (GRUB_ERR_BAD_DEVICE,
"no disk label entry for `%s'", dev);
@ -1152,16 +1220,22 @@ convert_system_partition_to_system_disk (const char *os_dev, struct stat *st)
|| strncmp ("sd", p, 2) == 0)
&& p[2] >= 'a' && p[2] <= 'z')
{
/* /dev/[hsv]d[a-z][0-9]* */
p[3] = '\0';
char *pp = p + 2;
while (*pp >= 'a' && *pp <= 'z')
pp++;
/* /dev/[hsv]d[a-z]+[0-9]* */
*pp = '\0';
return path;
}
/* If this is a Xen virtual block device. */
if ((strncmp ("xvd", p, 3) == 0) && p[3] >= 'a' && p[3] <= 'z')
{
/* /dev/xvd[a-z][0-9]* */
p[4] = '\0';
char *pp = p + 3;
while (*pp >= 'a' && *pp <= 'z')
pp++;
/* /dev/xvd[a-z]+[0-9]* */
*pp = '\0';
return path;
}
@ -1278,7 +1352,17 @@ devmapper_out:
path[8] = 0;
return path;
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__)
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
char *out, *out2;
if (strncmp (os_dev, "/dev/", sizeof ("/dev/") - 1) != 0)
return xstrdup (os_dev);
follow_geom_up (os_dev + sizeof ("/dev/") - 1, NULL, &out);
out2 = xasprintf ("/dev/%s", out);
free (out);
return out2;
#elif defined(__APPLE__)
char *path = xstrdup (os_dev);
if (strncmp ("/dev/", path, 5) == 0)
{
@ -1434,6 +1518,7 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev)
if (stat (os_dev, &st) < 0)
{
grub_error (GRUB_ERR_BAD_DEVICE, "cannot stat `%s'", os_dev);
grub_util_info ("cannot stat `%s'", os_dev);
return 0;
}
@ -1442,6 +1527,7 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev)
{
grub_error (GRUB_ERR_UNKNOWN_DEVICE,
"no mapping exists for `%s'", os_dev);
grub_util_info ("no mapping exists for `%s'", os_dev);
return 0;
}
@ -1456,7 +1542,8 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev)
#endif
return make_device_name (drive, -1, -1);
#if defined(__linux__) || defined(__CYGWIN__) || defined(HAVE_DIOCGDINFO)
#if defined(__linux__) || defined(__CYGWIN__) || defined(HAVE_DIOCGDINFO) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
/* Linux counts partitions uniformly, whether a BSD partition or a DOS
partition, so mapping them to GRUB devices is not trivial.
Here, get the start sector of a partition by HDIO_GETGEO, and

View file

@ -240,3 +240,23 @@ grub_register_variable_hook (const char *name,
return GRUB_ERR_NONE;
}
grub_err_t
grub_env_export (const char *name)
{
struct grub_env_var *var;
var = grub_env_find (name);
if (! var)
{
grub_err_t err;
err = grub_env_set (name, "");
if (err)
return err;
var = grub_env_find (name);
}
var->global = 1;
return GRUB_ERR_NONE;
}

View file

@ -20,10 +20,15 @@
#include <grub/misc.h>
#include <grub/err.h>
#include <grub/file.h>
#include <grub/net.h>
#include <grub/mm.h>
#include <grub/fs.h>
#include <grub/device.h>
grub_ssize_t (*grub_file_net_read) (grub_file_t file, void *buf, grub_size_t len) = NULL;
grub_err_t (*grub_file_net_open) (struct grub_file *file, const char *name) = NULL;
grub_err_t (*grub_file_net_seek) (struct grub_file *file, grub_off_t offset) = NULL;
grub_file_filter_t grub_file_filters_all[GRUB_FILE_FILTER_MAX];
grub_file_filter_t grub_file_filters_enabled[GRUB_FILE_FILTER_MAX];
@ -85,6 +90,13 @@ grub_file_open (const char *name)
file->device = device;
if (device->net && grub_file_net_open)
{
if (grub_file_net_open (file, file_name))
goto fail;
return file;
}
if (device->disk && file_name[0] != '/')
/* This is a block list. */
file->fs = &grub_fs_blocklist;
@ -130,7 +142,7 @@ grub_file_open (const char *name)
grub_ssize_t
grub_file_read (grub_file_t file, void *buf, grub_size_t len)
{
grub_ssize_t res;
grub_ssize_t res = 0;
if (file->offset > file->size)
{
@ -148,8 +160,12 @@ grub_file_read (grub_file_t file, void *buf, grub_size_t len)
if (len == 0)
return 0;
res = (file->fs->read) (file, buf, len);
if (file->device->disk)
res = (file->fs->read) (file, buf, len);
else
if (grub_file_net_read && file->device->net)
res = grub_file_net_read (file, buf, len);
if (res > 0)
file->offset += res;
@ -159,6 +175,9 @@ grub_file_read (grub_file_t file, void *buf, grub_size_t len)
grub_err_t
grub_file_close (grub_file_t file)
{
if (file->device->net)
return grub_errno;
if (file->fs->close)
(file->fs->close) (file);
@ -179,8 +198,12 @@ grub_file_seek (grub_file_t file, grub_off_t offset)
"attempt to seek outside of the file");
return -1;
}
if (file->device->net && grub_file_net_seek)
grub_file_net_seek (file, offset);
old = file->offset;
file->offset = offset;
return old;
}

View file

@ -95,7 +95,7 @@ grub_fs_probe (grub_device_t device)
}
}
else if (device->net)
return device->net->protocol;
return NULL;
grub_error (GRUB_ERR_UNKNOWN_FS, "unknown filesystem");
return 0;

View file

@ -140,36 +140,27 @@ compact_mem_regions (void)
}
}
/*
*
* grub_get_conv_memsize(i) : return the conventional memory size in KB.
* BIOS call "INT 12H" to get conventional memory size
* The return value in AX.
*/
static inline grub_uint16_t
grub_get_conv_memsize (void)
{
struct grub_bios_int_registers regs;
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
grub_bios_interrupt (0x12, &regs);
return regs.eax & 0xffff;
}
void
grub_machine_init (void)
{
int i;
#if 0
int grub_lower_mem;
#endif
/* Initialize the console as early as possible. */
grub_console_init ();
/* This sanity check is useless since top of GRUB_MEMORY_MACHINE_RESERVED_END
is used for stack and if it's unavailable we wouldn't have gotten so far.
*/
#if 0
grub_lower_mem = grub_get_conv_memsize () << 10;
/* Sanity check. */
if (grub_lower_mem < GRUB_MEMORY_MACHINE_RESERVED_END)
grub_fatal ("too small memory");
#endif
/* FIXME: This prevents loader/i386/linux.c from using low memory. When our
heap implements support for requesting a chunk in low memory, this should

View file

@ -36,6 +36,22 @@ struct grub_machine_mmap_entry
} __attribute__((packed));
/*
*
* grub_get_conv_memsize(i) : return the conventional memory size in KB.
* BIOS call "INT 12H" to get conventional memory size
* The return value in AX.
*/
static inline grub_uint16_t
grub_get_conv_memsize (void)
{
struct grub_bios_int_registers regs;
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
grub_bios_interrupt (0x12, &regs);
return regs.eax & 0xffff;
}
/*
* grub_get_ext_memsize() : return the extended memory size in KB.
* BIOS call "INT 15H, AH=88H" to get extended memory size
@ -155,6 +171,10 @@ grub_machine_mmap_iterate (grub_memory_hook_t hook)
{
grub_uint32_t eisa_mmap = grub_get_eisa_mmap ();
if (hook (0x0, ((grub_uint32_t) grub_get_conv_memsize ()) << 10,
GRUB_MEMORY_AVAILABLE))
return 0;
if (eisa_mmap)
{
if (hook (0x100000, (eisa_mmap & 0xFFFF) << 10,
@ -162,7 +182,8 @@ grub_machine_mmap_iterate (grub_memory_hook_t hook)
hook (0x1000000, eisa_mmap & ~0xFFFF, GRUB_MEMORY_AVAILABLE);
}
else
hook (0x100000, grub_get_ext_memsize () << 10, GRUB_MEMORY_AVAILABLE);
hook (0x100000, ((grub_uint32_t) grub_get_ext_memsize ()) << 10,
GRUB_MEMORY_AVAILABLE);
}
return 0;

View file

@ -151,8 +151,6 @@ LOCAL (codestart):
addl $(GRUB_KERNEL_MACHINE_RAW_SIZE - GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART), %edx
movl reed_solomon_redundancy, %ecx
leal _start + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART, %eax
testl %edx, %edx
jz post_reed_solomon
call EXT_C (grub_reed_solomon_recover)
jmp post_reed_solomon
@ -224,6 +222,7 @@ multiboot_trampoline:
movb $0xFF, %dh
/* enter the usual booting */
call prot_to_real
jmp LOCAL (codestart)
post_reed_solomon:
@ -649,7 +648,7 @@ FUNCTION(grub_console_getkey)
jae 2f
movl %edx, %eax
leal LOCAL(bypass_table), %edi
movl $((LOCAL(bypass_table_end) - LOCAL(bypass_table)) / 2), %ecx
movl $((LOCAL(bypass_table_end) - LOCAL(bypass_table)) >> 1), %ecx
repne scasw
jz 3f

View file

@ -84,6 +84,9 @@ grub_ieee1275_find_options (void)
if (rc >= 0 && !grub_strcmp (tmp, "Emulated PC"))
is_qemu = 1;
if (grub_strncmp (tmp, "PowerMac", sizeof ("PowerMac") - 1) == 0)
grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_BROKEN_ADDRESS_CELLS);
if (is_smartfirmware)
{
/* Broken in all versions */

View file

@ -31,6 +31,8 @@
#include <grub/ieee1275/console.h>
#include <grub/ieee1275/ofdisk.h>
#include <grub/ieee1275/ieee1275.h>
#include <grub/ieee1275/ofnet.h>
#include <grub/net.h>
#include <grub/offsets.h>
#include <grub/memory.h>
@ -74,7 +76,22 @@ grub_machine_set_prefix (void)
char bootpath[64]; /* XXX check length */
char *filename;
char *prefix;
grub_bootp_t bootp_pckt;
char addr[GRUB_NET_MAX_STR_ADDR_LEN];
/* Set the net prefix when possible. */
if (grub_getbootp && (bootp_pckt = grub_getbootp()))
{
grub_uint32_t n = bootp_pckt->siaddr;
grub_snprintf (addr, GRUB_NET_MAX_STR_ADDR_LEN, "%d.%d.%d.%d",
((n >> 24) & 0xff), ((n >> 16) & 0xff),
((n >> 8) & 0xff), ((n >> 0) & 0xff));
prefix = grub_xasprintf ("(tftp,%s)%s", addr,grub_prefix);
grub_env_set ("prefix", prefix);
grub_free (prefix);
return;
}
if (grub_prefix[0])
{
grub_env_set ("prefix", grub_prefix);

View file

@ -50,6 +50,12 @@ grub_machine_mmap_iterate (grub_memory_hook_t hook)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
"couldn't examine /memory/available property");
if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_BROKEN_ADDRESS_CELLS))
{
address_cells = 1;
size_cells = 1;
}
/* Decode each entry and call `hook'. */
i = 0;
available_size /= sizeof (grub_uint32_t);

View file

@ -28,6 +28,7 @@
#include <grub/net/disknet.h>
#include <grub/net/tftp.h>
grub_bootp_t (*grub_getbootp) (void);
enum grub_ieee1275_parse_type
{
GRUB_PARSE_FILENAME,

View file

@ -189,6 +189,8 @@ grub_main (void)
for convenience. */
grub_machine_set_prefix ();
grub_set_root_dev ();
grub_env_export ("root");
grub_env_export ("prefix");
grub_register_core_commands ();

View file

@ -41,6 +41,7 @@ extern void grub_at_keyboard_init (void);
extern void grub_serial_init (void);
extern void grub_terminfo_init (void);
extern void grub_keylayouts_init (void);
extern void grub_boot_init (void);
/* FIXME: use interrupt to count high. */
grub_uint64_t
@ -210,6 +211,8 @@ grub_machine_init (void)
grub_terminfo_init ();
grub_serial_init ();
grub_boot_init ();
}
void
@ -223,6 +226,8 @@ grub_halt (void)
grub_outb (grub_inb (GRUB_CPU_LOONGSON_GPIOCFG)
& ~GRUB_CPU_LOONGSON_SHUTDOWN_GPIO, GRUB_CPU_LOONGSON_GPIOCFG);
grub_millisleep (1500);
grub_printf ("Shutdown failed\n");
grub_refresh ();
while (1);
@ -239,6 +244,8 @@ grub_reboot (void)
{
grub_write_ec (GRUB_MACHINE_EC_COMMAND_REBOOT);
grub_millisleep (1500);
grub_printf ("Reboot failed\n");
grub_refresh ();
while (1);

View file

@ -37,80 +37,80 @@
.text
FUNCTION(efi_wrap_0)
subq $40, %rsp
subq $48, %rsp
call *%rdi
addq $40, %rsp
addq $48, %rsp
ret
FUNCTION(efi_wrap_1)
subq $40, %rsp
subq $48, %rsp
mov %rsi, %rcx
call *%rdi
addq $40, %rsp
addq $48, %rsp
ret
FUNCTION(efi_wrap_2)
subq $40, %rsp
subq $48, %rsp
mov %rsi, %rcx
call *%rdi
addq $40, %rsp
addq $48, %rsp
ret
FUNCTION(efi_wrap_3)
subq $40, %rsp
subq $48, %rsp
mov %rcx, %r8
mov %rsi, %rcx
call *%rdi
addq $40, %rsp
addq $48, %rsp
ret
FUNCTION(efi_wrap_4)
subq $40, %rsp
subq $48, %rsp
mov %r8, %r9
mov %rcx, %r8
mov %rsi, %rcx
call *%rdi
addq $40, %rsp
addq $48, %rsp
ret
FUNCTION(efi_wrap_5)
subq $40, %rsp
subq $48, %rsp
mov %r9, 32(%rsp)
mov %r8, %r9
mov %rcx, %r8
mov %rsi, %rcx
call *%rdi
addq $40, %rsp
addq $48, %rsp
ret
FUNCTION(efi_wrap_6)
subq $56, %rsp
mov 56+8(%rsp), %rax
subq $64, %rsp
mov 64+8(%rsp), %rax
mov %rax, 40(%rsp)
mov %r9, 32(%rsp)
mov %r8, %r9
mov %rcx, %r8
mov %rsi, %rcx
call *%rdi
addq $56, %rsp
addq $64, %rsp
ret
FUNCTION(efi_wrap_10)
subq $88, %rsp
mov 88+40(%rsp), %rax
subq $96, %rsp
mov 96+40(%rsp), %rax
mov %rax, 72(%rsp)
mov 88+32(%rsp), %rax
mov 96+32(%rsp), %rax
mov %rax, 64(%rsp)
mov 88+24(%rsp), %rax
mov 96+24(%rsp), %rax
mov %rax, 56(%rsp)
mov 88+16(%rsp), %rax
mov 96+16(%rsp), %rax
mov %rax, 48(%rsp)
mov 88+8(%rsp), %rax
mov 96+8(%rsp), %rax
mov %rax, 40(%rsp)
mov %r9, 32(%rsp)
mov %r8, %r9
mov %rcx, %r8
mov %rsi, %rcx
call *%rdi
addq $88, %rsp
addq $96, %rsp
ret

View file

@ -340,17 +340,20 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv,
}
option = grub_strchr (arg, '=');
if (option) {
arglen = option - arg - 2;
option++;
} else {
if (option)
{
arglen = option - arg - 2;
option++;
}
else
arglen = grub_strlen (arg) - 2;
if (argv[curarg + 1])
option = argv[curarg + 1][0] == '-' ? 0 : argv[++curarg];
}
opt = find_long (cmd->options, arg + 2, arglen);
if (!option && argv[curarg + 1] && argv[curarg + 1][0] != '-'
&& opt->type != ARG_TYPE_NONE)
option = argv[++curarg];
if (!opt && (cmd->cmd->flags & GRUB_COMMAND_ACCEPT_DASH))
{
if (add_arg (arg) != 0)

105
grub-core/lib/cmdline.c Normal file
View file

@ -0,0 +1,105 @@
/* cmdline.c - linux command line handling */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2010 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/lib/cmdline.h>
#include <grub/misc.h>
static unsigned int check_arg (char *c, int *has_space)
{
int space = 0;
unsigned int size = 0;
while (*c)
{
if (*c == '\\' || *c == '\'' || *c == '"')
size++;
else if (*c == ' ')
space = 1;
size++;
c++;
}
if (space)
size += 2;
if (has_space)
*has_space = space;
return size;
}
unsigned int grub_loader_cmdline_size (int argc, char *argv[])
{
int i;
unsigned int size = 0;
for (i = 0; i < argc; i++)
{
size += check_arg (argv[i], 0);
size++; /* Separator space or NULL. */
}
return size;
}
int grub_create_loader_cmdline (int argc, char *argv[], char *buf,
grub_size_t size)
{
int i, space;
unsigned int arg_size;
char *c;
for (i = 0; i < argc; i++)
{
c = argv[i];
arg_size = check_arg(argv[i], &space);
arg_size++; /* Separator space or NULL. */
if (size < arg_size)
break;
size -= arg_size;
if (space)
*buf++ = '"';
while (*c)
{
if (*c == '\\' || *c == '\'' || *c == '"')
*buf++ = '\\';
*buf++ = *c;
c++;
}
if (space)
*buf++ = '"';
*buf++ = ' ';
}
/* Replace last space with null. */
if (i)
buf--;
*buf = 0;
return i;
}

View file

@ -62,13 +62,25 @@ grub_relocator_firmware_fill_events (struct grub_relocator_mmap_event *events)
(char *) desc < ((char *) descs + mmapsize);
desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
{
grub_uint64_t start = desc->physical_start;
grub_uint64_t end = desc->physical_start + (desc->num_pages << 12);
/* post-4G addresses are never supported on 32-bit EFI.
Moreover it has been reported that some 64-bit EFI contrary to the
spec don't map post-4G pages. So if you enable post-4G allocations,
map pages manually or check that they are mapped.
*/
if (end >= 0x100000000ULL)
end = 0x100000000ULL;
if (end <= start)
continue;
if (desc->type != GRUB_EFI_CONVENTIONAL_MEMORY)
continue;
events[counter].type = REG_FIRMWARE_START;
events[counter].pos = desc->physical_start;
events[counter].pos = start;
counter++;
events[counter].type = REG_FIRMWARE_END;
events[counter].pos = desc->physical_start + (desc->num_pages << 12);
events[counter].pos = end;
counter++;
}
@ -85,6 +97,9 @@ grub_relocator_firmware_alloc_region (grub_addr_t start, grub_size_t size)
if (grub_efi_is_finished)
return 1;
grub_dprintf ("relocator", "EFI alloc: %llx, %llx\n",
(unsigned long long) start, (unsigned long long) size);
b = grub_efi_system_table->boot_services;
status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_ADDRESS,
GRUB_EFI_LOADER_DATA, size >> 12, &address);

View file

@ -19,6 +19,7 @@
#include <grub/env.h>
#include <grub/misc.h>
#include <grub/disk.h>
#include <grub/machine/biosnum.h>
static int
grub_get_root_biosnumber_default (void)

View file

@ -58,7 +58,7 @@ struct legacy_command
const char *longdesc;
};
struct legacy_command legacy_commands[] =
static struct legacy_command legacy_commands[] =
{
{"blocklist", "blocklist '%s'\n", NULL, 0, 1, {TYPE_FILE}, 0, "FILE",
"Print the blocklist notation of the file FILE."},
@ -322,24 +322,23 @@ struct legacy_command legacy_commands[] =
char *
grub_legacy_escape (const char *in, grub_size_t len)
{
const char *ptr;
char *ret, *outptr;
char *ptr;
char *ret;
char saved;
int overhead = 0;
for (ptr = in; ptr < in + len && *ptr; ptr++)
if (*ptr == '\'' || *ptr == '\\')
overhead++;
for (ptr = (char*)in; ptr < in + len && *ptr; ptr++)
if (*ptr == '\'')
overhead += 3;
ret = grub_malloc (ptr - in + overhead + 1);
if (!ret)
return NULL;
outptr = ret;
for (ptr = in; ptr < in + len && *ptr; ptr++)
{
if (*ptr == '\'' || *ptr == '\\')
*outptr++ = '\\';
*outptr++ = *ptr;
}
*outptr++ = 0;
ptr = (char*)in;
saved = ptr[len];
ptr[len] = '\0';
grub_strchrsub (ret, ptr, '\'', "'\\''");
ptr[len] = saved;
return ret;
}
@ -622,12 +621,13 @@ grub_legacy_parse (const char *buf, char **entryname, char **suffix)
{
for (; *ptr && grub_isspace (*ptr); ptr++);
for (; *ptr && !grub_isspace (*ptr); ptr++)
if (*ptr == '\\' || *ptr == '\'')
overhead++;
if (*ptr == '\'')
overhead += 3;
if (*ptr)
ptr++;
overhead += 3;
}
outptr0 = args[i] = grub_malloc (overhead + (ptr - curarg));
if (!outptr0)
return NULL;
@ -641,9 +641,15 @@ grub_legacy_parse (const char *buf, char **entryname, char **suffix)
*outptr++ = '\'';
for (; *ptr && !grub_isspace (*ptr); ptr++)
{
if (*ptr == '\\' || *ptr == '\'')
*outptr++ = '\\';
*outptr++ = *ptr;
if (*ptr == '\'')
{
*outptr++ = '\'';
*outptr++ = '\\';
*outptr++ = '\'';
*outptr++ = '\'';
}
else
*outptr++ = *ptr;
}
*outptr++ = '\'';
if (*ptr)

View file

@ -25,6 +25,12 @@
#include <grub/dl.h>
#include <grub/crypto.h>
#ifdef GRUB_CPU_WORDS_BIGENDIAN
#define WORDS_BIGENDIAN
#else
#undef WORDS_BIGENDIAN
#endif
#define __GNU_LIBRARY__
#define DIM ARRAY_SIZE

View file

@ -0,0 +1 @@
#include <sys/types.h>

View file

@ -32,4 +32,15 @@ typedef grub_uint16_t uint16_t;
typedef grub_uint32_t uint32_t;
typedef grub_uint64_t uint64_t;
typedef grub_int8_t int8_t;
typedef grub_int16_t int16_t;
typedef grub_int32_t int32_t;
typedef grub_int64_t int64_t;
#ifdef GRUB_CPU_WORDS_BIGENDIAN
#define WORDS_BIGENDIAN
#else
#undef WORDS_BIGENDIAN
#endif
#endif

View file

@ -18,6 +18,8 @@
#ifdef TEST
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define xmalloc malloc
#define grub_memset memset
#define grub_memcpy memcpy
@ -25,8 +27,6 @@
#ifndef STANDALONE
#ifdef TEST
#include <string.h>
#include <stdlib.h>
typedef unsigned int grub_size_t;
typedef unsigned char grub_uint8_t;
typedef unsigned short grub_uint16_t;
@ -45,6 +45,7 @@ typedef unsigned char grub_uint8_t;
typedef unsigned short grub_uint16_t;
#else
#include <grub/types.h>
#include <grub/misc.h>
#endif
void
grub_reed_solomon_recover (void *ptr_, grub_size_t s, grub_size_t rs);
@ -59,7 +60,9 @@ typedef grub_uint16_t gf_double_t;
static char *gf_invert __attribute__ ((section(".text"))) = (void *) 0x100000;
static char *scratch __attribute__ ((section(".text"))) = (void *) 0x100100;
#else
#if defined (STANDALONE)
static char *scratch;
#endif
static grub_uint8_t gf_invert[256];
#endif
@ -207,11 +210,12 @@ gauss_solve (gf_single_t *eq, int n, int m, gf_single_t *sol)
#ifndef STANDALONE
chosen = xmalloc (n * sizeof (int));
grub_memset (chosen, -1, n * sizeof (int));
#else
chosen = (void *) scratch;
scratch += n;
scratch += n * sizeof (int);
#endif
for (i = 0; i < n; i++)
chosen[i] = -1;
for (i = 0; i < m; i++)
sol[i] = 0;
gauss_eliminate (eq, n, m, chosen);
@ -228,7 +232,7 @@ gauss_solve (gf_single_t *eq, int n, int m, gf_single_t *sol)
#ifndef STANDALONE
free (chosen);
#else
scratch -= n;
scratch -= n * sizeof (int);
#endif
}
@ -370,6 +374,10 @@ decode_block (gf_single_t *ptr, grub_size_t s,
grub_size_t rr = (rs + SECTOR_SIZE - 1 - i) / SECTOR_SIZE;
gf_single_t m[ds + rr];
/* Nothing to do. */
if (!ds || !rr)
continue;
for (j = 0; j < (int) ds; j++)
m[j] = ptr[SECTOR_SIZE * j + i];
for (j = 0; j < (int) rr; j++)
@ -412,6 +420,10 @@ grub_reed_solomon_add_redundancy (void *buffer, grub_size_t data_size,
gf_single_t *ptr = buffer;
gf_single_t *rptr = ptr + s;
/* Nothing to do. */
if (!rs)
return;
while (s > 0)
{
grub_size_t tt;
@ -421,8 +433,8 @@ grub_reed_solomon_add_redundancy (void *buffer, grub_size_t data_size,
tt = cs + crs;
if (tt > MAX_BLOCK_SIZE)
{
cs = (cs * MAX_BLOCK_SIZE) / tt;
crs = (crs * MAX_BLOCK_SIZE) / tt;
cs = ((cs * (MAX_BLOCK_SIZE / 512)) / tt) * 512;
crs = ((crs * (MAX_BLOCK_SIZE / 512)) / tt) * 512;
}
encode_block (ptr, cs, rptr, crs);
ptr += cs;
@ -439,6 +451,10 @@ grub_reed_solomon_recover (void *ptr_, grub_size_t s, grub_size_t rs)
gf_single_t *ptr = ptr_;
gf_single_t *rptr = ptr + s;
/* Nothing to do. */
if (!rs)
return;
#if defined (STANDALONE)
init_inverts ();
#endif
@ -452,8 +468,8 @@ grub_reed_solomon_recover (void *ptr_, grub_size_t s, grub_size_t rs)
tt = cs + crs;
if (tt > MAX_BLOCK_SIZE)
{
cs = cs * MAX_BLOCK_SIZE / tt;
crs = crs * MAX_BLOCK_SIZE / tt;
cs = ((cs * (MAX_BLOCK_SIZE / 512)) / tt) * 512;
crs = ((crs * (MAX_BLOCK_SIZE / 512)) / tt) * 512;
}
decode_block (ptr, cs, rptr, crs);
ptr += cs;
@ -485,14 +501,10 @@ main (int argc, char **argv)
fseek (in, 0, SEEK_END);
s = ftell (in);
fseek (in, 0, SEEK_SET);
rs = 1024 * ((s + MAX_BLOCK_SIZE - 1) / (MAX_BLOCK_SIZE - 1024));
rs = s / 3;
buf = xmalloc (s + rs + SECTOR_SIZE);
fread (buf, 1, s, in);
s = 0x5fbb;
rs = 0x6af9;
#if 0
grub_reed_solomon_add_redundancy (buf, s, rs);
out = fopen ("tst_rs.bin", "wb");
@ -504,9 +516,6 @@ main (int argc, char **argv)
out = fopen ("tst_dam.bin", "wb");
fwrite (buf, 1, s + rs, out);
fclose (out);
#endif
s = 0x5fbb;
rs = 0x6af9;
grub_reed_solomon_recover (buf, s, rs);
out = fopen ("tst_rec.bin", "wb");

View file

@ -77,10 +77,10 @@ struct grub_relocator_fw_leftover
grub_uint8_t freebytes[GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT / 8];
};
struct grub_relocator_fw_leftover *leftovers;
static struct grub_relocator_fw_leftover *leftovers;
#endif
struct grub_relocator_extra_block *extra_blocks;
static struct grub_relocator_extra_block *extra_blocks;
void *
get_virtual_current_address (grub_relocator_chunk_t in)
@ -134,9 +134,10 @@ allocate_regstart (grub_phys_addr_t addr, grub_size_t size, grub_mm_region_t rb,
grub_addr_t newreg_size, newreg_presize;
grub_mm_header_t new_header;
grub_mm_header_t hb = (grub_mm_header_t) (rb + 1);
grub_dprintf ("relocator", "ra = %p, rb = %p\n", regancestor, rb);
#ifdef DEBUG_RELOCATOR_NOMEM_DPRINTF
grub_dprintf ("relocator", "ra = %p, rb = %p\n", regancestor, rb);
#endif
newreg_start = ALIGN_UP (newreg_raw_start, GRUB_MM_ALIGN);
newreg_presize = newreg_start - newreg_raw_start;
newreg_size = rb->size - (newreg_start - (grub_addr_t) rb);
@ -179,11 +180,12 @@ allocate_regstart (grub_phys_addr_t addr, grub_size_t size, grub_mm_region_t rb,
if ((void *) h < (void *) (newreg + 1))
grub_fatal ("Failed to adjust memory region: %p, %p, %p, %p, %p",
newreg, newreg->first, h, hp, hb);
#ifdef DEBUG_RELOCATOR_NOMEM_DPRINTF
if ((void *) h == (void *) (newreg + 1))
grub_dprintf ("relocator",
"Free start memory region: %p, %p, %p, %p, %p",
newreg, newreg->first, h, hp, hb);
#endif
hp = h;
h = h->next;
}
@ -200,10 +202,12 @@ allocate_inreg (grub_phys_addr_t paddr, grub_size_t size,
struct grub_mm_header *foll = NULL;
grub_addr_t vaddr = (grub_addr_t) hb + (paddr - grub_vtop (hb));
#ifdef DEBUG_RELOCATOR_NOMEM_DPRINTF
grub_dprintf ("relocator", "inreg paddr = 0x%lx, size = %lu,"
" hb = %p, hbp = %p, rb = %p, vaddr = 0x%lx\n",
(unsigned long) paddr, (unsigned long) size, hb, hbp,
rb, (unsigned long) vaddr);
#endif
if (ALIGN_UP (vaddr + size, GRUB_MM_ALIGN) + GRUB_MM_ALIGN
<= (grub_addr_t) (hb + hb->size))
@ -211,8 +215,10 @@ allocate_inreg (grub_phys_addr_t paddr, grub_size_t size,
foll = (void *) ALIGN_UP (vaddr + size, GRUB_MM_ALIGN);
foll->magic = GRUB_MM_FREE_MAGIC;
foll->size = hb + hb->size - foll;
#ifdef DEBUG_RELOCATOR_NOMEM_DPRINTF
grub_dprintf ("relocator", "foll = %p, foll->size = %lu\n", foll,
(unsigned long) foll->size);
#endif
}
if (vaddr - (grub_addr_t) hb >= sizeof (*hb))
@ -597,7 +603,8 @@ malloc_in_range (struct grub_relocator *rel,
events[N].hancestor = pa;
N++;
events[N].type = REG_BEG_END;
events[N].pos = grub_vtop (p + p->size) - sizeof (*r);
events[N].pos = grub_vtop (p + p->size) - sizeof (*r)
- sizeof (struct grub_mm_header);
N++;
}
else
@ -818,9 +825,11 @@ malloc_in_range (struct grub_relocator *rel,
fend
= ALIGN_UP (alloc_end,
GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT);
#ifdef DEBUG_RELOCATOR_NOMEM_DPRINTF
grub_dprintf ("relocator", "requesting %lx-%lx\n",
(unsigned long) fstart,
(unsigned long) fend);
#endif
/* The failure here can be very expensive. */
if (!grub_relocator_firmware_alloc_region (fstart,
fend - fstart))
@ -1281,23 +1290,8 @@ grub_relocator_alloc_chunk_addr (struct grub_relocator *rel,
chunk->srcv = grub_map_memory (chunk->src, chunk->size);
*out = chunk;
#ifdef DEBUG_RELOCATOR
{
grub_mm_region_t r;
grub_mm_header_t p;
grub_memset (chunk->srcv, 0xfa, chunk->size);
for (r = grub_mm_base; r; r = r->next)
{
p = r->first;
do
{
if ((grub_addr_t) p < (grub_addr_t) (r + 1)
|| (grub_addr_t) p >= (grub_addr_t) (r + 1) + r->size)
grub_fatal (__FILE__ ":%d: out of range pointer: %p\n", __LINE__, p);
p = p->next;
}
while (p != r->first);
}
}
grub_memset (chunk->srcv, 0xfa, chunk->size);
grub_mm_check ();
#endif
return GRUB_ERR_NONE;
}
@ -1435,24 +1429,8 @@ grub_relocator_alloc_chunk_align (struct grub_relocator *rel,
chunk->srcv = grub_map_memory (chunk->src, chunk->size);
*out = chunk;
#ifdef DEBUG_RELOCATOR
{
grub_mm_region_t r;
grub_mm_header_t p;
grub_memset (chunk->srcv, 0xfa, chunk->size);
for (r = grub_mm_base; r; r = r->next)
{
p = r->first;
do
{
if ((grub_addr_t) p < (grub_addr_t) (r + 1)
|| (grub_addr_t) p >= (grub_addr_t) (r + 1) + r->size)
grub_fatal (__FILE__ "%d: out of range pointer: %p\n", __LINE__, p);
p = p->next;
}
while (p != r->first);
}
}
grub_memset (chunk->srcv, 0xfa, chunk->size);
grub_mm_check ();
#endif
return GRUB_ERR_NONE;
}

View file

@ -65,7 +65,7 @@ static void *kern_chunk_src;
static grub_uint32_t bootflags;
static int is_elf_kernel, is_64bit;
static grub_uint32_t openbsd_root;
struct grub_relocator *relocator = NULL;
static struct grub_relocator *relocator = NULL;
static struct grub_openbsd_ramdisk_descriptor openbsd_ramdisk;
struct bsd_tag
@ -252,7 +252,7 @@ struct grub_e820_mmap
#define GRUB_E820_RESERVED 2
#define GRUB_E820_ACPI 3
#define GRUB_E820_NVS 4
#define GRUB_E820_EXEC_CODE 5
#define GRUB_E820_BADRAM 5
static void
generate_e820_mmap (grub_size_t *len, grub_size_t *cnt, void *buf)
@ -521,6 +521,8 @@ grub_netbsd_list_modules (void)
/* This function would be here but it's under different license. */
#include "bsd_pagetable.c"
static grub_uint32_t freebsd_bootdev, freebsd_biosdev;
static grub_err_t
grub_freebsd_boot (void)
{
@ -528,7 +530,6 @@ grub_freebsd_boot (void)
grub_uint8_t *p, *p0;
grub_addr_t p_target;
grub_size_t p_size = 0;
grub_uint32_t bootdev, biosdev, unit, slice, part;
grub_err_t err;
grub_size_t tag_buf_len = 0;
@ -564,11 +565,7 @@ grub_freebsd_boot (void)
bi.version = FREEBSD_BOOTINFO_VERSION;
bi.length = sizeof (bi);
grub_bsd_get_device (&biosdev, &unit, &slice, &part);
bootdev = (FREEBSD_B_DEVMAGIC + ((slice + 1) << FREEBSD_B_SLICESHIFT) +
(unit << FREEBSD_B_UNITSHIFT) + (part << FREEBSD_B_PARTSHIFT));
bi.boot_device = biosdev;
bi.boot_device = freebsd_biosdev;
p_size = 0;
grub_env_iterate (iterate_env_count);
@ -741,7 +738,7 @@ grub_freebsd_boot (void)
state.ebp = stack_target;
stack[0] = entry; /* "Return" address. */
stack[1] = bootflags | FREEBSD_RB_BOOTINFO;
stack[2] = bootdev;
stack[2] = freebsd_bootdev;
stack[3] = 0;
stack[4] = 0;
stack[5] = 0;
@ -1371,6 +1368,8 @@ grub_cmd_freebsd (grub_extcmd_context_t ctxt, int argc, char *argv[])
if (grub_bsd_load (argc, argv) == GRUB_ERR_NONE)
{
grub_uint32_t unit, slice, part;
kern_end = ALIGN_PAGE (kern_end);
if (is_elf_kernel)
{
@ -1414,6 +1413,10 @@ grub_cmd_freebsd (grub_extcmd_context_t ctxt, int argc, char *argv[])
if (err)
return err;
}
grub_bsd_get_device (&freebsd_biosdev, &unit, &slice, &part);
freebsd_bootdev = (FREEBSD_B_DEVMAGIC + ((slice + 1) << FREEBSD_B_SLICESHIFT) +
(unit << FREEBSD_B_UNITSHIFT) + (part << FREEBSD_B_PARTSHIFT));
grub_loader_set (grub_freebsd_boot, grub_bsd_unload, 0);
}
@ -1611,7 +1614,7 @@ grub_cmd_freebsd_loadenv (grub_command_t cmd __attribute__ ((unused)),
char *buf = 0, *curr, *next;
int len;
if (kernel_type == KERNEL_TYPE_NONE)
if (! grub_loader_is_loaded ())
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"you need to load the kernel first");
@ -1844,7 +1847,7 @@ grub_cmd_freebsd_module_elf (grub_command_t cmd __attribute__ ((unused)),
grub_file_t file = 0;
grub_err_t err;
if (kernel_type == KERNEL_TYPE_NONE)
if (! grub_loader_is_loaded ())
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"you need to load the kernel first");

View file

@ -195,6 +195,11 @@ SUFFIX (grub_freebsd_load_elfmodule) (struct grub_relocator *relocator,
chunk_size = s->sh_addr + s->sh_size;
}
if (chunk_size < sizeof (e))
chunk_size = sizeof (e);
chunk_size += e.e_phnum * e.e_phentsize;
chunk_size += e.e_shnum * e.e_shentsize;
{
grub_relocator_chunk_t ch;
@ -394,7 +399,7 @@ SUFFIX (grub_netbsd_load_elf_meta) (struct grub_relocator *relocator,
grub_err_t err;
Elf_Ehdr e;
Elf_Shdr *s, *symsh, *strsh;
char *shdr;
char *shdr = NULL;
unsigned symsize, strsize;
void *sym_chunk;
grub_uint8_t *curload;
@ -511,7 +516,7 @@ SUFFIX(grub_openbsd_find_ramdisk) (grub_file_t file,
grub_err_t err;
Elf_Ehdr e;
Elf_Shdr *s;
char *shdr;
char *shdr = NULL;
err = read_headers (file, &e, &shdr);
if (err)

View file

@ -33,6 +33,7 @@
#include <grub/command.h>
#include <grub/i386/relocator.h>
#include <grub/i18n.h>
#include <grub/lib/cmdline.h>
#ifdef GRUB_MACHINE_PCBIOS
#include <grub/i386/pc/vesa_modes_table.h>
@ -135,7 +136,8 @@ find_efi_mmap_size (void)
later, and EFI itself may allocate more. */
mmap_size += (1 << 12);
return page_align (mmap_size);
mmap_size = page_align (mmap_size);
return mmap_size;
}
#endif
@ -312,6 +314,13 @@ grub_linux_setup_video (struct linux_kernel_params *params)
struct grub_video_mode_info mode_info;
void *framebuffer;
grub_err_t err;
grub_video_driver_id_t driver_id;
char *gfxlfbvar = grub_env_get ("gfxpayloadforcelfb");
driver_id = grub_video_get_driver_id ();
if (driver_id == GRUB_VIDEO_DRIVER_NONE)
return 1;
err = grub_video_get_info_and_fini (&mode_info, &framebuffer);
@ -338,12 +347,40 @@ grub_linux_setup_video (struct linux_kernel_params *params)
params->reserved_mask_size = mode_info.reserved_mask_size;
params->reserved_field_pos = mode_info.reserved_field_pos;
if (gfxlfbvar && (gfxlfbvar[0] == '1' || gfxlfbvar[0] == 'y'))
params->have_vga = GRUB_VIDEO_LINUX_TYPE_SIMPLE;
else
{
switch (driver_id)
{
case GRUB_VIDEO_DRIVER_VBE:
params->lfb_size >>= 16;
params->have_vga = GRUB_VIDEO_LINUX_TYPE_VESA;
break;
case GRUB_VIDEO_DRIVER_EFI_UGA:
case GRUB_VIDEO_DRIVER_EFI_GOP:
params->have_vga = GRUB_VIDEO_LINUX_TYPE_EFIFB;
break;
/* FIXME: check if better id is available. */
case GRUB_VIDEO_DRIVER_SM712:
case GRUB_VIDEO_DRIVER_VGA:
case GRUB_VIDEO_DRIVER_CIRRUS:
case GRUB_VIDEO_DRIVER_BOCHS:
/* Make gcc happy. */
case GRUB_VIDEO_DRIVER_SDL:
case GRUB_VIDEO_DRIVER_NONE:
params->have_vga = GRUB_VIDEO_LINUX_TYPE_SIMPLE;
break;
}
}
#ifdef GRUB_MACHINE_PCBIOS
/* VESA packed modes may come with zeroed mask sizes, which need
to be set here according to DAC Palette width. If we don't,
this results in Linux displaying a black screen. */
if (mode_info.bpp <= 8)
if (driver_id == GRUB_VIDEO_DRIVER_VBE && mode_info.bpp <= 8)
{
struct grub_vbe_info_block controller_info;
int status;
@ -418,9 +455,9 @@ grub_linux_boot (void)
addr, size, GRUB_E820_NVS);
break;
case GRUB_MEMORY_CODE:
case GRUB_MEMORY_BADRAM:
grub_e820_add_region (params->e820_map, &e820_num,
addr, size, GRUB_E820_EXEC_CODE);
addr, size, GRUB_E820_BADRAM);
break;
default:
@ -456,15 +493,7 @@ grub_linux_boot (void)
grub_errno = GRUB_ERR_NONE;
}
if (! grub_linux_setup_video (params))
{
/* Use generic framebuffer unless VESA is known to be supported. */
if (params->have_vga != GRUB_VIDEO_LINUX_TYPE_VESA)
params->have_vga = GRUB_VIDEO_LINUX_TYPE_SIMPLE;
else
params->lfb_size >>= 16;
}
else
if (grub_linux_setup_video (params))
{
#if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_QEMU)
params->have_vga = GRUB_VIDEO_LINUX_TYPE_TEXT;
@ -575,7 +604,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
grub_size_t real_size, prot_size;
grub_ssize_t len;
int i;
char *dest;
grub_dl_ref (my_mod);
@ -655,7 +683,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
goto fail;
}
params->type_of_loader = (LINUX_LOADER_ID_GRUB << 4);
params->type_of_loader = GRUB_LINUX_BOOT_LOADER_TYPE;
/* These two are used (instead of cmd_line_ptr) by older versions of Linux,
and otherwise ignored. */
@ -719,6 +747,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
grub_err_t err;
char *buf;
grub_dl_load ("vbe");
if (grub_strcmp (val, "normal") == 0)
vid_mode = GRUB_LINUX_VID_MODE_NORMAL;
else if (grub_strcmp (val, "ext") == 0)
@ -769,10 +799,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
break;
}
/* We can't detect VESA, but user is implicitly telling us that it
is built-in because `vga=' parameter was used. */
params->have_vga = GRUB_VIDEO_LINUX_TYPE_VESA;
linux_mode = &grub_vesa_mode_table[vid_mode
- GRUB_VESA_MODE_TABLE_START];
@ -834,22 +860,14 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
params->loadflags |= GRUB_LINUX_FLAG_QUIET;
}
/* Specify the boot file. */
dest = grub_stpcpy ((char *) real_mode_mem + GRUB_LINUX_CL_OFFSET,
"BOOT_IMAGE=");
dest = grub_stpcpy (dest, argv[0]);
/* Copy kernel parameters. */
for (i = 1;
i < argc
&& dest + grub_strlen (argv[i]) + 1 < ((char *) real_mode_mem
+ GRUB_LINUX_CL_END_OFFSET);
i++)
{
*dest++ = ' ';
dest = grub_stpcpy (dest, argv[i]);
}
/* Create kernel command line. */
grub_memcpy ((char *)real_mode_mem + GRUB_LINUX_CL_OFFSET, LINUX_IMAGE,
sizeof (LINUX_IMAGE));
grub_create_loader_cmdline (argc, argv,
(char *)real_mode_mem + GRUB_LINUX_CL_OFFSET
+ sizeof (LINUX_IMAGE) - 1,
GRUB_LINUX_CL_END_OFFSET - GRUB_LINUX_CL_OFFSET
- (sizeof (LINUX_IMAGE) - 1));
len = prot_size;
if (grub_file_read (file, prot_mode_mem, len) != len)

View file

@ -47,7 +47,7 @@ struct module
int cmdline_size;
};
struct module *modules, *modules_last;
static struct module *modules, *modules_last;
static grub_size_t cmdline_size;
static grub_size_t total_modcmd;
static unsigned modcnt;
@ -142,7 +142,7 @@ grub_multiboot_load (grub_file_t file)
}
if (header->bss_end_addr)
grub_memset ((grub_uint32_t *) source + load_size, 0,
grub_memset ((grub_uint8_t *) source + load_size, 0,
header->bss_end_addr - header->load_addr - load_size);
grub_multiboot_payload_eip = header->entry_addr;
@ -454,7 +454,7 @@ grub_multiboot_make_mbi (grub_uint32_t *target)
if (err)
return err;
ptrorig = get_virtual_current_address (ch);
ptrdest = (grub_addr_t) get_virtual_current_address (ch);
ptrdest = get_physical_target_address (ch);
*target = ptrdest;
@ -566,6 +566,9 @@ grub_multiboot_make_mbi (grub_uint32_t *target)
mbi->u.elf_sec.shndx = elf_sec_shstrndx;
mbi->flags |= MULTIBOOT_INFO_ELF_SHDR;
ptrorig += elf_sec_entsize * elf_sec_num;
ptrdest += elf_sec_entsize * elf_sec_num;
}
err = retrieve_video_parameters (mbi, ptrorig, ptrdest);
@ -574,6 +577,16 @@ grub_multiboot_make_mbi (grub_uint32_t *target)
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
}
if ((mbi->flags & MULTIBOOT_INFO_FRAMEBUFFER_INFO)
&& mbi->framebuffer_type == MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED)
{
ptrorig += mbi->framebuffer_palette_num_colors
* sizeof (struct multiboot_color);
ptrdest += mbi->framebuffer_palette_num_colors
* sizeof (struct multiboot_color);
}
#if GRUB_MACHINE_HAS_VBE
ptrorig += sizeof (struct grub_vbe_info_block);
ptrdest += sizeof (struct grub_vbe_info_block);
@ -668,6 +681,7 @@ grub_multiboot_add_module (grub_addr_t start, grub_size_t size,
return grub_errno;
newmod->start = start;
newmod->size = size;
newmod->next = 0;
for (i = 0; i < argc; i++)
len += grub_strlen (argv[i]) + 1;

View file

@ -34,6 +34,7 @@
#include <grub/cpu/relocator.h>
#include <grub/video.h>
#include <grub/i386/floppy.h>
#include <grub/lib/cmdline.h>
#define GRUB_LINUX_CL_OFFSET 0x9000
#define GRUB_LINUX_CL_END_OFFSET 0x90FF
@ -86,7 +87,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
grub_size_t real_size;
grub_ssize_t len;
int i;
char *dest;
char *grub_linux_prot_chunk;
int grub_linux_is_bzimage;
grub_addr_t grub_linux_prot_target;
@ -286,21 +286,14 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
((GRUB_LINUX_MAX_SETUP_SECTS - setup_sects - 1)
<< GRUB_DISK_SECTOR_BITS));
/* Specify the boot file. */
dest = grub_stpcpy (grub_linux_real_chunk + GRUB_LINUX_CL_OFFSET,
"BOOT_IMAGE=");
dest = grub_stpcpy (dest, argv[0]);
/* Copy kernel parameters. */
for (i = 1;
i < argc
&& dest + grub_strlen (argv[i]) + 1 < (grub_linux_real_chunk
+ GRUB_LINUX_CL_END_OFFSET);
i++)
{
*dest++ = ' ';
dest = grub_stpcpy (dest, argv[i]);
}
/* Create kernel command line. */
grub_memcpy ((char *)grub_linux_real_chunk + GRUB_LINUX_CL_OFFSET,
LINUX_IMAGE, sizeof (LINUX_IMAGE));
grub_create_loader_cmdline (argc, argv,
(char *)grub_linux_real_chunk
+ GRUB_LINUX_CL_OFFSET + sizeof (LINUX_IMAGE) - 1,
GRUB_LINUX_CL_END_OFFSET - GRUB_LINUX_CL_OFFSET
- (sizeof (LINUX_IMAGE) - 1));
if (grub_linux_is_bzimage)
grub_linux_prot_target = GRUB_LINUX_BZIMAGE_ADDR;

View file

@ -49,7 +49,7 @@ struct tbl_alias
char *name;
};
struct tbl_alias table_aliases[] =
static struct tbl_alias table_aliases[] =
{
{GRUB_EFI_ACPI_20_TABLE_GUID, "ACPI_20"},
{GRUB_EFI_ACPI_TABLE_GUID, "ACPI"},
@ -219,7 +219,7 @@ struct property_descriptor
void *data;
};
struct grub_xnu_devprop_device_descriptor *devices = 0;
static struct grub_xnu_devprop_device_descriptor *devices = 0;
grub_err_t
grub_xnu_devprop_remove_property (struct grub_xnu_devprop_device_descriptor *dev,
@ -951,10 +951,11 @@ grub_err_t
grub_xnu_boot (void)
{
struct grub_xnu_boot_params *bootparams;
void *bp_in;
grub_addr_t bootparams_target;
grub_err_t err;
grub_efi_uintn_t memory_map_size = 0;
grub_efi_memory_descriptor_t *memory_map;
void *memory_map;
grub_addr_t memory_map_target;
grub_efi_uintn_t map_key = 0;
grub_efi_uintn_t descriptor_size = 0;
@ -1006,9 +1007,10 @@ grub_xnu_boot (void)
/* Relocate the boot parameters to heap. */
err = grub_xnu_heap_malloc (sizeof (*bootparams),
(void **) &bootparams, &bootparams_target);
&bp_in, &bootparams_target);
if (err)
return err;
bootparams = bp_in;
/* Set video. */
err = grub_xnu_set_video (bootparams);
@ -1035,7 +1037,7 @@ grub_xnu_boot (void)
memory map growth. */
memory_map_size += 20 * descriptor_size;
err = grub_xnu_heap_malloc (memory_map_size,
(void **) &memory_map, &memory_map_target);
&memory_map, &memory_map_target);
if (err)
return err;
@ -1109,7 +1111,7 @@ grub_xnu_boot (void)
grub_xnu_arg1 = bootparams_target;
grub_autoefi_set_virtual_address_map (memory_map_size, descriptor_size,
descriptor_version,memory_map);
descriptor_version, memory_map);
state.eip = grub_xnu_entry_point;
state.eax = grub_xnu_arg1;

View file

@ -32,6 +32,14 @@
#include <grub/pci.h>
#include <grub/machine/time.h>
#ifdef GRUB_MACHINE_MIPS_YEELOONG
/* This can be detected on runtime from PMON, but:
a) it wouldn't work when GRUB is the firmware
and
b) for now we only support Yeeloong anyway. */
#define LOONGSON_MACHTYPE "machtype=lemote-yeeloong-2f-8.9inches"
#endif
static grub_dl_t my_mod;
static int loaded;
@ -83,7 +91,7 @@ grub_linux_load32 (grub_elf_t elf, void **extra_mem, grub_size_t extra_size)
/* Linux's entry point incorrectly contains a virtual address. */
entry_addr = elf->ehdr.ehdr32.e_entry;
linux_size = grub_elf32_size (elf, &base);
linux_size = grub_elf32_size (elf, &base, 0);
if (linux_size == 0)
return grub_errno;
target_addr = base;
@ -138,7 +146,7 @@ grub_linux_load64 (grub_elf_t elf, void **extra_mem, grub_size_t extra_size)
/* Linux's entry point incorrectly contains a virtual address. */
entry_addr = elf->ehdr.ehdr64.e_entry;
linux_size = grub_elf64_size (elf, &base);
linux_size = grub_elf64_size (elf, &base, 0);
if (linux_size == 0)
return grub_errno;
target_addr = base;
@ -214,6 +222,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
/* For arguments. */
linux_argc = argc;
#ifdef LOONGSON_MACHTYPE
linux_argc++;
#endif
/* Main arguments. */
size = (linux_argc) * sizeof (grub_uint32_t);
/* Initrd address and size. */
@ -226,7 +237,10 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
/* Normal arguments. */
for (i = 1; i < argc; i++)
size += ALIGN_UP (grub_strlen (argv[i]) + 1, 4);
#ifdef LOONGSON_MACHTYPE
size += ALIGN_UP (sizeof (LOONGSON_MACHTYPE), 4);
#endif
/* rd arguments. */
size += ALIGN_UP (sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), 4);
size += ALIGN_UP (sizeof ("rd_size=0xXXXXXXXXXXXXXXXX"), 4);
@ -263,6 +277,16 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
linux_argv++;
linux_args += ALIGN_UP (sizeof ("a0"), 4);
#ifdef LOONGSON_MACHTYPE
/* In Loongson platform, it is the responsibility of the bootloader/firmware
to supply the OS kernel with machine type information. */
grub_memcpy (linux_args, LOONGSON_MACHTYPE, sizeof (LOONGSON_MACHTYPE));
*linux_argv = (grub_uint8_t *) linux_args - (grub_uint8_t *) playground
+ target_addr;
linux_argv++;
linux_args += ALIGN_UP (sizeof (LOONGSON_MACHTYPE), 4);
#endif
for (i = 1; i < argc; i++)
{
grub_memcpy (linux_args, argv[i], grub_strlen (argv[i]) + 1);

View file

@ -54,7 +54,7 @@ struct module
int cmdline_size;
};
struct module *modules, *modules_last;
static struct module *modules, *modules_last;
static grub_size_t cmdline_size;
static grub_size_t total_modcmd;
static unsigned modcnt;

View file

@ -26,6 +26,8 @@
#include <grub/ieee1275/ieee1275.h>
#include <grub/command.h>
#include <grub/i18n.h>
#include <grub/memory.h>
#include <grub/lib/cmdline.h>
#define ELF32_LOADMASK (0xc0000000UL)
#define ELF64_LOADMASK (0xc000000000000000ULL)
@ -45,6 +47,51 @@ static char *linux_args;
typedef void (*kernel_entry_t) (void *, unsigned long, int (void *),
unsigned long, unsigned long);
static grub_addr_t
grub_linux_claimmap_iterate (grub_addr_t target, grub_size_t size,
grub_size_t align)
{
grub_addr_t found_addr = (grub_addr_t) -1;
auto int NESTED_FUNC_ATTR alloc_mem (grub_uint64_t addr, grub_uint64_t len,
grub_memory_type_t type);
int NESTED_FUNC_ATTR alloc_mem (grub_uint64_t addr, grub_uint64_t len,
grub_memory_type_t type)
{
grub_uint64_t end = addr + len;
addr = ALIGN_UP (addr, align);
target = ALIGN_UP (target, align);
/* Target above the memory chunk. */
if (type != GRUB_MEMORY_AVAILABLE || target > end)
return 0;
/* Target inside the memory chunk. */
if (target >= addr && target < end && size <= end - target)
{
if (grub_claimmap (target, size) == GRUB_ERR_NONE)
{
found_addr = target;
return 1;
}
}
/* Target below the memory chunk. */
if (target < addr && addr + size <= end)
{
if (grub_claimmap (addr, size) == GRUB_ERR_NONE)
{
found_addr = addr;
return 1;
}
}
return 0;
}
grub_machine_mmap_iterate (alloc_mem);
return found_addr;
}
static grub_err_t
grub_linux_boot (void)
{
@ -102,34 +149,34 @@ grub_linux_unload (void)
static grub_err_t
grub_linux_load32 (grub_elf_t elf)
{
Elf32_Addr base_addr;
grub_addr_t seg_addr;
grub_uint32_t align;
grub_uint32_t offset;
Elf32_Addr entry;
int found_addr = 0;
/* Linux's entry point incorrectly contains a virtual address. */
entry = elf->ehdr.ehdr32.e_entry & ~ELF32_LOADMASK;
if (entry == 0)
entry = 0x01400000;
linux_size = grub_elf32_size (elf, 0);
linux_size = grub_elf32_size (elf, &base_addr, &align);
if (linux_size == 0)
return grub_errno;
/* Pad it; the kernel scribbles over memory beyond its load address. */
linux_size += 0x100000;
/* Linux's entry point incorrectly contains a virtual address. */
entry = elf->ehdr.ehdr32.e_entry & ~ELF32_LOADMASK;
/* Linux's incorrectly contains a virtual address. */
base_addr &= ~ELF32_LOADMASK;
offset = entry - base_addr;
/* On some systems, firmware occupies the memory we're trying to use.
* Happily, Linux can be loaded anywhere (it relocates itself). Iterate
* until we find an open area. */
for (linux_addr = entry; linux_addr < entry + 200 * 0x100000; linux_addr += 0x100000)
{
grub_dprintf ("loader", "Attempting to claim at 0x%x, size 0x%x.\n",
linux_addr, linux_size);
found_addr = grub_claimmap (linux_addr, linux_size);
if (found_addr != -1)
break;
}
if (found_addr == -1)
seg_addr = grub_linux_claimmap_iterate (base_addr & ~ELF32_LOADMASK, linux_size, align);
if (seg_addr == (grub_addr_t) -1)
return grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't claim memory");
linux_addr = seg_addr + offset;
/* Now load the segments into the area we claimed. */
auto grub_err_t offset_phdr (Elf32_Phdr *phdr, grub_addr_t *addr, int *do_load);
grub_err_t offset_phdr (Elf32_Phdr *phdr, grub_addr_t *addr, int *do_load)
@ -141,9 +188,7 @@ grub_linux_load32 (grub_elf_t elf)
}
*do_load = 1;
/* Linux's program headers incorrectly contain virtual addresses.
* Translate those to physical, and offset to the area we claimed. */
*addr = (phdr->p_paddr & ~ELF32_LOADMASK) + linux_addr;
*addr = (phdr->p_paddr - base_addr) + seg_addr;
return 0;
}
return grub_elf32_load (elf, offset_phdr, 0, 0);
@ -152,34 +197,32 @@ grub_linux_load32 (grub_elf_t elf)
static grub_err_t
grub_linux_load64 (grub_elf_t elf)
{
Elf64_Addr base_addr;
grub_addr_t seg_addr;
grub_uint64_t align;
grub_uint64_t offset;
Elf64_Addr entry;
int found_addr = 0;
/* Linux's entry point incorrectly contains a virtual address. */
entry = elf->ehdr.ehdr64.e_entry & ~ELF64_LOADMASK;
if (entry == 0)
entry = 0x01400000;
linux_size = grub_elf64_size (elf, 0);
linux_size = grub_elf64_size (elf, &base_addr, &align);
if (linux_size == 0)
return grub_errno;
/* Pad it; the kernel scribbles over memory beyond its load address. */
linux_size += 0x100000;
base_addr &= ~ELF64_LOADMASK;
entry = elf->ehdr.ehdr64.e_entry & ~ELF64_LOADMASK;
offset = entry - base_addr;
/* Linux's incorrectly contains a virtual address. */
/* On some systems, firmware occupies the memory we're trying to use.
* Happily, Linux can be loaded anywhere (it relocates itself). Iterate
* until we find an open area. */
for (linux_addr = entry; linux_addr < entry + 200 * 0x100000; linux_addr += 0x100000)
{
grub_dprintf ("loader", "Attempting to claim at 0x%x, size 0x%x.\n",
linux_addr, linux_size);
found_addr = grub_claimmap (linux_addr, linux_size);
if (found_addr != -1)
break;
}
if (found_addr == -1)
seg_addr = grub_linux_claimmap_iterate (base_addr & ~ELF64_LOADMASK, linux_size, align);
if (seg_addr == (grub_addr_t) -1)
return grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't claim memory");
linux_addr = seg_addr + offset;
/* Now load the segments into the area we claimed. */
auto grub_err_t offset_phdr (Elf64_Phdr *phdr, grub_addr_t *addr, int *do_load);
grub_err_t offset_phdr (Elf64_Phdr *phdr, grub_addr_t *addr, int *do_load)
@ -190,9 +233,8 @@ grub_linux_load64 (grub_elf_t elf)
return 0;
}
*do_load = 1;
/* Linux's program headers incorrectly contain virtual addresses.
* Translate those to physical, and offset to the area we claimed. */
*addr = (phdr->p_paddr & ~ELF64_LOADMASK) + linux_addr;
*addr = (phdr->p_paddr - base_addr) + seg_addr;
return 0;
}
return grub_elf64_load (elf, offset_phdr, 0, 0);
@ -203,9 +245,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
{
grub_elf_t elf = 0;
int i;
int size;
char *dest;
grub_dl_ref (my_mod);
@ -240,23 +280,15 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
goto out;
}
size = sizeof ("BOOT_IMAGE=") + grub_strlen (argv[0]);
for (i = 0; i < argc; i++)
size += grub_strlen (argv[i]) + 1;
linux_args = grub_malloc (size);
size = grub_loader_cmdline_size(argc, argv);
linux_args = grub_malloc (size + sizeof (LINUX_IMAGE));
if (! linux_args)
goto out;
/* Specify the boot file. */
dest = grub_stpcpy (linux_args, "BOOT_IMAGE=");
dest = grub_stpcpy (dest, argv[0]);
for (i = 1; i < argc; i++)
{
*dest++ = ' ';
dest = grub_stpcpy (dest, argv[i]);
}
/* Create kernel command line. */
grub_memcpy (linux_args, LINUX_IMAGE, sizeof (LINUX_IMAGE));
grub_create_loader_cmdline (argc, argv, linux_args + sizeof (LINUX_IMAGE) - 1,
size);
out:
@ -287,7 +319,6 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
grub_ssize_t size;
grub_addr_t first_addr;
grub_addr_t addr;
int found_addr = 0;
if (argc == 0)
{
@ -311,20 +342,9 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
/* Attempt to claim at a series of addresses until successful in
the same way that grub_rescue_cmd_linux does. */
for (addr = first_addr; addr < first_addr + 200 * 0x100000; addr += 0x100000)
{
grub_dprintf ("loader", "Attempting to claim at 0x%x, size 0x%x.\n",
addr, size);
found_addr = grub_claimmap (addr, size);
if (found_addr != -1)
break;
}
if (found_addr == -1)
{
grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot claim memory");
goto fail;
}
addr = grub_linux_claimmap_iterate (first_addr, size, 0x100000);
if (addr == (grub_addr_t) -1)
goto fail;
grub_dprintf ("loader", "Loading initrd at 0x%x, size 0x%x\n", addr, size);

View file

@ -27,6 +27,7 @@
#include <grub/command.h>
#include <grub/i18n.h>
#include <grub/memory.h>
#include <grub/lib/cmdline.h>
static grub_dl_t my_mod;
@ -247,7 +248,7 @@ grub_linux_load64 (grub_elf_t elf)
linux_entry = elf->ehdr.ehdr64.e_entry;
linux_addr = 0x40004000;
off = 0x4000;
linux_size = grub_elf64_size (elf, 0);
linux_size = grub_elf64_size (elf, 0, 0);
if (linux_size == 0)
return grub_errno;
@ -295,9 +296,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
{
grub_file_t file = 0;
grub_elf_t elf = 0;
int i;
int size;
char *dest;
grub_dl_ref (my_mod);
@ -333,23 +332,16 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
goto out;
}
size = sizeof ("BOOT_IMAGE=") + grub_strlen (argv[0]);
for (i = 0; i < argc; i++)
size += grub_strlen (argv[i]) + 1;
size = grub_loader_cmdline_size(argc, argv);
linux_args = grub_malloc (size);
linux_args = grub_malloc (size + sizeof (LINUX_IMAGE));
if (! linux_args)
goto out;
/* Specify the boot file. */
dest = grub_stpcpy (linux_args, "BOOT_IMAGE=");
dest = grub_stpcpy (dest, argv[0]);
for (i = 1; i < argc; i++)
{
*dest++ = ' ';
dest = grub_stpcpy (dest, argv[i]);
}
/* Create kernel command line. */
grub_memcpy (linux_args, LINUX_IMAGE, sizeof (LINUX_IMAGE));
grub_create_loader_cmdline (argc, argv, linux_args + sizeof (LINUX_IMAGE) - 1,
size);
out:
if (elf)

View file

@ -34,6 +34,10 @@
#include <grub/env.h>
#include <grub/i18n.h>
#if defined (__i386) && !defined (GRUB_MACHINE_EFI)
#include <grub/autoefi.h>
#endif
struct grub_xnu_devtree_key *grub_xnu_devtree_root = 0;
static int driverspackagenum = 0;
static int driversnum = 0;
@ -338,7 +342,8 @@ grub_cmd_xnu_kernel (grub_command_t cmd __attribute__ ((unused)),
grub_macho_t macho;
grub_uint32_t startcode, endcode;
int i;
char *ptr, *loadaddr;
char *ptr;
void *loadaddr;
grub_addr_t loadaddr_target;
if (argc < 1)
@ -371,7 +376,7 @@ grub_cmd_xnu_kernel (grub_command_t cmd __attribute__ ((unused)),
if (!grub_xnu_relocator)
return grub_errno;
grub_xnu_heap_target_start = startcode;
err = grub_xnu_heap_malloc (endcode - startcode, (void **) &loadaddr,
err = grub_xnu_heap_malloc (endcode - startcode, &loadaddr,
&loadaddr_target);
if (err)
@ -382,7 +387,8 @@ grub_cmd_xnu_kernel (grub_command_t cmd __attribute__ ((unused)),
}
/* Load kernel. */
err = grub_macho_load32 (macho, loadaddr - startcode, GRUB_MACHO_NOBSS);
err = grub_macho_load32 (macho, (char *) loadaddr - startcode,
GRUB_MACHO_NOBSS);
if (err)
{
grub_macho_close (macho);
@ -424,6 +430,12 @@ grub_cmd_xnu_kernel (grub_command_t cmd __attribute__ ((unused)),
if (ptr != grub_xnu_cmdline)
*(ptr - 1) = 0;
#if defined (__i386) && !defined (GRUB_MACHINE_EFI)
err = grub_efiemu_autocore ();
if (err)
return err;
#endif
grub_loader_set (grub_xnu_boot, grub_xnu_unload, 0);
grub_xnu_lock ();
@ -440,7 +452,8 @@ grub_cmd_xnu_kernel64 (grub_command_t cmd __attribute__ ((unused)),
grub_macho_t macho;
grub_uint64_t startcode, endcode;
int i;
char *ptr, *loadaddr;
char *ptr;
void *loadaddr;
grub_addr_t loadaddr_target;
if (argc < 1)
@ -476,7 +489,7 @@ grub_cmd_xnu_kernel64 (grub_command_t cmd __attribute__ ((unused)),
if (!grub_xnu_relocator)
return grub_errno;
grub_xnu_heap_target_start = startcode;
err = grub_xnu_heap_malloc (endcode - startcode, (void **) &loadaddr,
err = grub_xnu_heap_malloc (endcode - startcode, &loadaddr,
&loadaddr_target);
if (err)
@ -487,7 +500,8 @@ grub_cmd_xnu_kernel64 (grub_command_t cmd __attribute__ ((unused)),
}
/* Load kernel. */
err = grub_macho_load64 (macho, loadaddr - startcode, GRUB_MACHO_NOBSS);
err = grub_macho_load64 (macho, (char *) loadaddr - startcode,
GRUB_MACHO_NOBSS);
if (err)
{
grub_macho_close (macho);
@ -529,6 +543,12 @@ grub_cmd_xnu_kernel64 (grub_command_t cmd __attribute__ ((unused)),
if (ptr != grub_xnu_cmdline)
*(ptr - 1) = 0;
#if defined (__i386) && !defined (GRUB_MACHINE_EFI)
err = grub_efiemu_autocore ();
if (err)
return err;
#endif
grub_loader_set (grub_xnu_boot, grub_xnu_unload, 0);
grub_xnu_lock ();
@ -620,7 +640,8 @@ grub_xnu_load_driver (char *infoplistname, grub_file_t binaryfile)
grub_file_t infoplist;
struct grub_xnu_extheader *exthead;
int neededspace = sizeof (*exthead);
grub_uint8_t *buf, *buf0;
grub_uint8_t *buf;
void *buf0;
grub_addr_t buf_target;
grub_size_t infoplistsize = 0, machosize = 0;
char *name, *nameend;
@ -676,7 +697,7 @@ grub_xnu_load_driver (char *infoplistname, grub_file_t binaryfile)
err = grub_xnu_align_heap (GRUB_XNU_PAGESIZE);
if (err)
return err;
err = grub_xnu_heap_malloc (neededspace, (void **) &buf0, &buf_target);
err = grub_xnu_heap_malloc (neededspace, &buf0, &buf_target);
if (err)
return err;
buf = buf0;
@ -688,7 +709,7 @@ grub_xnu_load_driver (char *infoplistname, grub_file_t binaryfile)
/* Load the binary. */
if (macho)
{
exthead->binaryaddr = buf_target + (buf - buf0);
exthead->binaryaddr = buf_target + (buf - (grub_uint8_t *) buf0);
exthead->binarysize = machosize;
if (grub_xnu_is_64bit)
err = grub_macho_readfile64 (macho, buf);
@ -707,7 +728,7 @@ grub_xnu_load_driver (char *infoplistname, grub_file_t binaryfile)
/* Load the plist. */
if (infoplist)
{
exthead->infoplistaddr = buf_target + (buf - buf0);
exthead->infoplistaddr = buf_target + (buf - (grub_uint8_t *) buf0);
exthead->infoplistsize = infoplistsize + 1;
if (grub_file_read (infoplist, buf, infoplistsize)
!= (grub_ssize_t) (infoplistsize))
@ -723,7 +744,7 @@ grub_xnu_load_driver (char *infoplistname, grub_file_t binaryfile)
}
grub_errno = GRUB_ERR_NONE;
exthead->nameaddr = (buf - buf0) + buf_target;
exthead->nameaddr = (buf - (grub_uint8_t *) buf0) + buf_target;
exthead->namesize = namelen + 1;
grub_memcpy (buf, name, namelen);
buf[namelen] = 0;
@ -1198,6 +1219,10 @@ grub_cmd_xnu_kext (grub_command_t cmd __attribute__ ((unused)),
int argc, char *args[])
{
grub_file_t binfile = 0;
if (! grub_xnu_heap_size)
return grub_error (GRUB_ERR_BAD_OS, "no xnu kernel loaded");
if (argc == 2)
{
/* User explicitly specified plist and binary. */
@ -1229,6 +1254,9 @@ grub_cmd_xnu_kextdir (grub_command_t cmd __attribute__ ((unused)),
if (argc != 1 && argc != 2)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "directory name required");
if (! grub_xnu_heap_size)
return grub_error (GRUB_ERR_BAD_OS, "no xnu kernel loaded");
if (argc == 1)
return grub_xnu_scan_dir_for_kexts (args[0],
"console,root,local-root,network-root",
@ -1370,6 +1398,9 @@ grub_cmd_xnu_splash (grub_extcmd_context_t ctxt,
if (argc != 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
if (! grub_xnu_heap_size)
return grub_error (GRUB_ERR_BAD_OS, "no xnu kernel loaded");
if (ctxt->state[XNU_SPLASH_CMD_ARGINDEX_MODE].set &&
grub_strcmp (ctxt->state[XNU_SPLASH_CMD_ARGINDEX_MODE].arg,
"stretch") == 0)
@ -1398,7 +1429,7 @@ grub_cmd_xnu_resume (grub_command_t cmd __attribute__ ((unused)),
#endif
void
grub_xnu_lock ()
grub_xnu_lock (void)
{
if (!locked)
grub_dl_ref (my_mod);
@ -1406,7 +1437,7 @@ grub_xnu_lock ()
}
void
grub_xnu_unlock ()
grub_xnu_unlock (void)
{
if (locked)
grub_dl_unref (my_mod);

View file

@ -194,7 +194,6 @@ grub_mmap_unregister (int handle)
{
struct overlay *curover, *prevover;
grub_efi_boot_services_t *b;
grub_efi_status_t status;
b = grub_efi_system_table->boot_services;
@ -204,7 +203,7 @@ grub_mmap_unregister (int handle)
{
if (curover->handle == handle)
{
status = efi_call_2 (b->free_pages, curover->address, curover->pages);
efi_call_2 (b->free_pages, curover->address, curover->pages);
if (prevover != 0)
prevover->next = curover->next;
else

View file

@ -35,36 +35,40 @@ grub_net_arp_resolve(struct grub_net_network_level_interface *inf,
grub_net_link_level_address_t *hw_addr)
{
struct arp_entry *entry;
struct grub_net_buff *nb;
struct grub_net_buff nb;
struct arphdr *arp_header;
grub_net_link_level_address_t target_hw_addr;
grub_uint8_t *aux, i;
char *aux, arp_data[128];
int i;
/* Check cache table */
/* Check cache table. */
entry = arp_find_entry (proto_addr);
if (entry)
{
*hw_addr = entry->ll_address;
return GRUB_ERR_NONE;
}
/* Build a request packet */
nb = grub_netbuff_alloc (2048);
if (!nb)
return grub_errno;
grub_netbuff_reserve(nb, 2048);
grub_netbuff_push(nb, sizeof(*arp_header) + 2 * (6 + 6));
arp_header = (struct arphdr *)nb->data;
/* Build a request packet. */
nb.head = arp_data;
nb.end = arp_data + sizeof (arp_data);
grub_netbuff_clear (&nb);
grub_netbuff_reserve (&nb,128);
grub_netbuff_push (&nb, sizeof(*arp_header) + 2 * (6 + 4));
arp_header = (struct arphdr *) nb.data;
arp_header->hrd = grub_cpu_to_be16 (GRUB_NET_ARPHRD_ETHERNET);
arp_header->pro = grub_cpu_to_be16 (GRUB_NET_ETHERTYPE_IP);
/* FIXME Add support to ipv6 address. */
arp_header->hln = 6;
arp_header->pln = 4;
arp_header->op = grub_cpu_to_be16 (ARP_REQUEST);
aux = (grub_uint8_t *)arp_header + sizeof(*arp_header);
/* Sender hardware address */
grub_memcpy(aux, &inf->hwaddress.mac, 6);
aux = (char *) arp_header + sizeof (*arp_header);
/* Sender hardware address. */
grub_memcpy (aux, &inf->hwaddress.mac, 6);
aux += 6;
/* Sender protocol address */
grub_memcpy(aux, &inf->address.ipv4, 4);
grub_memcpy (aux, &inf->address.ipv4, 4);
aux += 4;
/* Target hardware address */
for(i = 0; i < 6; i++)
@ -72,49 +76,40 @@ grub_net_arp_resolve(struct grub_net_network_level_interface *inf,
aux += 6;
/* Target protocol address */
grub_memcpy(aux, &proto_addr->ipv4, 4);
grub_memset (&target_hw_addr.mac, 0xff, 6);
send_ethernet_packet (inf, nb, target_hw_addr, GRUB_NET_ETHERTYPE_ARP);
grub_netbuff_clear(nb);
grub_netbuff_reserve(nb, 2048);
grub_uint64_t start_time, current_time;
start_time = grub_get_time_ms();
do
send_ethernet_packet (inf, &nb, target_hw_addr, GRUB_NET_ETHERTYPE_ARP);
for (i = 0; i < 3; i++)
{
grub_net_recv_ethernet_packet (inf, nb, GRUB_NET_ETHERTYPE_ARP);
/* Now check cache table again */
entry = arp_find_entry(proto_addr);
entry = arp_find_entry (proto_addr);
if (entry)
{
grub_memcpy(hw_addr, &entry->ll_address, sizeof (*hw_addr));
grub_netbuff_clear(nb);
return GRUB_ERR_NONE;
}
current_time = grub_get_time_ms();
if (current_time - start_time > 3000)
break;
} while (! entry);
grub_netbuff_clear(nb);
{
grub_memcpy (hw_addr, &entry->ll_address, sizeof (*hw_addr));
return GRUB_ERR_NONE;
}
grub_net_pool_cards (200);
}
return grub_error (GRUB_ERR_TIMEOUT, "Timeout: could not resolve hardware address.");
}
grub_err_t
grub_net_arp_receive (struct grub_net_network_level_interface *inf,
struct grub_net_buff *nb)
grub_net_arp_receive (struct grub_net_buff *nb)
{
struct arphdr *arp_header = (struct arphdr *)nb->data;
struct arp_entry *entry;
grub_uint8_t *sender_hardware_address, *sender_protocol_address;
grub_uint8_t *target_hardware_address, *target_protocol_address;
grub_net_network_level_address_t hwaddress;
struct grub_net_network_level_interface *inf;
sender_hardware_address = (grub_uint8_t *) arp_header + sizeof(*arp_header);
sender_protocol_address = sender_hardware_address + arp_header->hln;
target_hardware_address = sender_protocol_address + arp_header->pln;
target_protocol_address = target_hardware_address + arp_header->hln;
grub_memcpy (&hwaddress.ipv4, sender_protocol_address, 4);
/* Check if the sender is in the cache table */
entry = arp_find_entry(&hwaddress);
/* Update sender hardware address */
@ -134,21 +129,24 @@ grub_net_arp_receive (struct grub_net_network_level_interface *inf,
new_table_entry = 0;
}
/* Am I the protocol address target? */
if (grub_memcmp(target_protocol_address, inf->hwaddress.mac, 6) == 0
&& grub_be_to_cpu16 (arp_header->op) == ARP_REQUEST)
FOR_NET_NETWORK_LEVEL_INTERFACES(inf)
{
grub_net_link_level_address_t aux;
/* Swap hardware fields */
grub_memcpy(target_hardware_address, sender_hardware_address, arp_header->hln);
grub_memcpy(sender_hardware_address, inf->hwaddress.mac, 6);
grub_memcpy(aux.mac, sender_protocol_address, 6);
grub_memcpy(sender_protocol_address, target_protocol_address, arp_header->pln);
grub_memcpy(target_protocol_address, aux.mac, arp_header->pln);
/* Change operation to REPLY and send packet */
arp_header->op = grub_be_to_cpu16 (ARP_REPLY);
grub_memcpy (aux.mac, target_hardware_address, 6);
send_ethernet_packet (inf, nb, aux, GRUB_NET_ETHERTYPE_ARP);
/* Am I the protocol address target? */
if (grub_memcmp (target_protocol_address, &inf->address.ipv4, 6) == 0
&& grub_be_to_cpu16 (arp_header->op) == ARP_REQUEST)
{
grub_net_link_level_address_t aux;
/* Swap hardware fields */
grub_memcpy (target_hardware_address, sender_hardware_address, arp_header->hln);
grub_memcpy (sender_hardware_address, inf->hwaddress.mac, 6);
grub_memcpy (aux.mac, sender_protocol_address, 6);
grub_memcpy (sender_protocol_address, target_protocol_address, arp_header->pln);
grub_memcpy (target_protocol_address, aux.mac, arp_header->pln);
/* Change operation to REPLY and send packet */
arp_header->op = grub_be_to_cpu16 (ARP_REPLY);
grub_memcpy (aux.mac, target_hardware_address, 6);
send_ethernet_packet (inf, nb, aux, GRUB_NET_ETHERTYPE_ARP);
}
}
return GRUB_ERR_NONE;
}

View file

View file

@ -78,12 +78,11 @@ bootp_response_properties[] =
{ .name = "bootpreply-packet", .offset = 0x2a },
};
grub_bootp_t
grub_getbootp( void )
static grub_bootp_t
grub_getbootp_real ( void )
{
grub_bootp_t packet = grub_malloc(sizeof *packet);
void *bootp_response = NULL;
grub_bootp_t packet = grub_malloc (sizeof *packet);
char *bootp_response;
grub_ssize_t size;
unsigned int i;
@ -94,30 +93,27 @@ grub_getbootp( void )
break;
if (size < 0)
{
grub_printf("Error to get bootp\n");
return NULL;
}
bootp_response = grub_malloc (size);
if (grub_ieee1275_get_property (grub_ieee1275_chosen,
bootp_response_properties[i].name,
bootp_response ,
size, 0) < 0)
{
grub_printf("Error to get bootp\n");
return NULL;
}
packet = (void *) ((int)bootp_response
+ bootp_response_properties[i].offset);
grub_memcpy (packet, bootp_response + bootp_response_properties[i].offset, sizeof (*packet));
grub_free (bootp_response);
return packet;
}
static
void grub_ofnet_findcards (void)
{
struct grub_net_card *card;
grub_ieee1275_phandle_t devhandle;
grub_net_link_level_address_t lla;
int i = 0;
auto int search_net_devices (struct grub_ieee1275_devalias *alias);
int search_net_devices (struct grub_ieee1275_devalias *alias)
@ -128,53 +124,82 @@ void grub_ofnet_findcards (void)
card = grub_malloc (sizeof (struct grub_net_card));
struct grub_ofnetcard_data *ofdata = grub_malloc (sizeof (struct grub_ofnetcard_data));
ofdata->path = grub_strdup (alias->path);
card->data = ofdata;
grub_ieee1275_finddevice (ofdata->path, &devhandle);
if (grub_ieee1275_get_integer_property
(devhandle, "max-frame-size", &(ofdata->mtu), sizeof (ofdata->mtu), 0))
return grub_error (GRUB_ERR_IO, "Couldn't retrieve mtu size.");
if (grub_ieee1275_get_property (devhandle, "mac-address", &(lla.mac), 6, 0))
return grub_error (GRUB_ERR_IO, "Couldn't retrieve mac address.");
lla.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
card->default_address = lla;
card->data = ofdata;
card->flags = 0;
card->name = grub_xasprintf("eth%d",i++); // grub_strdup (alias->name);
grub_net_card_register (card);
}
return 0;
}
/*Look at all nodes for devices of the type network*/
/* Look at all nodes for devices of the type network. */
grub_ieee1275_devices_iterate (search_net_devices);
}
static
void grub_ofnet_probecards (void)
{
struct grub_net_card *card;
struct grub_net_card_driver *driver;
struct grub_net_network_level_interface *inter;
grub_bootp_t bootp_pckt;
grub_net_network_level_address_t addr;
grub_net_network_level_netaddress_t net;
/*Assign correspondent driver for each device. */
/* Assign correspondent driver for each device. */
FOR_NET_CARDS (card)
{
FOR_NET_CARD_DRIVERS (driver)
{
if (driver->init(card) == GRUB_ERR_NONE)
{
card->driver = driver;
continue;
}
{
card->driver = driver;
bootp_pckt = grub_getbootp ();
if (bootp_pckt)
{
addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
addr.ipv4 = bootp_pckt->yiaddr;
grub_net_add_addr ("bootp_cli_addr", card, addr, card->default_address, 0);
FOR_NET_NETWORK_LEVEL_INTERFACES (inter)
if (grub_strcmp (inter->name, "bootp_cli_addr") == 0)
break;
net.type = addr.type;
net.ipv4.base = addr.ipv4;
net.ipv4.masksize = 24;
grub_net_add_route ("bootp-router", net, inter);
}
grub_free (bootp_pckt);
break;
}
}
}
}
GRUB_MOD_INIT(ofnet)
GRUB_MOD_INIT (ofnet)
{
grub_getbootp = grub_getbootp_real;
grub_net_card_driver_register (&ofdriver);
grub_ofnet_findcards();
grub_ofnet_probecards();
/*init tftp stack - will be handled by module subsystem in the future*/
tftp_ini ();
/*get bootp packet - won't be needed in the future*/
bootp_pckt = grub_getbootp ();
grub_disknet_init();
grub_ofnet_findcards ();
grub_ofnet_probecards ();
}
GRUB_MODE_FINI(ofnet)
GRUB_MOD_FINI (ofnet)
{
grub_net_card_driver_unregister (&ofdriver);
grub_getbootp = NULL;
}

View file

@ -23,23 +23,20 @@ send_ethernet_packet (struct grub_net_network_level_interface *inf,
eth->type = grub_cpu_to_be16 (ethertype);
return inf->card->driver->send (inf->card,nb);
return inf->card->driver->send (inf->card, nb);
}
grub_err_t
grub_net_recv_ethernet_packet (struct grub_net_network_level_interface *inf,
struct grub_net_buff *nb,
grub_uint16_t ethertype)
grub_net_recv_ethernet_packet (struct grub_net_buff *nb)
{
struct etherhdr *eth;
struct llchdr *llch;
struct snaphdr *snaph;
grub_uint16_t type;
inf->card->driver->recv (inf->card, nb);
eth = (struct etherhdr *) nb->data;
type = grub_be_to_cpu16 (eth->type);
grub_netbuff_pull(nb,sizeof (*eth));
grub_netbuff_pull (nb, sizeof (*eth));
if (type <= 1500)
{
@ -56,10 +53,13 @@ grub_net_recv_ethernet_packet (struct grub_net_network_level_interface *inf,
/* ARP packet */
if (type == GRUB_NET_ETHERTYPE_ARP)
grub_net_arp_receive(inf, nb);
{
grub_net_arp_receive (nb);
grub_netbuff_free (nb);
}
/* IP packet */
if(type == GRUB_NET_ETHERTYPE_IP && ethertype == GRUB_NET_ETHERTYPE_IP)
return GRUB_ERR_NONE;
if (type == GRUB_NET_ETHERTYPE_IP)
grub_net_recv_ip_packets (nb);
return GRUB_ERR_NONE;
}

View file

@ -292,7 +292,7 @@ grub_pxefs_label (grub_device_t device __attribute ((unused)),
return GRUB_ERR_NONE;
}
static struct grub_fs grub_pxefs_fs =
static struct grub_net_app_protocol grub_pxefs_fs =
{
.name = "pxe",
.dir = grub_pxefs_dir,

View file

@ -1,6 +1,7 @@
#include <grub/net/ip.h>
#include <grub/misc.h>
#include <grub/net/arp.h>
#include <grub/net/udp.h>
#include <grub/net/ethernet.h>
#include <grub/net.h>
#include <grub/net/netbuff.h>
@ -33,7 +34,7 @@ grub_net_send_ip_packet (struct grub_net_network_level_interface *inf,
grub_net_link_level_address_t ll_target_addr;
grub_err_t err;
grub_netbuff_push(nb,sizeof(*iph));
grub_netbuff_push (nb, sizeof(*iph));
iph = (struct iphdr *) nb->data;
iph->verhdrlen = ((4 << 4) | 5);
@ -49,17 +50,15 @@ grub_net_send_ip_packet (struct grub_net_network_level_interface *inf,
iph->chksum = 0 ;
iph->chksum = ipchksum((void *)nb->data, sizeof(*iph));
/* Determine link layer target address via ARP */
err = grub_net_arp_resolve(inf, target, &ll_target_addr);
/* Determine link layer target address via ARP. */
err = grub_net_arp_resolve (inf, target, &ll_target_addr);
if (err)
return err;
return send_ethernet_packet (inf, nb, ll_target_addr, GRUB_NET_ETHERTYPE_IP);
}
/*
static int
ip_filter (struct grub_net_buff *nb,
struct grub_net_network_level_interface *inf)
ip_filter (struct grub_net_buff *nb)
{
struct iphdr *iph = (struct iphdr *) nb->data;
grub_err_t err;
@ -80,15 +79,22 @@ ip_filter (struct grub_net_buff *nb,
}
return 1;
}
*/
grub_err_t
grub_net_recv_ip_packets (struct grub_net_network_level_interface *inf)
grub_net_recv_ip_packets (struct grub_net_buff *nb)
{
struct grub_net_buff *nb;
nb = grub_netbuff_alloc (2048);
if (!nb)
return grub_errno;
grub_net_recv_ethernet_packet (inf, nb, GRUB_NET_ETHERTYPE_IP);
ip_filter (nb, inf);
struct iphdr *iph = (struct iphdr *) nb->data;
grub_netbuff_pull (nb, sizeof (*iph));
switch (iph->protocol)
{
case IP_UDP:
return grub_net_recv_udp_packet (nb);
break;
default:
grub_netbuff_free (nb);
break;
}
return GRUB_ERR_NONE;
}

View file

@ -17,8 +17,12 @@
*/
#include <grub/net.h>
#include <grub/net/netbuff.h>
#include <grub/time.h>
#include <grub/file.h>
#include <grub/i18n.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/dl.h>
#include <grub/command.h>
#include <grub/env.h>
@ -40,6 +44,7 @@ struct grub_net_route
struct grub_net_route *grub_net_routes = NULL;
struct grub_net_network_level_interface *grub_net_network_level_interfaces = NULL;
struct grub_net_card *grub_net_cards = NULL;
struct grub_net_card_driver *grub_net_card_drivers = NULL;
struct grub_net_network_level_protocol *grub_net_network_level_protocols = NULL;
static inline void
@ -105,7 +110,7 @@ match_net (const grub_net_network_level_netaddress_t *net,
{
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4:
{
grub_int32_t mask = (1 << net->ipv4.masksize) - 1;
grub_int32_t mask = ((1 << net->ipv4.masksize) - 1) << (32 - net->ipv4.masksize);
return ((grub_be_to_cpu32 (net->ipv4.base) & mask)
== (grub_be_to_cpu32 (addr->ipv4) & mask));
}
@ -538,6 +543,7 @@ grub_cmd_listcards (struct grub_command *cmd __attribute__ ((unused)),
}
grub_net_app_level_t grub_net_app_level_list;
struct grub_net_socket *grub_net_sockets;
static grub_net_t
grub_net_open_real (const char *name)
@ -570,6 +576,159 @@ grub_net_open_real (const char *name)
return NULL;
}
static grub_err_t
grub_net_file_open_real (struct grub_file *file, const char *name)
{
grub_err_t err;
grub_net_network_level_address_t addr;
struct grub_net_network_level_interface *inf;
grub_net_network_level_address_t gateway;
grub_net_socket_t socket;
static int port = 25300;
err = grub_net_resolve_address (file->device->net->name
+ sizeof (file->device->net->protocol->name) + 1, &addr);
if (err)
return err;
err = grub_net_route_address (addr, &gateway, &inf);
if (err)
return err;
if ((socket = (grub_net_socket_t) grub_malloc (sizeof (*socket))) == NULL)
return GRUB_ERR_OUT_OF_MEMORY;
socket->inf = inf;
socket->out_nla = addr;
socket->in_port = port++;
socket->status = 0;
socket->app = file->device->net->protocol;
socket->packs = NULL;
file->device->net->socket = socket;
grub_net_socket_register (socket);
if ((err = file->device->net->protocol->open (file,name)))
goto fail;
return GRUB_ERR_NONE;
fail:
grub_net_socket_unregister (socket);
grub_free (socket);
return err;
}
static grub_err_t
receive_packets (struct grub_net_card *card)
{
/* Maybe should be better have a fixed number of packets for each card
and just mark them as used and not used. */
struct grub_net_buff *nb;
nb = grub_netbuff_alloc (1500);
if (!nb)
return grub_errno;
card->driver->recv (card, nb);
return GRUB_ERR_NONE;
}
void
grub_net_pool_cards (unsigned time)
{
struct grub_net_card *card;
grub_uint64_t start_time;
FOR_NET_CARDS (card)
{
start_time = grub_get_time_ms ();
while( (grub_get_time_ms () - start_time) < time)
receive_packets (card);
}
}
static grub_ssize_t
process_packets (grub_file_t file, void *buf, grub_size_t len,
void *NESTED_FUNC_ATTR (hook) (void *dest, const void *src, grub_size_t n))
{
grub_net_socket_t sock = file->device->net->socket;
struct grub_net_buff *nb;
char *ptr = (char *) buf;
grub_size_t amount, total = 0;
int try = 0;
while (try <= 3)
{
while (sock->packs->first)
{
try = 0;
nb = sock->packs->first->nb;
amount = (grub_size_t)(len <= (grub_size_t) (nb->tail - nb->data))? len :(grub_size_t)(nb->tail - nb->data);
len -= amount;
total += amount;
hook (ptr, nb->data, amount);
ptr += amount;
if (amount == (grub_size_t) (nb->tail - nb->data))
{
grub_netbuff_free (nb);
grub_net_remove_packet (sock->packs->first);
}
else
nb->data += amount;
if (!len)
return total;
}
if (sock->status == 1)
{
try++;
grub_net_pool_cards (200);
}
else
return total;
}
return total;
}
/* Read from the packets list*/
static grub_ssize_t
grub_net_read_real (grub_file_t file, void *buf, grub_size_t len )
{
auto void *NESTED_FUNC_ATTR memcpy_hook (void *dest, const void *src, grub_size_t n);
void *NESTED_FUNC_ATTR memcpy_hook (void *dest __attribute__ ((unused)), const void *src __attribute__ ((unused)),
grub_size_t n __attribute__ ((unused)))
{
return grub_memcpy (dest, src, n);
}
return process_packets (file, buf, len, memcpy_hook);
}
/* Read from the packets list*/
static grub_err_t
grub_net_seek_real (struct grub_file *file, grub_off_t offset)
{
grub_net_socket_t sock = file->device->net->socket;
struct grub_net_buff *nb;
grub_size_t len = offset - file->offset;
if (!len)
return GRUB_ERR_NONE;
/* We cant seek backwards past the current packet. */
if (file->offset > offset)
{
nb = sock->packs->first->nb;
return grub_netbuff_push (nb, file->offset - offset);
}
auto void *NESTED_FUNC_ATTR dummy (void *dest, const void *src, grub_size_t n);
void *NESTED_FUNC_ATTR dummy (void *dest __attribute__ ((unused)), const void *src __attribute__ ((unused)),
grub_size_t n __attribute__ ((unused)))
{
return NULL;
}
process_packets (file, NULL, len, dummy);
return GRUB_ERR_NONE;
}
static char *
grub_env_write_readonly (struct grub_env_var *var __attribute__ ((unused)),
const char *val __attribute__ ((unused)))
@ -857,6 +1016,9 @@ GRUB_MOD_INIT(net)
N_("retrieve DHCP option and save it into VAR. If VAR is - then print the value."));
grub_net_open = grub_net_open_real;
grub_file_net_open = grub_net_file_open_real;
grub_file_net_read = grub_net_read_real;
grub_file_net_seek = grub_net_seek_real;
}
GRUB_MOD_FINI(net)
@ -869,4 +1031,6 @@ GRUB_MOD_FINI(net)
grub_unregister_command (cmd_lscards);
grub_unregister_command (cmd_getdhcp);
grub_net_open = NULL;
grub_file_net_read = NULL;
grub_file_net_open = NULL;
}

View file

@ -22,43 +22,43 @@
#include <grub/net/netbuff.h>
grub_err_t grub_netbuff_put (struct grub_net_buff *net_buff ,grub_size_t len)
grub_err_t grub_netbuff_put (struct grub_net_buff *nb ,grub_size_t len)
{
net_buff->tail += len;
if (net_buff->tail > net_buff->end)
nb->tail += len;
if (nb->tail > nb->end)
return grub_error (GRUB_ERR_OUT_OF_RANGE, "put out of the packet range.");
return GRUB_ERR_NONE;
}
grub_err_t grub_netbuff_unput (struct grub_net_buff *net_buff ,grub_size_t len)
grub_err_t grub_netbuff_unput (struct grub_net_buff *nb ,grub_size_t len)
{
net_buff->tail -= len;
if (net_buff->tail < net_buff->head)
nb->tail -= len;
if (nb->tail < nb->head)
return grub_error (GRUB_ERR_OUT_OF_RANGE, "unput out of the packet range.");
return GRUB_ERR_NONE;
}
grub_err_t grub_netbuff_push (struct grub_net_buff *net_buff ,grub_size_t len)
grub_err_t grub_netbuff_push (struct grub_net_buff *nb ,grub_size_t len)
{
net_buff->data -= len;
if (net_buff->data < net_buff->head)
nb->data -= len;
if (nb->data < nb->head)
return grub_error (GRUB_ERR_OUT_OF_RANGE, "push out of the packet range.");
return GRUB_ERR_NONE;
}
grub_err_t grub_netbuff_pull (struct grub_net_buff *net_buff ,grub_size_t len)
grub_err_t grub_netbuff_pull (struct grub_net_buff *nb ,grub_size_t len)
{
net_buff->data += len;
if (net_buff->data > net_buff->end)
nb->data += len;
if (nb->data > nb->end)
return grub_error (GRUB_ERR_OUT_OF_RANGE, "pull out of the packet range.");
return GRUB_ERR_NONE;
}
grub_err_t grub_netbuff_reserve (struct grub_net_buff *net_buff ,grub_size_t len)
grub_err_t grub_netbuff_reserve (struct grub_net_buff *nb ,grub_size_t len)
{
net_buff->data += len;
net_buff->tail += len;
if ((net_buff->tail > net_buff->end) || (net_buff->data > net_buff->end))
nb->data += len;
nb->tail += len;
if ((nb->tail > nb->end) || (nb->data > nb->end))
return grub_error (GRUB_ERR_OUT_OF_RANGE, "reserve out of the packet range.");
return GRUB_ERR_NONE;
}
@ -73,22 +73,23 @@ struct grub_net_buff *grub_netbuff_alloc ( grub_size_t len )
len = ALIGN_UP (len,NETBUFF_ALIGN);
data = grub_memalign (NETBUFF_ALIGN, len + sizeof (*nb));
if (!data)
return NULL;
nb = (struct grub_net_buff *) ((grub_uint8_t *) data + len);
nb->head = nb->data = nb->tail = data;
nb->end = (char *) nb;
nb->end = (char *) nb;
return nb;
}
grub_err_t grub_netbuff_free (struct grub_net_buff *net_buff)
grub_err_t grub_netbuff_free (struct grub_net_buff *nb)
{
grub_free (net_buff->head);
grub_free (nb->head);
return 0;
}
grub_err_t grub_netbuff_clear (struct grub_net_buff *net_buff)
grub_err_t grub_netbuff_clear (struct grub_net_buff *nb)
{
net_buff->data = net_buff->tail = net_buff->head;
nb->data = nb->tail = nb->head;
return 0;
}

Some files were not shown because too many files have changed in this diff Show more