From 9d17de0887ee48f66be4e47be43f8fc6a4ea7799 Mon Sep 17 00:00:00 2001 From: Marcin Krol Date: Tue, 4 Aug 2015 10:54:18 +0000 Subject: [PATCH] - partial PLD merge --- blscfg.patch | 251 +++++++++ efi-net-fix.patch | 59 +++ grub.sysconfig | 10 +- grub2-xfs-Add-helper-for-inode-size.patch | 76 +++ ...e-numbers-to-cpu-endianity-immediate.patch | 82 +++ ...ination-loop-for-directory-iteration.patch | 32 ++ grub2-xfs-V5-filesystem-format-support.patch | 478 ++++++++++++++++++ grub2.spec | 32 +- 8 files changed, 1007 insertions(+), 13 deletions(-) create mode 100644 blscfg.patch create mode 100644 efi-net-fix.patch create mode 100644 grub2-xfs-Add-helper-for-inode-size.patch create mode 100644 grub2-xfs-Convert-inode-numbers-to-cpu-endianity-immediate.patch create mode 100644 grub2-xfs-Fix-termination-loop-for-directory-iteration.patch create mode 100644 grub2-xfs-V5-filesystem-format-support.patch diff --git a/blscfg.patch b/blscfg.patch new file mode 100644 index 0000000..407e832 --- /dev/null +++ b/blscfg.patch @@ -0,0 +1,251 @@ +From ddfb160353df14e9f88affe7498512a553146872 Mon Sep 17 00:00:00 2001 +From: Fedora Ninjas +Date: Tue, 22 Jan 2013 06:31:38 +0100 +Subject: [PATCH 101/152] blscfg: add blscfg module to parse Boot Loader + Specification snippets + +http://www.freedesktop.org/wiki/Specifications/BootLoaderSpec + +Works like this: + + insmod blscfg + bls_import + +Done! You should now have menu items for your snippets in place. + +Signed-off-by: Peter Jones +--- + grub-core/Makefile.core.def | 8 ++ + grub-core/commands/blscfg.c | 201 ++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 209 insertions(+) + create mode 100644 grub-core/commands/blscfg.c + +diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def +index ec46506..7bf1c8a 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -747,6 +747,14 @@ module = { + }; + + module = { ++ name = blscfg; ++ common = commands/blscfg.c; ++ enable = i386_efi; ++ enable = x86_64_efi; ++ enable = i386_pc; ++}; ++ ++module = { + name = boot; + common = commands/boot.c; + i386_pc = lib/i386/pc/biosnum.c; +diff --git a/grub-core/commands/blscfg.c b/grub-core/commands/blscfg.c +new file mode 100644 +index 0000000..4274aca +--- /dev/null ++++ b/grub-core/commands/blscfg.c +@@ -0,0 +1,201 @@ ++/*-*- Mode: C; c-basic-offset: 2; indent-tabs-mode: t -*-*/ ++ ++/* bls.c - implementation of the boot loader spec */ ++ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * ++ * 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 . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++GRUB_MOD_LICENSE ("GPLv3+"); ++ ++#ifdef GRUB_MACHINE_EFI ++#define GRUB_LINUX_CMD "linuxefi" ++#define GRUB_INITRD_CMD "initrdefi" ++#define GRUB_BLS_CONFIG_PATH "/EFI/fedora/loader/entries/" ++#define GRUB_BOOT_DEVICE "($boot)" ++#else ++#define GRUB_LINUX_CMD "linux" ++#define GRUB_INITRD_CMD "initrd" ++#define GRUB_BLS_CONFIG_PATH "/loader/entries/" ++#define GRUB_BOOT_DEVICE "($root)" ++#endif ++ ++static int parse_entry ( ++ const char *filename, ++ const struct grub_dirhook_info *info __attribute__ ((unused)), ++ void *data __attribute__ ((unused))) ++{ ++ grub_size_t n; ++ char *p; ++ grub_file_t f = NULL; ++ grub_off_t sz; ++ char *title = NULL, *options = NULL, *clinux = NULL, *initrd = NULL, *src = NULL; ++ const char *args[2] = { NULL, NULL }; ++ ++ if (filename[0] == '.') ++ return 0; ++ ++ n = grub_strlen (filename); ++ if (n <= 5) ++ return 0; ++ ++ if (grub_strcmp (filename + n - 5, ".conf") != 0) ++ return 0; ++ ++ p = grub_xasprintf (GRUB_BLS_CONFIG_PATH "%s", filename); ++ ++ f = grub_file_open (p); ++ if (!f) ++ goto finish; ++ ++ sz = grub_file_size (f); ++ if (sz == GRUB_FILE_SIZE_UNKNOWN || sz > 1024*1024) ++ goto finish; ++ ++ for (;;) ++ { ++ char *buf; ++ ++ buf = grub_file_getline (f); ++ if (!buf) ++ break; ++ ++ if (grub_strncmp (buf, "title ", 6) == 0) ++ { ++ grub_free (title); ++ title = grub_strdup (buf + 6); ++ if (!title) ++ goto finish; ++ } ++ else if (grub_strncmp (buf, "options ", 8) == 0) ++ { ++ grub_free (options); ++ options = grub_strdup (buf + 8); ++ if (!options) ++ goto finish; ++ } ++ else if (grub_strncmp (buf, "linux ", 6) == 0) ++ { ++ grub_free (clinux); ++ clinux = grub_strdup (buf + 6); ++ if (!clinux) ++ goto finish; ++ } ++ else if (grub_strncmp (buf, "initrd ", 7) == 0) ++ { ++ grub_free (initrd); ++ initrd = grub_strdup (buf + 7); ++ if (!initrd) ++ goto finish; ++ } ++ ++ grub_free(buf); ++ } ++ ++ if (!linux) ++ { ++ grub_printf ("Skipping file %s with no 'linux' key.", p); ++ goto finish; ++ } ++ ++ args[0] = title ? title : filename; ++ ++ src = grub_xasprintf ("load_video\n" ++ "set gfx_payload=keep\n" ++ "insmod gzio\n" ++ GRUB_LINUX_CMD " %s%s%s%s\n" ++ "%s%s%s%s", ++ GRUB_BOOT_DEVICE, clinux, options ? " " : "", options ? options : "", ++ initrd ? GRUB_INITRD_CMD " " : "", initrd ? GRUB_BOOT_DEVICE : "", initrd ? initrd : "", initrd ? "\n" : ""); ++ ++ grub_normal_add_menu_entry (1, args, NULL, NULL, "bls", NULL, NULL, src, 0); ++ ++finish: ++ grub_free (p); ++ grub_free (title); ++ grub_free (options); ++ grub_free (clinux); ++ grub_free (initrd); ++ grub_free (src); ++ ++ if (f) ++ grub_file_close (f); ++ ++ return 0; ++} ++ ++static grub_err_t ++grub_cmd_bls_import (grub_extcmd_context_t ctxt __attribute__ ((unused)), ++ int argc __attribute__ ((unused)), ++ char **args __attribute__ ((unused))) ++{ ++ grub_fs_t fs; ++ grub_device_t dev; ++ static grub_err_t r; ++ const char *devid; ++ ++ devid = grub_env_get ("root"); ++ if (!devid) ++ return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"), "root"); ++ ++ dev = grub_device_open (devid); ++ if (!dev) ++ return grub_errno; ++ ++ fs = grub_fs_probe (dev); ++ if (!fs) ++ { ++ r = grub_errno; ++ goto finish; ++ } ++ ++ r = fs->dir (dev, GRUB_BLS_CONFIG_PATH, parse_entry, NULL); ++ ++finish: ++ if (dev) ++ grub_device_close (dev); ++ ++ return r; ++} ++ ++static grub_extcmd_t cmd; ++ ++GRUB_MOD_INIT(bls) ++{ ++ cmd = grub_register_extcmd ("bls_import", ++ grub_cmd_bls_import, ++ 0, ++ NULL, ++ N_("Import Boot Loader Specification snippets."), ++ NULL); ++} ++ ++GRUB_MOD_FINI(bls) ++{ ++ grub_unregister_extcmd (cmd); ++} +-- +1.9.3 + diff --git a/efi-net-fix.patch b/efi-net-fix.patch new file mode 100644 index 0000000..41872c0 --- /dev/null +++ b/efi-net-fix.patch @@ -0,0 +1,59 @@ +From 886d93184b894a29b0bef1f2467230a20c7a33ce Mon Sep 17 00:00:00 2001 +From: Mark Salter +Date: Tue, 8 Apr 2014 10:58:11 -0400 +Subject: [PATCH] reopen SNP protocol for exclusive use by grub + +While working with pxeboot of grub on an ARM platform, I noticed +very poor network performance while grub was loading a kernel +and initramfs. The performance during the loading of grub itself +seemed reasonable. Digging into the issue, I found that the UEFI +firmware was periodically polling for network packets while grub +was downloading files. This was causing timeouts and retries in +the grub network stack. + +The solution I found was to reopen the SNP protocol for exclusive +use. This forces UEFI to shutdown its use of SNP so that grub is +not competing for incoming packets. + +Signed-off-by: Mark Salter +--- + grub-core/net/drivers/efi/efinet.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c +index 2b344d6..a6e4c79 100644 +--- a/grub-core/net/drivers/efi/efinet.c ++++ b/grub-core/net/drivers/efi/efinet.c +@@ -223,6 +223,7 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, + { + struct grub_net_card *card; + grub_efi_device_path_t *dp; ++ grub_efi_simple_network_t *net; + + dp = grub_efi_get_device_path (hnd); + if (! dp) +@@ -250,6 +251,21 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, + &pxe_mode->dhcp_ack, + sizeof (pxe_mode->dhcp_ack), + 1, device, path); ++ net = grub_efi_open_protocol (card->efi_handle, &net_io_guid, ++ GRUB_EFI_OPEN_PROTOCOL_BY_EXCLUSIVE); ++ if (net) { ++ if (net->mode->state == GRUB_EFI_NETWORK_STOPPED ++ && efi_call_1 (net->start, net) != GRUB_EFI_SUCCESS) ++ continue; ++ ++ if (net->mode->state == GRUB_EFI_NETWORK_STOPPED) ++ continue; ++ ++ if (net->mode->state == GRUB_EFI_NETWORK_STARTED ++ && efi_call_3 (net->initialize, net, 0, 0) != GRUB_EFI_SUCCESS) ++ continue; ++ card->efi_net = net; ++ } + return; + } + } +-- +1.8.5.3 + diff --git a/grub.sysconfig b/grub.sysconfig index f59916d..0c2f181 100644 --- a/grub.sysconfig +++ b/grub.sysconfig @@ -4,7 +4,7 @@ # # To disable auto generation of /boot/grub/grub.conf on kernel package # install/upgrade, UPDATE_GRUB must be set to "no". -#UPDATE_GRUB=yes +#UPDATE_GRUB=no # Default entry to boot. Numeric value starting with 0. # Use special value 'saved' to stick with last booted entry. used with GRUB_SAVEDEFAULT @@ -13,15 +13,21 @@ GRUB_DEFAULT=0 # save_default_entry #GRUB_SAVEDEFAULT=true +# Boot the default entry this many seconds after the menu is displayed, unless a key +# is pressed. Set to 0 to boot immediately without displaying the menu, or to -1 to +# wait indefinitely. GRUB_TIMEOUT=15 +# Wait this many seconds for a key to be pressed before displaying the menu. +#GRUB_HIDDEN_TIMEOUT=15 + # Unless `GRUB_DISABLE_RECOVERY' is set to `true', two menu entries # will be generated for each Linux kernel: one default entry and one # entry for recovery mode. This option lists command-line arguments # to add only to the default menu entry, after those listed in # `GRUB_CMDLINE_LINUX'. # To disable IPv6 in kernel, append: ipv6.disable=1 -GRUB_CMDLINE_LINUX_DEFAULT="panic=120 quiet" +GRUB_CMDLINE_LINUX_DEFAULT="panic=300 quiet" # Command-line arguments to add to menu entries for the Linux kernel. GRUB_CMDLINE_LINUX="" diff --git a/grub2-xfs-Add-helper-for-inode-size.patch b/grub2-xfs-Add-helper-for-inode-size.patch new file mode 100644 index 0000000..47abde2 --- /dev/null +++ b/grub2-xfs-Add-helper-for-inode-size.patch @@ -0,0 +1,76 @@ +From 34231b28cbb6b2e10d7668c5b6d2432e8563bd1d Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Thu, 5 Jun 2014 20:56:21 +0200 +Subject: [PATCH 1/4] xfs: Add helper for inode size + +Signed-off-by: Jan Kara +--- + grub-core/fs/xfs.c | 17 +++++++++++------ + 1 file changed, 11 insertions(+), 6 deletions(-) + +diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c +index 16ffd3f1ebd9..a2fc942707c1 100644 +--- a/grub-core/fs/xfs.c ++++ b/grub-core/fs/xfs.c +@@ -255,6 +255,11 @@ grub_xfs_inode_offset (struct grub_xfs_data *data, + data->sblock.log2_inode); + } + ++static inline int ++grub_xfs_inode_size(struct grub_xfs_data *data) ++{ ++ return 1 << data->sblock.log2_inode; ++} + + static grub_err_t + grub_xfs_read_inode (struct grub_xfs_data *data, grub_uint64_t ino, +@@ -264,8 +269,8 @@ grub_xfs_read_inode (struct grub_xfs_data *data, grub_uint64_t ino, + int offset = grub_xfs_inode_offset (data, ino); + + /* Read the inode. */ +- if (grub_disk_read (data->disk, block, offset, +- 1 << data->sblock.log2_inode, inode)) ++ if (grub_disk_read (data->disk, block, offset, grub_xfs_inode_size(data), ++ inode)) + return grub_errno; + + if (grub_strncmp ((char *) inode->magic, "IN", 2)) +@@ -297,7 +302,7 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) + if (node->inode.fork_offset) + recoffset = (node->inode.fork_offset - 1) / 2; + else +- recoffset = ((1 << node->data->sblock.log2_inode) ++ recoffset = (grub_xfs_inode_size(node->data) + - ((char *) &node->inode.data.btree.keys + - (char *) &node->inode)) + / (2 * sizeof (grub_uint64_t)); +@@ -458,7 +463,7 @@ static int iterate_dir_call_hook (grub_uint64_t ino, const char *filename, + + fdiro = grub_malloc (sizeof (struct grub_fshelp_node) + - sizeof (struct grub_xfs_inode) +- + (1 << ctx->diro->data->sblock.log2_inode) + 1); ++ + grub_xfs_inode_size(ctx->diro->data) + 1); + if (!fdiro) + { + grub_print_error (); +@@ -684,7 +689,7 @@ grub_xfs_mount (grub_disk_t disk) + data = grub_realloc (data, + sizeof (struct grub_xfs_data) + - sizeof (struct grub_xfs_inode) +- + (1 << data->sblock.log2_inode) + 1); ++ + grub_xfs_inode_size(data) + 1); + + if (! data) + goto fail; +@@ -802,7 +807,7 @@ grub_xfs_open (struct grub_file *file, const char *name) + grub_memcpy (&data->diropen, fdiro, + sizeof (struct grub_fshelp_node) + - sizeof (struct grub_xfs_inode) +- + (1 << data->sblock.log2_inode)); ++ + grub_xfs_inode_size(data)); + grub_free (fdiro); + } + +-- +1.8.1.4 + diff --git a/grub2-xfs-Convert-inode-numbers-to-cpu-endianity-immediate.patch b/grub2-xfs-Convert-inode-numbers-to-cpu-endianity-immediate.patch new file mode 100644 index 0000000..c5b6b0f --- /dev/null +++ b/grub2-xfs-Convert-inode-numbers-to-cpu-endianity-immediate.patch @@ -0,0 +1,82 @@ +From 57ae4073cc28fa74014a62aca397a40ce1f73763 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Thu, 12 Jun 2014 11:01:11 +0200 +Subject: [PATCH 3/4] xfs: Convert inode numbers to cpu endianity immediately + after reading + +Currently XFS driver converted inode numbers to native endianity only +when using them to compute inode position. Although this works, it is +somewhat confusing. So convert inode numbers when reading them from disk +structures as every other field. + +Signed-off-by: Jan Kara +--- + grub-core/fs/xfs.c | 13 ++++++------- + 1 file changed, 6 insertions(+), 7 deletions(-) + +diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c +index ef3bc787e968..7e247a32df5c 100644 +--- a/grub-core/fs/xfs.c ++++ b/grub-core/fs/xfs.c +@@ -180,14 +180,14 @@ static inline grub_uint64_t + GRUB_XFS_INO_INOINAG (struct grub_xfs_data *data, + grub_uint64_t ino) + { +- return (grub_be_to_cpu64 (ino) & ((1LL << GRUB_XFS_INO_AGBITS (data)) - 1)); ++ return (ino & ((1LL << GRUB_XFS_INO_AGBITS (data)) - 1)); + } + + static inline grub_uint64_t + GRUB_XFS_INO_AG (struct grub_xfs_data *data, + grub_uint64_t ino) + { +- return (grub_be_to_cpu64 (ino) >> GRUB_XFS_INO_AGBITS (data)); ++ return (ino >> GRUB_XFS_INO_AGBITS (data)); + } + + static inline grub_disk_addr_t +@@ -511,13 +511,12 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, + if (smallino) + { + parent = grub_be_to_cpu32 (diro->inode.data.dir.dirhead.parent.i4); +- parent = grub_cpu_to_be64 (parent); + /* The header is a bit smaller than usual. */ + de = (struct grub_xfs_dir_entry *) ((char *) de - 4); + } + else + { +- parent = diro->inode.data.dir.dirhead.parent.i8; ++ parent = grub_be_to_cpu64(diro->inode.data.dir.dirhead.parent.i8); + } + + /* Synthesize the direntries for `.' and `..'. */ +@@ -550,7 +549,6 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, + | (((grub_uint64_t) inopos[5]) << 16) + | (((grub_uint64_t) inopos[6]) << 8) + | (((grub_uint64_t) inopos[7]) << 0); +- ino = grub_cpu_to_be64 (ino); + + c = de->name[de->len]; + de->name[de->len] = '\0'; +@@ -632,7 +630,8 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, + is not used by GRUB. So it can be overwritten. */ + filename[direntry->len] = '\0'; + +- if (iterate_dir_call_hook (direntry->inode, filename, &ctx)) ++ if (iterate_dir_call_hook (grub_be_to_cpu64(direntry->inode), ++ filename, &ctx)) + { + grub_free (dirblock); + return 1; +@@ -694,7 +693,7 @@ grub_xfs_mount (grub_disk_t disk) + goto fail; + + data->diropen.data = data; +- data->diropen.ino = data->sblock.rootino; ++ data->diropen.ino = grub_be_to_cpu64(data->sblock.rootino); + data->diropen.inode_read = 1; + data->bsize = grub_be_to_cpu32 (data->sblock.bsize); + data->agsize = grub_be_to_cpu32 (data->sblock.agsize); +-- +1.8.1.4 + diff --git a/grub2-xfs-Fix-termination-loop-for-directory-iteration.patch b/grub2-xfs-Fix-termination-loop-for-directory-iteration.patch new file mode 100644 index 0000000..a35fc93 --- /dev/null +++ b/grub2-xfs-Fix-termination-loop-for-directory-iteration.patch @@ -0,0 +1,32 @@ +From a7d584c005bde09bb86475a79d714215b3480821 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Wed, 11 Jun 2014 18:36:59 +0200 +Subject: [PATCH 2/4] xfs: Fix termination loop for directory iteration + +Directory iteration used wrong position (sizeof wrong structure) for +termination of iteration inside a directory block. Luckily the position +ended up being wrong by just 1 byte and directory entries are larger so +things worked out fine in practice. But fix the problem anyway. + +Signed-off-by: Jan Kara +--- + grub-core/fs/xfs.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c +index a2fc942707c1..ef3bc787e968 100644 +--- a/grub-core/fs/xfs.c ++++ b/grub-core/fs/xfs.c +@@ -608,8 +608,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, + - grub_be_to_cpu32 (tail->leaf_stale)); + + /* Iterate over all entries within this block. */ +- while (pos < (dirblk_size +- - (int) sizeof (struct grub_xfs_dir2_entry))) ++ while (pos < tail_start) + { + struct grub_xfs_dir2_entry *direntry; + grub_uint8_t *freetag; +-- +1.8.1.4 + diff --git a/grub2-xfs-V5-filesystem-format-support.patch b/grub2-xfs-V5-filesystem-format-support.patch new file mode 100644 index 0000000..56318d4 --- /dev/null +++ b/grub2-xfs-V5-filesystem-format-support.patch @@ -0,0 +1,478 @@ +From 2f725e644d8ccf001a4dccddc8abb2c9479352a7 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Wed, 11 Jun 2014 18:36:01 +0200 +Subject: [PATCH] xfs: V5 filesystem format support + +Signed-off-by: Jan Kara +--- + grub-core/fs/xfs.c | 245 +++++++++++++++++++++++++++++++++++++---------------- + 1 file changed, 173 insertions(+), 72 deletions(-) + +Index: grub-2.02~beta2/grub-core/fs/xfs.c +=================================================================== +--- grub-2.02~beta2.orig/grub-core/fs/xfs.c ++++ grub-2.02~beta2/grub-core/fs/xfs.c +@@ -34,6 +34,15 @@ GRUB_MOD_LICENSE ("GPLv3+"); + #define XFS_INODE_FORMAT_EXT 2 + #define XFS_INODE_FORMAT_BTREE 3 + ++/* Superblock version field flags */ ++#define XFS_SB_VERSION_NUMBITS 0x000f ++#define XFS_SB_VERSION_MOREBITSBIT 0x8000 ++ ++/* features2 field flags */ ++#define XFS_SB_VERSION2_FTYPE 0x00000200 /* inode type in dir */ ++ ++/* incompat feature flags */ ++#define XFS_SB_FEAT_INCOMPAT_FTYPE (1 << 0) /* filetype in dirent */ + + struct grub_xfs_sblock + { +@@ -45,7 +54,9 @@ struct grub_xfs_sblock + grub_uint64_t rootino; + grub_uint8_t unused3[20]; + grub_uint32_t agsize; +- grub_uint8_t unused4[20]; ++ grub_uint8_t unused4[12]; ++ grub_uint16_t version; ++ grub_uint8_t unused5[6]; + grub_uint8_t label[12]; + grub_uint8_t log2_bsize; + grub_uint8_t log2_sect; +@@ -54,12 +65,19 @@ struct grub_xfs_sblock + grub_uint8_t log2_agblk; + grub_uint8_t unused6[67]; + grub_uint8_t log2_dirblk; ++ grub_uint8_t unused7[7]; ++ grub_uint32_t features2; ++ grub_uint8_t unused8[4]; ++ grub_uint32_t sb_features_compat; ++ grub_uint32_t sb_features_ro_compat; ++ grub_uint32_t sb_features_incompat; ++ grub_uint32_t sb_features_log_incompat; + } GRUB_PACKED; + + struct grub_xfs_dir_header + { + grub_uint8_t count; +- grub_uint8_t smallino; ++ grub_uint8_t largeino; + union + { + grub_uint32_t i4; +@@ -67,14 +85,16 @@ struct grub_xfs_dir_header + } GRUB_PACKED parent; + } GRUB_PACKED; + ++/* Structure for directory entry inlined in the inode */ + struct grub_xfs_dir_entry + { + grub_uint8_t len; + grub_uint16_t offset; + char name[1]; +- /* Inode number follows, 32 bits. */ ++ /* Inode number follows, 32 / 64 bits. */ + } GRUB_PACKED; + ++/* Structure for directory entry in a block */ + struct grub_xfs_dir2_entry + { + grub_uint64_t inode; +@@ -90,7 +110,8 @@ struct grub_xfs_btree_node + grub_uint16_t numrecs; + grub_uint64_t left; + grub_uint64_t right; +- grub_uint64_t keys[1]; ++ /* In V5 here follow crc, uuid, etc. */ ++ /* Then follow keys and block pointers */ + } GRUB_PACKED; + + struct grub_xfs_btree_root +@@ -123,17 +144,6 @@ struct grub_xfs_inode + grub_uint16_t unused3; + grub_uint8_t fork_offset; + grub_uint8_t unused4[17]; +- union +- { +- char raw[156]; +- struct dir +- { +- struct grub_xfs_dir_header dirhead; +- struct grub_xfs_dir_entry direntry[1]; +- } dir; +- grub_xfs_extent extents[XFS_INODE_EXTENTS]; +- struct grub_xfs_btree_root btree; +- } GRUB_PACKED data; + } GRUB_PACKED; + + struct grub_xfs_dirblock_tail +@@ -157,6 +167,8 @@ struct grub_xfs_data + int pos; + int bsize; + grub_uint32_t agsize; ++ unsigned int hasftype:1; ++ unsigned int hascrc:1; + struct grub_fshelp_node diropen; + }; + +@@ -164,6 +176,24 @@ static grub_dl_t my_mod; + + + ++static int grub_xfs_sb_hascrc(struct grub_xfs_data *data) ++{ ++ return (grub_be_to_cpu16(data->sblock.version) & XFS_SB_VERSION_NUMBITS) == 5; ++} ++ ++static int grub_xfs_sb_hasftype(struct grub_xfs_data *data) ++{ ++ grub_uint32_t version = grub_be_to_cpu16(data->sblock.version); ++ ++ if ((version & XFS_SB_VERSION_NUMBITS) == 5 && ++ grub_be_to_cpu32(data->sblock.sb_features_incompat) & XFS_SB_FEAT_INCOMPAT_FTYPE) ++ return 1; ++ if (version & XFS_SB_VERSION_MOREBITSBIT && ++ grub_be_to_cpu32(data->sblock.features2) & XFS_SB_VERSION2_FTYPE) ++ return 1; ++ return 0; ++} ++ + /* Filetype information as used in inodes. */ + #define FILETYPE_INO_MASK 0170000 + #define FILETYPE_INO_REG 0100000 +@@ -219,18 +249,6 @@ GRUB_XFS_EXTENT_SIZE (grub_xfs_extent *e + return (grub_be_to_cpu32 (exts[ex][3]) & ((1 << 21) - 1)); + } + +-static inline int +-GRUB_XFS_ROUND_TO_DIRENT (int pos) +-{ +- return ((((pos) + 8 - 1) / 8) * 8); +-} +- +-static inline int +-GRUB_XFS_NEXT_DIRENT (int pos, int len) +-{ +- return (pos) + GRUB_XFS_ROUND_TO_DIRENT (8 + 1 + len + 2); +-} +- + + static inline grub_uint64_t + grub_xfs_inode_block (struct grub_xfs_data *data, +@@ -261,6 +279,92 @@ grub_xfs_inode_size(struct grub_xfs_data + return 1 << data->sblock.log2_inode; + } + ++static void * ++grub_xfs_inode_data(struct grub_xfs_inode *inode) ++{ ++ if (inode->version <= 2) ++ return ((char *)inode) + 100; ++ return ((char *)inode) + 176; ++} ++ ++static struct grub_xfs_dir_entry * ++grub_xfs_inline_de(struct grub_xfs_dir_header *head) ++{ ++ /* ++ * With small inode numbers the header is 4 bytes smaller because of ++ * smaller parent pointer ++ */ ++ return (void *)(((char *)head) + sizeof(struct grub_xfs_dir_header) - ++ (head->largeino ? 0 : sizeof(grub_uint32_t))); ++} ++ ++static grub_uint8_t * ++grub_xfs_inline_de_inopos(struct grub_xfs_data *data, ++ struct grub_xfs_dir_entry *de) ++{ ++ return ((grub_uint8_t *)(de + 1)) + de->len - 1 + ++ (data->hasftype ? 1 : 0); ++} ++ ++static struct grub_xfs_dir_entry * ++grub_xfs_inline_next_de(struct grub_xfs_data *data, ++ struct grub_xfs_dir_header *head, ++ struct grub_xfs_dir_entry *de) ++{ ++ char *p = (char *)de + sizeof(struct grub_xfs_dir_entry) - 1 + de->len; ++ ++ p += head->largeino ? sizeof(grub_uint64_t) : sizeof(grub_uint32_t); ++ if (data->hasftype) ++ p++; ++ ++ return (struct grub_xfs_dir_entry *)p; ++} ++ ++static struct grub_xfs_dirblock_tail * ++grub_xfs_dir_tail(struct grub_xfs_data *data, void *dirblock) ++{ ++ int dirblksize = 1 << (data->sblock.log2_bsize + data->sblock.log2_dirblk); ++ ++ return (struct grub_xfs_dirblock_tail *) ++ ((char *)dirblock + dirblksize - sizeof (struct grub_xfs_dirblock_tail)); ++} ++ ++static struct grub_xfs_dir2_entry * ++grub_xfs_first_de(struct grub_xfs_data *data, void *dirblock) ++{ ++ if (data->hascrc) ++ return (struct grub_xfs_dir2_entry *)((char *)dirblock + 64); ++ return (struct grub_xfs_dir2_entry *)((char *)dirblock + 16); ++} ++ ++static inline int ++grub_xfs_round_dirent_size (int len) ++{ ++ return (len + 7) & ~7; ++} ++ ++static struct grub_xfs_dir2_entry * ++grub_xfs_next_de(struct grub_xfs_data *data, struct grub_xfs_dir2_entry *de) ++{ ++ int size = sizeof (struct grub_xfs_dir2_entry) + de->len + 2 /* Tag */; ++ ++ if (data->hasftype) ++ size++; /* File type */ ++ return (struct grub_xfs_dir2_entry *) ++ (((char *)de) + grub_xfs_round_dirent_size (size)); ++} ++ ++static grub_uint64_t * ++grub_xfs_btree_keys(struct grub_xfs_data *data, ++ struct grub_xfs_btree_node *leaf) ++{ ++ char *p = (char *)(leaf + 1); ++ ++ if (data->hascrc) ++ p += 48; /* crc, uuid, ... */ ++ return (grub_uint64_t *)(void*)p; ++} ++ + static grub_err_t + grub_xfs_read_inode (struct grub_xfs_data *data, grub_uint64_t ino, + struct grub_xfs_inode *inode) +@@ -268,6 +372,9 @@ grub_xfs_read_inode (struct grub_xfs_dat + grub_uint64_t block = grub_xfs_inode_block (data, ino); + int offset = grub_xfs_inode_offset (data, ino); + ++ grub_dprintf("xfs", "Reading inode (%llu) - %llu, %d\n", ++ (unsigned long long) ino, ++ (unsigned long long) block, offset); + /* Read the inode. */ + if (grub_disk_read (data->disk, block, offset, grub_xfs_inode_size(data), + inode)) +@@ -290,6 +397,7 @@ grub_xfs_read_block (grub_fshelp_node_t + + if (node->inode.format == XFS_INODE_FORMAT_BTREE) + { ++ struct grub_xfs_btree_root *root; + const grub_uint64_t *keys; + int recoffset; + +@@ -297,15 +405,15 @@ grub_xfs_read_block (grub_fshelp_node_t + if (leaf == 0) + return 0; + +- nrec = grub_be_to_cpu16 (node->inode.data.btree.numrecs); +- keys = &node->inode.data.btree.keys[0]; ++ root = grub_xfs_inode_data(&node->inode); ++ nrec = grub_be_to_cpu16 (root->numrecs); ++ keys = &root->keys[0]; + if (node->inode.fork_offset) + recoffset = (node->inode.fork_offset - 1) / 2; + else + recoffset = (grub_xfs_inode_size(node->data) +- - ((char *) &node->inode.data.btree.keys +- - (char *) &node->inode)) +- / (2 * sizeof (grub_uint64_t)); ++ - ((char *) keys - (char *) &node->inode)) ++ / (2 * sizeof (grub_uint64_t)); + do + { + int i; +@@ -327,7 +435,10 @@ grub_xfs_read_block (grub_fshelp_node_t + 0, node->data->bsize, leaf)) + return 0; + +- if (grub_strncmp ((char *) leaf->magic, "BMAP", 4)) ++ if ((!node->data->hascrc && ++ grub_strncmp ((char *) leaf->magic, "BMAP", 4)) || ++ (node->data->hascrc && ++ grub_strncmp ((char *) leaf->magic, "BMA3", 4))) + { + grub_free (leaf); + grub_error (GRUB_ERR_BAD_FS, "not a correct XFS BMAP node"); +@@ -335,8 +446,8 @@ grub_xfs_read_block (grub_fshelp_node_t + } + + nrec = grub_be_to_cpu16 (leaf->numrecs); +- keys = &leaf->keys[0]; +- recoffset = ((node->data->bsize - ((char *) &leaf->keys ++ keys = grub_xfs_btree_keys(node->data, leaf); ++ recoffset = ((node->data->bsize - ((char *) keys + - (char *) leaf)) + / (2 * sizeof (grub_uint64_t))); + } +@@ -346,7 +457,7 @@ grub_xfs_read_block (grub_fshelp_node_t + else if (node->inode.format == XFS_INODE_FORMAT_EXT) + { + nrec = grub_be_to_cpu32 (node->inode.nextents); +- exts = &node->inode.data.extents[0]; ++ exts = grub_xfs_inode_data(&node->inode); + } + else + { +@@ -404,7 +515,7 @@ grub_xfs_read_symlink (grub_fshelp_node_ + switch (node->inode.format) + { + case XFS_INODE_FORMAT_INO: +- return grub_strndup (node->inode.data.raw, size); ++ return grub_strndup (grub_xfs_inode_data(&node->inode), size); + + case XFS_INODE_FORMAT_EXT: + { +@@ -501,23 +612,18 @@ grub_xfs_iterate_dir (grub_fshelp_node_t + { + case XFS_INODE_FORMAT_INO: + { +- struct grub_xfs_dir_entry *de = &diro->inode.data.dir.direntry[0]; +- int smallino = !diro->inode.data.dir.dirhead.smallino; ++ struct grub_xfs_dir_header *head = grub_xfs_inode_data(&diro->inode); ++ struct grub_xfs_dir_entry *de = grub_xfs_inline_de(head); ++ int smallino = !head->largeino; + int i; + grub_uint64_t parent; + + /* If small inode numbers are used to pack the direntry, the + parent inode number is small too. */ + if (smallino) +- { +- parent = grub_be_to_cpu32 (diro->inode.data.dir.dirhead.parent.i4); +- /* The header is a bit smaller than usual. */ +- de = (struct grub_xfs_dir_entry *) ((char *) de - 4); +- } ++ parent = grub_be_to_cpu32 (head->parent.i4); + else +- { +- parent = grub_be_to_cpu64(diro->inode.data.dir.dirhead.parent.i8); +- } ++ parent = grub_be_to_cpu64 (head->parent.i8); + + /* Synthesize the direntries for `.' and `..'. */ + if (iterate_dir_call_hook (diro->ino, ".", &ctx)) +@@ -526,12 +632,10 @@ grub_xfs_iterate_dir (grub_fshelp_node_t + if (iterate_dir_call_hook (parent, "..", &ctx)) + return 1; + +- for (i = 0; i < diro->inode.data.dir.dirhead.count; i++) ++ for (i = 0; i < head->count; i++) + { + grub_uint64_t ino; +- grub_uint8_t *inopos = (((grub_uint8_t *) de) +- + sizeof (struct grub_xfs_dir_entry) +- + de->len - 1); ++ grub_uint8_t *inopos = grub_xfs_inline_de_inopos(dir->data, de); + grub_uint8_t c; + + /* inopos might be unaligned. */ +@@ -556,10 +660,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t + return 1; + de->name[de->len] = c; + +- de = ((struct grub_xfs_dir_entry *) +- (((char *) de)+ sizeof (struct grub_xfs_dir_entry) + de->len +- + ((smallino ? sizeof (grub_uint32_t) +- : sizeof (grub_uint64_t))) - 1)); ++ de = grub_xfs_inline_next_de(dir->data, head, de); + } + break; + } +@@ -586,15 +687,11 @@ grub_xfs_iterate_dir (grub_fshelp_node_t + >> dirblk_log2); + blk++) + { +- /* The header is skipped, the first direntry is stored +- from byte 16. */ +- int pos = 16; ++ struct grub_xfs_dir2_entry *direntry = ++ grub_xfs_first_de(dir->data, dirblock); + int entries; +- int tail_start = (dirblk_size +- - sizeof (struct grub_xfs_dirblock_tail)); +- +- struct grub_xfs_dirblock_tail *tail; +- tail = (struct grub_xfs_dirblock_tail *) &dirblock[tail_start]; ++ struct grub_xfs_dirblock_tail *tail = ++ grub_xfs_dir_tail(dir->data, dirblock); + + numread = grub_xfs_read_file (dir, 0, 0, + blk << dirblk_log2, +@@ -606,13 +703,11 @@ grub_xfs_iterate_dir (grub_fshelp_node_t + - grub_be_to_cpu32 (tail->leaf_stale)); + + /* Iterate over all entries within this block. */ +- while (pos < tail_start) ++ while ((char *)direntry < (char *)tail) + { +- struct grub_xfs_dir2_entry *direntry; + grub_uint8_t *freetag; + char *filename; + +- direntry = (struct grub_xfs_dir2_entry *) &dirblock[pos]; + freetag = (grub_uint8_t *) direntry; + + if (grub_get_unaligned16 (freetag) == 0XFFFF) +@@ -620,14 +715,16 @@ grub_xfs_iterate_dir (grub_fshelp_node_t + grub_uint8_t *skip = (freetag + sizeof (grub_uint16_t)); + + /* This entry is not used, go to the next one. */ +- pos += grub_be_to_cpu16 (grub_get_unaligned16 (skip)); ++ direntry = (struct grub_xfs_dir2_entry *) ++ (((char *)direntry) + ++ grub_be_to_cpu16 (grub_get_unaligned16 (skip))); + + continue; + } + +- filename = &dirblock[pos + sizeof (*direntry)]; +- /* The byte after the filename is for the tag, which +- is not used by GRUB. So it can be overwritten. */ ++ filename = (char *)(direntry + 1); ++ /* The byte after the filename is for the filetype, padding, or ++ tag, which is not used by GRUB. So it can be overwritten. */ + filename[direntry->len] = '\0'; + + if (iterate_dir_call_hook (grub_be_to_cpu64(direntry->inode), +@@ -644,8 +741,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t + break; + + /* Select the next directory entry. */ +- pos = GRUB_XFS_NEXT_DIRENT (pos, direntry->len); +- pos = GRUB_XFS_ROUND_TO_DIRENT (pos); ++ direntry = grub_xfs_next_de(dir->data, direntry); + } + } + grub_free (dirblock); +@@ -670,6 +766,7 @@ grub_xfs_mount (grub_disk_t disk) + if (!data) + return 0; + ++ grub_dprintf("xfs", "Reading sb\n"); + /* Read the superblock. */ + if (grub_disk_read (disk, 0, 0, + sizeof (struct grub_xfs_sblock), &data->sblock)) +@@ -697,9 +794,13 @@ grub_xfs_mount (grub_disk_t disk) + data->diropen.inode_read = 1; + data->bsize = grub_be_to_cpu32 (data->sblock.bsize); + data->agsize = grub_be_to_cpu32 (data->sblock.agsize); ++ data->hasftype = grub_xfs_sb_hasftype(data); ++ data->hascrc = grub_xfs_sb_hascrc(data); + + data->disk = disk; + data->pos = 0; ++ grub_dprintf("xfs", "Reading root ino %llu\n", ++ (unsigned long long) grub_cpu_to_be64(data->sblock.rootino)); + + grub_xfs_read_inode (data, data->diropen.ino, &data->diropen.inode); + diff --git a/grub2.spec b/grub2.spec index dc359e8..b1cb292 100644 --- a/grub2.spec +++ b/grub2.spec @@ -30,6 +30,7 @@ %define platforms %{?with_efi:efi} %{?with_pc:pc} %endif +%define rel 6 Summary: GRand Unified Bootloader Summary(de.UTF-8): GRUB2 - ein Bootloader für x86 Summary(hu.UTF-8): GRUB2 - rendszerbetöltő x86 gépekhez @@ -38,14 +39,14 @@ Summary(pt_BR.UTF-8): Gerenciador de inicialização GRUB2 %define beta beta2 Name: grub2 Version: 2.02 -Release: 0.%{beta}.5 +Release: 0.%{beta}.%{rel} License: GPL v2 Group: Base # 1. Download and unpack latest official beta snapshot from http://git.savannah.gnu.org/cgit/grub.git # 2. Run ./autogen.sh and ./linguas.sh # 3. Recompress and upload to DF Source0: grub-%{version}-%{beta}.tar.xz -# Source0-md5: f262e61eba2e76a6f60b39a810814284 +# Source0-md5: f262e61eba2e76a6f60b39a810814284 Source1: update-grub Source2: update-grub.8 Source3: grub.sysconfig @@ -62,6 +63,12 @@ Patch9: just-say-linux.patch Patch10: ignore-kernel-symlinks.patch Patch11: choose-preferred-initrd.patch Patch12: %{name}-cfg.patch +Patch13: efi-net-fix.patch +Patch14: grub2-xfs-Add-helper-for-inode-size.patch +Patch15: grub2-xfs-Convert-inode-numbers-to-cpu-endianity-immediate.patch +Patch16: grub2-xfs-Fix-termination-loop-for-directory-iteration.patch +Patch17: grub2-xfs-V5-filesystem-format-support.patch +Patch18: blscfg.patch URL: http://www.gnu.org/software/grub/ BuildRequires: autoconf >= 2.53 BuildRequires: automake >= 1:1.11.1-1 @@ -71,7 +78,8 @@ BuildRequires: flex >= 2.5.35 BuildRequires: fonts-TTF-DejaVu BuildRequires: freetype-devel >= 2 BuildRequires: gawk -BuildRequires: gettext-devel +BuildRequires: gcc >= 5:3.4 +BuildRequires: gettext-tools BuildRequires: glibc-localedb-all BuildRequires: glibc-static BuildRequires: help2man @@ -89,12 +97,8 @@ BuildRequires: xz BuildRequires: xz-devel %ifarch %{x8664} BuildRequires: /usr/lib/libc.so -%if "%{pld_release}" == "ac" -BuildRequires: libgcc32 -%else BuildRequires: gcc-multilib %endif -%endif Requires: %{name}-platform = %{version}-%{release} Requires: issue Requires: which @@ -271,7 +275,7 @@ starfield theme for GRUB. Motyw starfield dla GRUB-a. %prep -%setup -q -n grub-%{version}-%{beta} +%setup -q -n grub-%{version}~%{beta} %patch1 -p1 %patch2 -p1 %patch3 -p1 @@ -284,6 +288,12 @@ Motyw starfield dla GRUB-a. %patch10 -p1 %patch11 -p1 %patch12 -p0 +%patch13 -p1 +%patch14 -p1 +%patch15 -p1 +%patch16 -p1 +%patch17 -p1 +%patch18 -p1 # we don't have C.utf-8 and need an UTF-8 locale for build sed -i -e 's/LC_ALL=C.UTF-8/LC_ALL=en_US.utf-8/g' po/Makefile* po/Rules* @@ -293,13 +303,13 @@ sed -i -e 's/LC_ALL=C.UTF-8/LC_ALL=en_US.utf-8/g' po/Makefile* po/Rules* # https://savannah.gnu.org/bugs/?34539 # http://sourceware.org/bugzilla/show_bug.cgi?id=14196 install -d our-ld -ln -s /usr/bin/ld.bfd our-ld/ld +ln -f -s /usr/bin/ld.bfd our-ld/ld export PATH=$(pwd)/our-ld:$PATH ## not only the typicall autotools stuff #./autogen.sh -%{__gettextize} +#{__gettextize} %{__aclocal} -I m4 %{__autoconf} %{__autoheader} @@ -315,7 +325,7 @@ for platform in %{platforms} ; do platform_opts="" fi - ln -s ../configure . + ln -f -s ../configure . # mawk stalls at ./genmoddep.awk, so force gawk AWK=gawk \ %configure \ -- 2.37.3