From a1007c6af296172c788f3346ff3ad30b9020f723 Mon Sep 17 00:00:00 2001 From: Toomas Soome Date: Thu, 16 Apr 2015 08:22:08 +0300 Subject: [PATCH 001/106] zfs: com.delphix:hole_birth feature support In the past birth was always zero for holes. This feature started to make use of birth for holes as well, so change code to test for valid DVA address instead. --- grub-core/fs/zfs/zfs.c | 6 ++++-- include/grub/zfs/spa.h | 4 +++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index 0cbb84bb3..71c155df2 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -280,7 +280,9 @@ grub_crypto_cipher_handle_t (*grub_zfs_load_key) (const struct grub_zfs_key *key */ #define MAX_SUPPORTED_FEATURE_STRLEN 50 static const char *spa_feature_names[] = { - "org.illumos:lz4_compress",NULL + "org.illumos:lz4_compress", + "com.delphix:hole_birth", + NULL }; static int @@ -1751,7 +1753,7 @@ zio_read_gang (blkptr_t * bp, grub_zfs_endian_t endian, dva_t * dva, void *buf, for (i = 0; i < SPA_GBH_NBLKPTRS; i++) { - if (zio_gb->zg_blkptr[i].blk_birth == 0) + if (BP_IS_HOLE(&zio_gb->zg_blkptr[i])) continue; err = zio_read_data (&zio_gb->zg_blkptr[i], endian, buf, data); diff --git a/include/grub/zfs/spa.h b/include/grub/zfs/spa.h index 7edb8ab7d..df43b6b32 100644 --- a/include/grub/zfs/spa.h +++ b/include/grub/zfs/spa.h @@ -279,7 +279,9 @@ typedef struct blkptr { #define BP_IDENTITY(bp) (&(bp)->blk_dva[0]) #define BP_IS_GANG(bp) DVA_GET_GANG(BP_IDENTITY(bp)) -#define BP_IS_HOLE(bp) ((bp)->blk_birth == 0) +#define DVA_IS_EMPTY(dva) ((dva)->dva_word[0] == 0ULL && \ + (dva)->dva_word[1] == 0ULL) +#define BP_IS_HOLE(bp) DVA_IS_EMPTY(BP_IDENTITY(bp)) /* BP_IS_RAIDZ(bp) assumes no block compression */ #define BP_IS_RAIDZ(bp) (DVA_GET_ASIZE(&(bp)->blk_dva[0]) > \ From 4a7ea4003bd9f39e9bf2ebadbe4ab38f8874be66 Mon Sep 17 00:00:00 2001 From: Toomas Soome Date: Thu, 16 Apr 2015 08:23:22 +0300 Subject: [PATCH 002/106] zfs: com.delphix:embedded_data feature support --- grub-core/fs/zfs/zfs.c | 84 +++++++++++++++++++++++++++++++++++------- include/grub/zfs/spa.h | 27 ++++++++++++-- 2 files changed, 93 insertions(+), 18 deletions(-) diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index 71c155df2..03d587d8c 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -282,6 +282,7 @@ grub_crypto_cipher_handle_t (*grub_zfs_load_key) (const struct grub_zfs_key *key static const char *spa_feature_names[] = { "org.illumos:lz4_compress", "com.delphix:hole_birth", + "com.delphix:embedded_data", NULL }; @@ -1802,6 +1803,39 @@ zio_read_data (blkptr_t * bp, grub_zfs_endian_t endian, void *buf, return err; } +/* + * buf must be at least BPE_GET_PSIZE(bp) bytes long (which will never be + * more than BPE_PAYLOAD_SIZE bytes). + */ +static grub_err_t +decode_embedded_bp_compressed(const blkptr_t *bp, void *buf) +{ + grub_size_t psize, i; + grub_uint8_t *buf8 = buf; + grub_uint64_t w = 0; + const grub_uint64_t *bp64 = (const grub_uint64_t *)bp; + + psize = BPE_GET_PSIZE(bp); + + /* + * Decode the words of the block pointer into the byte array. + * Low bits of first word are the first byte (little endian). + */ + for (i = 0; i < psize; i++) + { + if (i % sizeof (w) == 0) + { + /* beginning of a word */ + w = *bp64; + bp64++; + if (!BPE_IS_PAYLOADWORD(bp, bp64)) + bp64++; + } + buf8[i] = BF64_GET(w, (i % sizeof (w)) * 8, 8); + } + return GRUB_ERR_NONE; +} + /* * Read in a block of data, verify its checksum, decompress if needed, * and put the uncompressed data in buf. @@ -1820,12 +1854,26 @@ zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf, *buf = NULL; checksum = (grub_zfs_to_cpu64((bp)->blk_prop, endian) >> 40) & 0xff; - comp = (grub_zfs_to_cpu64((bp)->blk_prop, endian)>>32) & 0xff; + comp = (grub_zfs_to_cpu64((bp)->blk_prop, endian)>>32) & 0x7f; encrypted = ((grub_zfs_to_cpu64((bp)->blk_prop, endian) >> 60) & 3); - lsize = (BP_IS_HOLE(bp) ? 0 : - (((grub_zfs_to_cpu64 ((bp)->blk_prop, endian) & 0xffff) + 1) - << SPA_MINBLOCKSHIFT)); - psize = get_psize (bp, endian); + if (BP_IS_EMBEDDED(bp)) + { + if (BPE_GET_ETYPE(bp) != BP_EMBEDDED_TYPE_DATA) + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "unsupported embedded BP (type=%u)\n", + BPE_GET_ETYPE(bp)); + lsize = BPE_GET_LSIZE(bp); + psize = BF64_GET_SB(grub_zfs_to_cpu64 ((bp)->blk_prop, endian), 25, 7, 0, 1); + } + else + { + lsize = (BP_IS_HOLE(bp) ? 0 : + (((grub_zfs_to_cpu64 ((bp)->blk_prop, endian) & 0xffff) + 1) + << SPA_MINBLOCKSHIFT)); + psize = get_psize (bp, endian); + } + grub_dprintf("zfs", "zio_read: E %d: size %" PRIdGRUB_SSIZE "/%" + PRIdGRUB_SSIZE "\n", (int)BP_IS_EMBEDDED(bp), lsize, psize); if (size) *size = lsize; @@ -1849,23 +1897,31 @@ zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf, compbuf = *buf = grub_malloc (lsize); grub_dprintf ("zfs", "endian = %d\n", endian); - err = zio_read_data (bp, endian, compbuf, data); + if (BP_IS_EMBEDDED(bp)) + err = decode_embedded_bp_compressed(bp, compbuf); + else + { + err = zio_read_data (bp, endian, compbuf, data); + grub_memset (compbuf, 0, ALIGN_UP (psize, 16) - psize); + } if (err) { grub_free (compbuf); *buf = NULL; return err; } - grub_memset (compbuf, 0, ALIGN_UP (psize, 16) - psize); - err = zio_checksum_verify (zc, checksum, endian, - compbuf, psize); - if (err) + if (!BP_IS_EMBEDDED(bp)) { - grub_dprintf ("zfs", "incorrect checksum\n"); - grub_free (compbuf); - *buf = NULL; - return err; + err = zio_checksum_verify (zc, checksum, endian, + compbuf, psize); + if (err) + { + grub_dprintf ("zfs", "incorrect checksum\n"); + grub_free (compbuf); + *buf = NULL; + return err; + } } if (encrypted) diff --git a/include/grub/zfs/spa.h b/include/grub/zfs/spa.h index df43b6b32..8dd1fa8e3 100644 --- a/include/grub/zfs/spa.h +++ b/include/grub/zfs/spa.h @@ -126,7 +126,7 @@ typedef struct zio_cksum { * +-------+-------+-------+-------+-------+-------+-------+-------+ * 5 |G| offset3 | * +-------+-------+-------+-------+-------+-------+-------+-------+ - * 6 |BDX|lvl| type | cksum | comp | PSIZE | LSIZE | + * 6 |BDX|lvl| type | cksum |E| comp| PSIZE | LSIZE | * +-------+-------+-------+-------+-------+-------+-------+-------+ * 7 | padding | * +-------+-------+-------+-------+-------+-------+-------+-------+ @@ -160,7 +160,8 @@ typedef struct zio_cksum { * G gang block indicator * B byteorder (endianness) * D dedup - * X unused + * X encryption + * E blkptr_t contains embedded data * lvl level of indirection * type DMU object type * phys birth txg of block allocation; zero if same as logical birth txg @@ -203,8 +204,8 @@ typedef struct blkptr { #define BP_SET_LSIZE(bp, x) \ BF64_SET_SB((bp)->blk_prop, 0, 16, SPA_MINBLOCKSHIFT, 1, x) -#define BP_GET_COMPRESS(bp) BF64_GET((bp)->blk_prop, 32, 8) -#define BP_SET_COMPRESS(bp, x) BF64_SET((bp)->blk_prop, 32, 8, x) +#define BP_GET_COMPRESS(bp) BF64_GET((bp)->blk_prop, 32, 7) +#define BP_SET_COMPRESS(bp, x) BF64_SET((bp)->blk_prop, 32, 7, x) #define BP_GET_CHECKSUM(bp) BF64_GET((bp)->blk_prop, 40, 8) #define BP_SET_CHECKSUM(bp, x) BF64_SET((bp)->blk_prop, 40, 8, x) @@ -215,6 +216,8 @@ typedef struct blkptr { #define BP_GET_LEVEL(bp) BF64_GET((bp)->blk_prop, 56, 5) #define BP_SET_LEVEL(bp, x) BF64_SET((bp)->blk_prop, 56, 5, x) +#define BP_IS_EMBEDDED(bp) BF64_GET((bp)->blk_prop, 39, 1) + #define BP_GET_PROP_BIT_61(bp) BF64_GET((bp)->blk_prop, 61, 1) #define BP_SET_PROP_BIT_61(bp, x) BF64_SET((bp)->blk_prop, 61, 1, x) @@ -277,6 +280,22 @@ typedef struct blkptr { (zcp)->zc_word[3] = w3; \ } +#define BPE_GET_ETYPE(bp) BP_GET_CHECKSUM(bp) +#define BPE_GET_LSIZE(bp) \ + BF64_GET_SB((bp)->blk_prop, 0, 25, 0, 1) +#define BPE_GET_PSIZE(bp) \ + BF64_GET_SB((bp)->blk_prop, 25, 7, 0, 1) + +typedef enum bp_embedded_type { + BP_EMBEDDED_TYPE_DATA, + NUM_BP_EMBEDDED_TYPES +} bp_embedded_type_t; + +#define BPE_NUM_WORDS 14 +#define BPE_PAYLOAD_SIZE (BPE_NUM_WORDS * sizeof(grub_uint64_t)) +#define BPE_IS_PAYLOADWORD(bp, wp) \ + ((wp) != &(bp)->blk_prop && (wp) != &(bp)->blk_birth) + #define BP_IDENTITY(bp) (&(bp)->blk_dva[0]) #define BP_IS_GANG(bp) DVA_GET_GANG(BP_IDENTITY(bp)) #define DVA_IS_EMPTY(dva) ((dva)->dva_word[0] == 0ULL && \ From 6210b8e8f7b4640711dd449ca8301d06fee62334 Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Sun, 3 May 2015 18:55:13 +0300 Subject: [PATCH 003/106] zfs: add missing NULL check and fix incorrect buffer overwrite grub_memset should zero out padding after data end. It is not clear why it is needed at all - ZFS block is at least 512 bytes and power of two, so it is always multiple of 16 bytes. This grub_memset apparently never did anything. --- grub-core/fs/zfs/zfs.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index 03d587d8c..08ed453a6 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -1887,14 +1887,12 @@ zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf, "compression algorithm %s not supported\n", decomp_table[comp].name); if (comp != ZIO_COMPRESS_OFF) - { - /* It's not really necessary to align to 16, just for safety. */ - compbuf = grub_malloc (ALIGN_UP (psize, 16)); - if (! compbuf) - return grub_errno; - } + /* It's not really necessary to align to 16, just for safety. */ + compbuf = grub_malloc (ALIGN_UP (psize, 16)); else compbuf = *buf = grub_malloc (lsize); + if (! compbuf) + return grub_errno; grub_dprintf ("zfs", "endian = %d\n", endian); if (BP_IS_EMBEDDED(bp)) @@ -1902,7 +1900,9 @@ zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf, else { err = zio_read_data (bp, endian, compbuf, data); - grub_memset (compbuf, 0, ALIGN_UP (psize, 16) - psize); + /* FIXME is it really necessary? */ + if (comp != ZIO_COMPRESS_OFF) + grub_memset (compbuf + psize, 0, ALIGN_UP (psize, 16) - psize); } if (err) { From 8d3c4544ffdd0289a4b0bdeb0cdc6355f801a4b3 Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Mon, 4 May 2015 08:08:57 +0300 Subject: [PATCH 004/106] efinet: memory leak on module removal --- grub-core/net/drivers/efi/efinet.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c index f171f20bf..eb1e682fa 100644 --- a/grub-core/net/drivers/efi/efinet.c +++ b/grub-core/net/drivers/efi/efinet.c @@ -278,6 +278,12 @@ GRUB_MOD_FINI(efinet) FOR_NET_CARDS_SAFE (card, next) if (card->driver == &efidriver) - grub_net_card_unregister (card); + { + grub_net_card_unregister (card); + grub_free (card->txbuf); + grub_free (card->rcvbuf); + grub_free (card->name); + grub_free (card); + } } From 47b2bee3ef0ea60fc3f5bfc37f3784e559385297 Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Mon, 4 May 2015 08:39:29 +0300 Subject: [PATCH 005/106] efinet: cannot free const char * pointer --- grub-core/net/drivers/efi/efinet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c index eb1e682fa..a879decdb 100644 --- a/grub-core/net/drivers/efi/efinet.c +++ b/grub-core/net/drivers/efi/efinet.c @@ -282,7 +282,7 @@ GRUB_MOD_FINI(efinet) grub_net_card_unregister (card); grub_free (card->txbuf); grub_free (card->rcvbuf); - grub_free (card->name); + grub_free ((char *)card->name); grub_free (card); } } From cc699535e57e0d0f099090e64a63037c7834f104 Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Mon, 4 May 2015 09:13:53 +0300 Subject: [PATCH 006/106] Revert "efinet: memory leak on module removal" This reverts commits 47b2bee3ef0ea60fc3f5bfc37f3784e559385297 and 8d3c4544ffdd0289a4b0bdeb0cdc6355f801a4b3. It is not safe to free allocated cards, dangling pointers main remain. Such cleanup requires more changes in net core. --- grub-core/net/drivers/efi/efinet.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c index a879decdb..f171f20bf 100644 --- a/grub-core/net/drivers/efi/efinet.c +++ b/grub-core/net/drivers/efi/efinet.c @@ -278,12 +278,6 @@ GRUB_MOD_FINI(efinet) FOR_NET_CARDS_SAFE (card, next) if (card->driver == &efidriver) - { - grub_net_card_unregister (card); - grub_free (card->txbuf); - grub_free (card->rcvbuf); - grub_free ((char *)card->name); - grub_free (card); - } + grub_net_card_unregister (card); } From f8451af8251a3866cb8b7307b9917dd5d34fbd0a Mon Sep 17 00:00:00 2001 From: Fu Wei Date: Thu, 7 May 2015 15:11:04 +0200 Subject: [PATCH 007/106] arm64: Export useful functions from linux.c Signed-off-by: Fu Wei --- gentpl.py | 2 +- grub-core/loader/arm64/linux.c | 59 +++++++++++++++++----------------- grub-core/loader/i386/linux.c | 11 +++---- grub-core/loader/linux.c | 3 +- include/grub/arm64/linux.h | 11 +++++++ 5 files changed, 49 insertions(+), 37 deletions(-) diff --git a/gentpl.py b/gentpl.py index f177883f8..0fd5ba427 100644 --- a/gentpl.py +++ b/gentpl.py @@ -759,7 +759,7 @@ def image(defn, platform): if test x$(TARGET_APPLE_LINKER) = x1; then \ $(MACHO2IMG) $< $@; \ else \ - $(TARGET_OBJCOPY) $(""" + cname(defn) + """_OBJCOPYFLAGS) --strip-unneeded -R .note -R .comment -R .note.gnu.build-id -R .MIPS.abiflags -R .reginfo -R .rel.dyn -R .note.gnu.gold-version $< $@; \ + $(TARGET_OBJCOPY) $(""" + cname(defn) + """_OBJCOPYFLAGS) --strip-unneeded -R .note -R .comment -R .note.gnu.build-id -R .MIPS.abiflags -R .reginfo -R .rel.dyn -R .note.gnu.gold-version -R .hash -R .dynsym -R .dynstr -R .rel.text $< $@; \ fi """) diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c index 564a75a80..987f5b9ee 100644 --- a/grub-core/loader/arm64/linux.c +++ b/grub-core/loader/arm64/linux.c @@ -33,12 +33,6 @@ GRUB_MOD_LICENSE ("GPLv3+"); -#define GRUB_EFI_PAGE_SHIFT 12 -#define BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> GRUB_EFI_PAGE_SHIFT) -#define GRUB_EFI_PE_MAGIC 0x5A4D - -static grub_efi_guid_t fdt_guid = GRUB_EFI_DEVICE_TREE_GUID; - static grub_dl_t my_mod; static int loaded; @@ -58,6 +52,7 @@ static void * get_firmware_fdt (void) { grub_efi_configuration_table_t *tables; + grub_efi_guid_t fdt_guid = GRUB_EFI_DEVICE_TREE_GUID; void *firmware_fdt = NULL; unsigned int i; @@ -75,8 +70,8 @@ get_firmware_fdt (void) return firmware_fdt; } -static void -get_fdt (void) +void * +grub_linux_get_fdt (void) { void *raw_fdt; grub_size_t size; @@ -99,7 +94,7 @@ get_fdt (void) grub_dprintf ("linux", "allocating %ld bytes for fdt\n", size); fdt = grub_efi_allocate_pages (0, BYTES_TO_PAGES (size)); if (!fdt) - return; + return NULL; if (raw_fdt) { @@ -110,10 +105,11 @@ get_fdt (void) { grub_fdt_create_empty_tree (fdt, size); } + return fdt; } -static grub_err_t -check_kernel (struct grub_arm64_linux_kernel_header *lh) +grub_err_t +grub_arm64_uefi_check_image (struct grub_arm64_linux_kernel_header * lh) { if (lh->magic != GRUB_ARM64_LINUX_MAGIC) return grub_error(GRUB_ERR_BAD_OS, "invalid magic number"); @@ -131,14 +127,14 @@ check_kernel (struct grub_arm64_linux_kernel_header *lh) } static grub_err_t -finalize_params (void) +finalize_params_linux (void) { grub_efi_boot_services_t *b; + grub_efi_guid_t fdt_guid = GRUB_EFI_DEVICE_TREE_GUID; grub_efi_status_t status; int node, retval; - get_fdt (); - if (!fdt) + if (!grub_linux_get_fdt ()) goto failure; node = grub_fdt_find_subnode (fdt, 0, "chosen"); @@ -240,21 +236,16 @@ out: return grub_errno; } -static grub_err_t -grub_linux_boot (void) +grub_err_t +grub_arm64_uefi_boot_image (grub_addr_t addr, grub_size_t size, char *args) { grub_efi_memory_mapped_device_path_t *mempath; grub_efi_handle_t image_handle; grub_efi_boot_services_t *b; grub_efi_status_t status; - grub_err_t retval; grub_efi_loaded_image_t *loaded_image; int len; - retval = finalize_params(); - if (retval != GRUB_ERR_NONE) - return retval; - mempath = grub_malloc (2 * sizeof (grub_efi_memory_mapped_device_path_t)); if (!mempath) return grub_errno; @@ -263,8 +254,8 @@ grub_linux_boot (void) mempath[0].header.subtype = GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE; mempath[0].header.length = grub_cpu_to_le16_compile_time (sizeof (*mempath)); mempath[0].memory_type = GRUB_EFI_LOADER_DATA; - mempath[0].start_address = (grub_addr_t) kernel_addr; - mempath[0].end_address = (grub_addr_t) kernel_addr + kernel_size; + mempath[0].start_address = addr; + mempath[0].end_address = addr + size; mempath[1].header.type = GRUB_EFI_END_DEVICE_PATH_TYPE; mempath[1].header.subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; @@ -273,16 +264,16 @@ grub_linux_boot (void) b = grub_efi_system_table->boot_services; status = b->load_image (0, grub_efi_image_handle, (grub_efi_device_path_t *) mempath, - kernel_addr, kernel_size, &image_handle); + (void *) addr, size, &image_handle); if (status != GRUB_EFI_SUCCESS) return grub_error (GRUB_ERR_BAD_OS, "cannot load image"); - grub_dprintf ("linux", "linux command line: '%s'\n", linux_args); + grub_dprintf ("linux", "linux command line: '%s'\n", args); /* Convert command line to UCS-2 */ loaded_image = grub_efi_get_loaded_image (image_handle); loaded_image->load_options_size = len = - (grub_strlen (linux_args) + 1) * sizeof (grub_efi_char16_t); + (grub_strlen (args) + 1) * sizeof (grub_efi_char16_t); loaded_image->load_options = grub_efi_allocate_pages (0, BYTES_TO_PAGES (loaded_image->load_options_size)); @@ -291,9 +282,9 @@ grub_linux_boot (void) loaded_image->load_options_size = 2 * grub_utf8_to_utf16 (loaded_image->load_options, len, - (grub_uint8_t *) linux_args, len, NULL); + (grub_uint8_t *) args, len, NULL); - grub_dprintf("linux", "starting image %p\n", image_handle); + grub_dprintf ("linux", "starting image %p\n", image_handle); status = b->start_image (image_handle, 0, NULL); /* When successful, not reached */ @@ -304,6 +295,16 @@ grub_linux_boot (void) return grub_errno; } +static grub_err_t +grub_linux_boot (void) +{ + if (finalize_params_linux () != GRUB_ERR_NONE) + return grub_errno; + + return (grub_arm64_uefi_boot_image((grub_addr_t)kernel_addr, + kernel_size, linux_args)); +} + static grub_err_t grub_linux_unload (void) { @@ -400,7 +401,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), if (grub_file_read (file, &lh, sizeof (lh)) < (long) sizeof (lh)) return grub_errno; - if (check_kernel (&lh) != GRUB_ERR_NONE) + if (grub_arm64_uefi_check_image (&lh) != GRUB_ERR_NONE) goto fail; grub_loader_unset(); diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c index 291f7289f..fddcc461d 100644 --- a/grub-core/loader/i386/linux.c +++ b/grub-core/loader/i386/linux.c @@ -69,7 +69,6 @@ static grub_addr_t prot_mode_target; static void *initrd_mem; static grub_addr_t initrd_mem_target; static grub_size_t prot_init_space; -static grub_uint32_t initrd_pages; static struct grub_relocator *relocator = NULL; static void *efi_mmap_buf; static grub_size_t maximal_cmdline_size; @@ -1046,7 +1045,7 @@ static grub_err_t grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), int argc, char *argv[]) { - grub_size_t size = 0; + grub_size_t size = 0, aligned_size = 0; grub_addr_t addr_min, addr_max; grub_addr_t addr; grub_err_t err; @@ -1068,8 +1067,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), goto fail; size = grub_get_initrd_size (&initrd_ctx); - - initrd_pages = (page_align (size) >> 12); + aligned_size = ALIGN_UP (size, 4096); /* Get the highest address available for the initrd. */ if (grub_le_to_cpu16 (linux_params.version) >= 0x0203) @@ -1097,7 +1095,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), addr_min = (grub_addr_t) prot_mode_target + prot_init_space; /* Put the initrd as high as possible, 4KiB aligned. */ - addr = (addr_max - size) & ~0xFFF; + addr = (addr_max - aligned_size) & ~0xFFF; if (addr < addr_min) { @@ -1108,7 +1106,8 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), { grub_relocator_chunk_t ch; err = grub_relocator_alloc_chunk_align (relocator, &ch, - addr_min, addr, size, 0x1000, + addr_min, addr, aligned_size, + 0x1000, GRUB_RELOCATOR_PREFERENCE_HIGH, 1); if (err) diff --git a/grub-core/loader/linux.c b/grub-core/loader/linux.c index 117232f0c..a63a11a7f 100644 --- a/grub-core/loader/linux.c +++ b/grub-core/loader/linux.c @@ -205,7 +205,8 @@ grub_initrd_init (int argc, char *argv[], initrd_ctx->nfiles++; initrd_ctx->components[i].size = grub_file_size (initrd_ctx->components[i].file); - initrd_ctx->size += ALIGN_UP (initrd_ctx->components[i].size, 4); + if (argc != 1) + initrd_ctx->size += ALIGN_UP (initrd_ctx->components[i].size, 4); } if (newc) diff --git a/include/grub/arm64/linux.h b/include/grub/arm64/linux.h index 864e5dc36..65796d907 100644 --- a/include/grub/arm64/linux.h +++ b/include/grub/arm64/linux.h @@ -23,6 +23,10 @@ #define GRUB_ARM64_LINUX_MAGIC 0x644d5241 /* 'ARM\x64' */ +#define GRUB_EFI_PAGE_SHIFT 12 +#define BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> GRUB_EFI_PAGE_SHIFT) +#define GRUB_EFI_PE_MAGIC 0x5A4D + /* From linux/Documentation/arm64/booting.txt */ struct grub_arm64_linux_kernel_header { @@ -38,4 +42,11 @@ struct grub_arm64_linux_kernel_header grub_uint32_t hdr_offset; /* Offset of PE/COFF header */ }; +/* Declare the functions for getting dtb and checking/booting image */ +void *grub_linux_get_fdt (void); +grub_err_t grub_arm64_uefi_check_image (struct grub_arm64_linux_kernel_header + *lh); +grub_err_t grub_arm64_uefi_boot_image (grub_addr_t addr, grub_size_t size, + char *args); + #endif /* ! GRUB_LINUX_CPU_HEADER */ From cfe2ae89360954f0cbc585f5c72e60a07eb066a2 Mon Sep 17 00:00:00 2001 From: Fu Wei Date: Thu, 7 May 2015 15:13:25 +0200 Subject: [PATCH 008/106] fdt.h: Add grub_fdt_set_reg64 macro Signed-off-by: Fu Wei --- include/grub/fdt.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/include/grub/fdt.h b/include/grub/fdt.h index 301699830..fdfca75bf 100644 --- a/include/grub/fdt.h +++ b/include/grub/fdt.h @@ -117,4 +117,16 @@ int grub_fdt_set_prop (void *fdt, unsigned int nodeoffset, const char *name, grub_fdt_set_prop ((fdt), (nodeoffset), (name), &_val, 8); \ }) +/* Setup "reg" property for + * #address-cells = <0x2> + * #size-cells = <0x2> + */ +#define grub_fdt_set_reg64(fdt, nodeoffset, addr, size) \ +({ \ + grub_uint64_t reg_64[2]; \ + reg_64[0] = grub_cpu_to_be64(addr); \ + reg_64[1] = grub_cpu_to_be64(size); \ + grub_fdt_set_prop ((fdt), (nodeoffset), "reg", reg_64, 16); \ +}) + #endif /* ! GRUB_FDT_HEADER */ From 9f731abc7f960a96a4c58d89717915e632837389 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Thu, 7 May 2015 16:21:34 +0200 Subject: [PATCH 009/106] Revert parts accidentally committed 2 commits ago. --- gentpl.py | 2 +- grub-core/loader/i386/linux.c | 11 ++++++----- grub-core/loader/linux.c | 3 +-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/gentpl.py b/gentpl.py index 0fd5ba427..f177883f8 100644 --- a/gentpl.py +++ b/gentpl.py @@ -759,7 +759,7 @@ def image(defn, platform): if test x$(TARGET_APPLE_LINKER) = x1; then \ $(MACHO2IMG) $< $@; \ else \ - $(TARGET_OBJCOPY) $(""" + cname(defn) + """_OBJCOPYFLAGS) --strip-unneeded -R .note -R .comment -R .note.gnu.build-id -R .MIPS.abiflags -R .reginfo -R .rel.dyn -R .note.gnu.gold-version -R .hash -R .dynsym -R .dynstr -R .rel.text $< $@; \ + $(TARGET_OBJCOPY) $(""" + cname(defn) + """_OBJCOPYFLAGS) --strip-unneeded -R .note -R .comment -R .note.gnu.build-id -R .MIPS.abiflags -R .reginfo -R .rel.dyn -R .note.gnu.gold-version $< $@; \ fi """) diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c index fddcc461d..291f7289f 100644 --- a/grub-core/loader/i386/linux.c +++ b/grub-core/loader/i386/linux.c @@ -69,6 +69,7 @@ static grub_addr_t prot_mode_target; static void *initrd_mem; static grub_addr_t initrd_mem_target; static grub_size_t prot_init_space; +static grub_uint32_t initrd_pages; static struct grub_relocator *relocator = NULL; static void *efi_mmap_buf; static grub_size_t maximal_cmdline_size; @@ -1045,7 +1046,7 @@ static grub_err_t grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), int argc, char *argv[]) { - grub_size_t size = 0, aligned_size = 0; + grub_size_t size = 0; grub_addr_t addr_min, addr_max; grub_addr_t addr; grub_err_t err; @@ -1067,7 +1068,8 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), goto fail; size = grub_get_initrd_size (&initrd_ctx); - aligned_size = ALIGN_UP (size, 4096); + + initrd_pages = (page_align (size) >> 12); /* Get the highest address available for the initrd. */ if (grub_le_to_cpu16 (linux_params.version) >= 0x0203) @@ -1095,7 +1097,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), addr_min = (grub_addr_t) prot_mode_target + prot_init_space; /* Put the initrd as high as possible, 4KiB aligned. */ - addr = (addr_max - aligned_size) & ~0xFFF; + addr = (addr_max - size) & ~0xFFF; if (addr < addr_min) { @@ -1106,8 +1108,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), { grub_relocator_chunk_t ch; err = grub_relocator_alloc_chunk_align (relocator, &ch, - addr_min, addr, aligned_size, - 0x1000, + addr_min, addr, size, 0x1000, GRUB_RELOCATOR_PREFERENCE_HIGH, 1); if (err) diff --git a/grub-core/loader/linux.c b/grub-core/loader/linux.c index a63a11a7f..117232f0c 100644 --- a/grub-core/loader/linux.c +++ b/grub-core/loader/linux.c @@ -205,8 +205,7 @@ grub_initrd_init (int argc, char *argv[], initrd_ctx->nfiles++; initrd_ctx->components[i].size = grub_file_size (initrd_ctx->components[i].file); - if (argc != 1) - initrd_ctx->size += ALIGN_UP (initrd_ctx->components[i].size, 4); + initrd_ctx->size += ALIGN_UP (initrd_ctx->components[i].size, 4); } if (newc) From e5b4ba8c2b2cfbb84e5b8254fb7d0b15b799fe78 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Thu, 7 May 2015 16:23:39 +0200 Subject: [PATCH 010/106] linux.c: Ensure that initrd is page-aligned. --- grub-core/loader/i386/linux.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c index 291f7289f..fddcc461d 100644 --- a/grub-core/loader/i386/linux.c +++ b/grub-core/loader/i386/linux.c @@ -69,7 +69,6 @@ static grub_addr_t prot_mode_target; static void *initrd_mem; static grub_addr_t initrd_mem_target; static grub_size_t prot_init_space; -static grub_uint32_t initrd_pages; static struct grub_relocator *relocator = NULL; static void *efi_mmap_buf; static grub_size_t maximal_cmdline_size; @@ -1046,7 +1045,7 @@ static grub_err_t grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), int argc, char *argv[]) { - grub_size_t size = 0; + grub_size_t size = 0, aligned_size = 0; grub_addr_t addr_min, addr_max; grub_addr_t addr; grub_err_t err; @@ -1068,8 +1067,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), goto fail; size = grub_get_initrd_size (&initrd_ctx); - - initrd_pages = (page_align (size) >> 12); + aligned_size = ALIGN_UP (size, 4096); /* Get the highest address available for the initrd. */ if (grub_le_to_cpu16 (linux_params.version) >= 0x0203) @@ -1097,7 +1095,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), addr_min = (grub_addr_t) prot_mode_target + prot_init_space; /* Put the initrd as high as possible, 4KiB aligned. */ - addr = (addr_max - size) & ~0xFFF; + addr = (addr_max - aligned_size) & ~0xFFF; if (addr < addr_min) { @@ -1108,7 +1106,8 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), { grub_relocator_chunk_t ch; err = grub_relocator_alloc_chunk_align (relocator, &ch, - addr_min, addr, size, 0x1000, + addr_min, addr, aligned_size, + 0x1000, GRUB_RELOCATOR_PREFERENCE_HIGH, 1); if (err) From 5fd1cb980af603126b82f421417f15326b0ca38d Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Thu, 7 May 2015 16:34:34 +0200 Subject: [PATCH 011/106] grub-mkrescue: Recognize -output as an alias of --output. This helps us to be in line with xorriso -as mkisofs. Suggested by: Thomas Schmitt --- util/grub-mkrescue.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/util/grub-mkrescue.c b/util/grub-mkrescue.c index 815fc9175..5a7993fbb 100644 --- a/util/grub-mkrescue.c +++ b/util/grub-mkrescue.c @@ -451,6 +451,12 @@ main (int argc, char *argv[]) int i; for (i = 1; i < argc; i++) { + if (strcmp (argv[i], "-output") == 0) { + argp_argv[argp_argc++] = "--output"; + i++; + argp_argv[argp_argc++] = argv[i]; + continue; + } switch (args_to_eat (argv[i])) { case 2: From 9916ed6f82d12b203b61cbc6d6bb9c56af707c02 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Thu, 7 May 2015 17:09:58 +0200 Subject: [PATCH 012/106] grub-install-common: Increase buf size to 8192 as modinfo.sh is bigger. --- util/grub-install-common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/grub-install-common.c b/util/grub-install-common.c index 37c1a98b9..0364b327c 100644 --- a/util/grub-install-common.c +++ b/util/grub-install-common.c @@ -902,7 +902,7 @@ grub_install_get_target (const char *src) { char *fn; grub_util_fd_t f; - char buf[2048]; + char buf[8192]; ssize_t r; char *c, *pl, *p; size_t i; From 71783dc9780c1e1897a59ec3273e6259807f47eb Mon Sep 17 00:00:00 2001 From: Daniel Kiper Date: Thu, 7 May 2015 18:00:47 +0200 Subject: [PATCH 013/106] i386/relocator: Remove unused extern grub_relocator64_rip_addr Signed-off-by: Daniel Kiper --- grub-core/lib/i386/relocator.c | 1 - 1 file changed, 1 deletion(-) diff --git a/grub-core/lib/i386/relocator.c b/grub-core/lib/i386/relocator.c index ffaf25f08..71dd4f0ab 100644 --- a/grub-core/lib/i386/relocator.c +++ b/grub-core/lib/i386/relocator.c @@ -64,7 +64,6 @@ extern grub_uint64_t grub_relocator64_rbx; extern grub_uint64_t grub_relocator64_rcx; extern grub_uint64_t grub_relocator64_rdx; extern grub_uint64_t grub_relocator64_rip; -extern grub_uint64_t grub_relocator64_rip_addr; extern grub_uint64_t grub_relocator64_rsp; extern grub_uint64_t grub_relocator64_rsi; extern grub_addr_t grub_relocator64_cr3; From a8c473288d3f0a5e17a903a5121dea1a695dda3b Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Thu, 7 May 2015 20:24:24 +0300 Subject: [PATCH 014/106] loader/linux: do not pad initrd with zeroes at the end Syslinux memdisk is using initrd image and needs to know uncompressed size in advance. For gzip uncompressed size is at the end of compressed stream. Grub padded each input file to 4 bytes at the end, which means syslinux got wrong size. Linux initramfs loader apparently does not care about trailing alignment. So change code to align beginning of each file instead which atomatically gives us the correct size for single file. Reported-By: David Shaw --- grub-core/loader/linux.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/grub-core/loader/linux.c b/grub-core/loader/linux.c index 117232f0c..d2cd591f6 100644 --- a/grub-core/loader/linux.c +++ b/grub-core/loader/linux.c @@ -161,6 +161,9 @@ grub_initrd_init (int argc, char *argv[], for (i = 0; i < argc; i++) { const char *fname = argv[i]; + + initrd_ctx->size = ALIGN_UP (initrd_ctx->size, 4); + if (grub_memcmp (argv[i], "newc:", 5) == 0) { const char *ptr, *eptr; @@ -205,7 +208,7 @@ grub_initrd_init (int argc, char *argv[], initrd_ctx->nfiles++; initrd_ctx->components[i].size = grub_file_size (initrd_ctx->components[i].file); - initrd_ctx->size += ALIGN_UP (initrd_ctx->components[i].size, 4); + initrd_ctx->size += initrd_ctx->components[i].size; } if (newc) @@ -248,10 +251,12 @@ grub_initrd_load (struct grub_linux_initrd_context *initrd_ctx, int i; int newc = 0; struct dir *root = 0; + grub_ssize_t cursize = 0; for (i = 0; i < initrd_ctx->nfiles; i++) { - grub_ssize_t cursize; + grub_memset (ptr, 0, ALIGN_UP_OVERHEAD (cursize, 4)); + ptr += ALIGN_UP_OVERHEAD (cursize, 4); if (initrd_ctx->components[i].newc_name) { @@ -283,8 +288,6 @@ grub_initrd_load (struct grub_linux_initrd_context *initrd_ctx, return grub_errno; } ptr += cursize; - grub_memset (ptr, 0, ALIGN_UP_OVERHEAD (cursize, 4)); - ptr += ALIGN_UP_OVERHEAD (cursize, 4); } if (newc) ptr = make_header (ptr, "TRAILER!!!", sizeof ("TRAILER!!!") - 1, 0, 0); From 16a7e723ea37d4596348a76f54a6675c6e03fedc Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Thu, 7 May 2015 20:33:28 +0300 Subject: [PATCH 015/106] convert to, not from, CPU byte order in DNS receive function --- grub-core/net/dns.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/grub-core/net/dns.c b/grub-core/net/dns.c index 0b771fb10..9d0c8fcea 100644 --- a/grub-core/net/dns.c +++ b/grub-core/net/dns.c @@ -262,7 +262,7 @@ recv_hook (grub_net_udp_socket_t sock __attribute__ ((unused)), grub_netbuff_free (nb); return GRUB_ERR_NONE; } - for (i = 0; i < grub_cpu_to_be16 (head->qdcount); i++) + for (i = 0; i < grub_be_to_cpu16 (head->qdcount); i++) { if (ptr >= nb->tail) { @@ -277,7 +277,7 @@ recv_hook (grub_net_udp_socket_t sock __attribute__ ((unused)), ptr += 4; } *data->addresses = grub_malloc (sizeof ((*data->addresses)[0]) - * grub_cpu_to_be16 (head->ancount)); + * grub_be_to_cpu16 (head->ancount)); if (!*data->addresses) { grub_errno = GRUB_ERR_NONE; @@ -286,7 +286,7 @@ recv_hook (grub_net_udp_socket_t sock __attribute__ ((unused)), } reparse_ptr = ptr; reparse: - for (i = 0, ptr = reparse_ptr; i < grub_cpu_to_be16 (head->ancount); i++) + for (i = 0, ptr = reparse_ptr; i < grub_be_to_cpu16 (head->ancount); i++) { int ignored = 0; grub_uint8_t class; From 7b386b703154c0901c4616badf18ddb260954bc1 Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Thu, 7 May 2015 20:37:16 +0300 Subject: [PATCH 016/106] efidisk: move device path helpers in core for efinet --- grub-core/disk/efi/efidisk.c | 61 ++++++------------------------------ grub-core/kern/efi/efi.c | 41 ++++++++++++++++++++++++ include/grub/efi/efi.h | 4 +++ 3 files changed, 55 insertions(+), 51 deletions(-) diff --git a/grub-core/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c index 60a6d3c50..a8783a3c1 100644 --- a/grub-core/disk/efi/efidisk.c +++ b/grub-core/disk/efi/efidisk.c @@ -43,47 +43,6 @@ static struct grub_efidisk_data *fd_devices; static struct grub_efidisk_data *hd_devices; static struct grub_efidisk_data *cd_devices; -/* Duplicate a device path. */ -static grub_efi_device_path_t * -duplicate_device_path (const grub_efi_device_path_t *dp) -{ - grub_efi_device_path_t *p; - grub_size_t total_size = 0; - - for (p = (grub_efi_device_path_t *) dp; - ; - p = GRUB_EFI_NEXT_DEVICE_PATH (p)) - { - total_size += GRUB_EFI_DEVICE_PATH_LENGTH (p); - if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (p)) - break; - } - - p = grub_malloc (total_size); - if (! p) - return 0; - - grub_memcpy (p, dp, total_size); - return p; -} - -/* Return the device path node right before the end node. */ -static grub_efi_device_path_t * -find_last_device_path (const grub_efi_device_path_t *dp) -{ - grub_efi_device_path_t *next, *p; - - if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp)) - return 0; - - for (p = (grub_efi_device_path_t *) dp, next = GRUB_EFI_NEXT_DEVICE_PATH (p); - ! GRUB_EFI_END_ENTIRE_DEVICE_PATH (next); - p = next, next = GRUB_EFI_NEXT_DEVICE_PATH (next)) - ; - - return p; -} - static struct grub_efidisk_data * make_devices (void) { @@ -110,7 +69,7 @@ make_devices (void) if (! dp) continue; - ldp = find_last_device_path (dp); + ldp = grub_efi_find_last_device_path (dp); if (! ldp) /* This is empty. Why? */ continue; @@ -150,11 +109,11 @@ find_parent_device (struct grub_efidisk_data *devices, grub_efi_device_path_t *dp, *ldp; struct grub_efidisk_data *parent; - dp = duplicate_device_path (d->device_path); + dp = grub_efi_duplicate_device_path (d->device_path); if (! dp) return 0; - ldp = find_last_device_path (dp); + ldp = grub_efi_find_last_device_path (dp); ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; ldp->length = sizeof (*ldp); @@ -180,11 +139,11 @@ is_child (struct grub_efidisk_data *child, grub_efi_device_path_t *dp, *ldp; int ret; - dp = duplicate_device_path (child->device_path); + dp = grub_efi_duplicate_device_path (child->device_path); if (! dp) return 0; - ldp = find_last_device_path (dp); + ldp = grub_efi_find_last_device_path (dp); ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; ldp->length = sizeof (*ldp); @@ -207,8 +166,8 @@ add_device (struct grub_efidisk_data **devices, struct grub_efidisk_data *d) { int ret; - ret = grub_efi_compare_device_paths (find_last_device_path ((*p)->device_path), - find_last_device_path (d->device_path)); + ret = grub_efi_compare_device_paths (grub_efi_find_last_device_path ((*p)->device_path), + grub_efi_find_last_device_path (d->device_path)); if (ret == 0) ret = grub_efi_compare_device_paths ((*p)->device_path, d->device_path); @@ -795,7 +754,7 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle) if (! dp) return 0; - ldp = find_last_device_path (dp); + ldp = grub_efi_find_last_device_path (dp); if (! ldp) return 0; @@ -810,14 +769,14 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle) /* It is necessary to duplicate the device path so that GRUB can overwrite it. */ - dup_dp = duplicate_device_path (dp); + dup_dp = grub_efi_duplicate_device_path (dp); if (! dup_dp) return 0; while (1) { grub_efi_device_path_t *dup_ldp; - dup_ldp = find_last_device_path (dup_dp); + dup_ldp = grub_efi_find_last_device_path (dup_dp); if (!(GRUB_EFI_DEVICE_PATH_TYPE (dup_ldp) == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE && (GRUB_EFI_DEVICE_PATH_SUBTYPE (dup_ldp) == GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE || GRUB_EFI_DEVICE_PATH_SUBTYPE (dup_ldp) == GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE))) diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c index b9eb1ab1e..49a150133 100644 --- a/grub-core/kern/efi/efi.c +++ b/grub-core/kern/efi/efi.c @@ -394,6 +394,47 @@ grub_efi_get_device_path (grub_efi_handle_t handle) GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); } +/* Return the device path node right before the end node. */ +grub_efi_device_path_t * +grub_efi_find_last_device_path (const grub_efi_device_path_t *dp) +{ + grub_efi_device_path_t *next, *p; + + if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp)) + return 0; + + for (p = (grub_efi_device_path_t *) dp, next = GRUB_EFI_NEXT_DEVICE_PATH (p); + ! GRUB_EFI_END_ENTIRE_DEVICE_PATH (next); + p = next, next = GRUB_EFI_NEXT_DEVICE_PATH (next)) + ; + + return p; +} + +/* Duplicate a device path. */ +grub_efi_device_path_t * +grub_efi_duplicate_device_path (const grub_efi_device_path_t *dp) +{ + grub_efi_device_path_t *p; + grub_size_t total_size = 0; + + for (p = (grub_efi_device_path_t *) dp; + ; + p = GRUB_EFI_NEXT_DEVICE_PATH (p)) + { + total_size += GRUB_EFI_DEVICE_PATH_LENGTH (p); + if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (p)) + break; + } + + p = grub_malloc (total_size); + if (! p) + return 0; + + grub_memcpy (p, dp, total_size); + return p; +} + static void dump_vendor_path (const char *type, grub_efi_vendor_device_path_t *vendor) { diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h index 489cf9e6d..0e6fd86b0 100644 --- a/include/grub/efi/efi.h +++ b/include/grub/efi/efi.h @@ -53,6 +53,10 @@ void EXPORT_FUNC(grub_efi_print_device_path) (grub_efi_device_path_t *dp); char *EXPORT_FUNC(grub_efi_get_filename) (grub_efi_device_path_t *dp); grub_efi_device_path_t * EXPORT_FUNC(grub_efi_get_device_path) (grub_efi_handle_t handle); +grub_efi_device_path_t * +EXPORT_FUNC(grub_efi_find_last_device_path) (const grub_efi_device_path_t *dp); +grub_efi_device_path_t * +EXPORT_FUNC(grub_efi_duplicate_device_path) (const grub_efi_device_path_t *dp); grub_err_t EXPORT_FUNC (grub_efi_finish_boot_services) (grub_efi_uintn_t *outbuf_size, void *outbuf, grub_efi_uintn_t *map_key, grub_efi_uintn_t *efi_desc_size, From c52ae40570c3bfbcca22d2195f5e6b31009d8a3f Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Thu, 7 May 2015 20:37:17 +0300 Subject: [PATCH 017/106] efinet: skip virtual IPv4 and IPv6 devices when enumerating cards EDK2 PXE driver creates two child devices - IPv4 and IPv6 - with bound SNP instance. This means we get three cards for every physical adapter when enumerating. Not only is this confusing, this may result in grub ignoring packets that come in via the "wrong" card. Example of device hierarchy is Ctrl[91] PciRoot(0x0)/Pci(0x3,0x0) Ctrl[95] PciRoot(0x0)/Pci(0x3,0x0)/MAC(525400123456,0x1) Ctrl[B4] PciRoot(0x0)/Pci(0x3,0x0)/MAC(525400123456,0x1)/IPv4(0.0.0.0) Ctrl[BC] PciRoot(0x0)/Pci(0x3,0x0)/MAC(525400123456,0x1)/IPv6(0000:0000:0000:0000:0000:0000:0000:0000) Skip PXE created virtual devices when enumerating cards. Make sure to find real card when applying initial autoconfiguration during PXE boot, this information is associated with one of child devices. --- grub-core/net/drivers/efi/efinet.c | 51 +++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c index f171f20bf..2b53e9ef6 100644 --- a/grub-core/net/drivers/efi/efinet.c +++ b/grub-core/net/drivers/efi/efinet.c @@ -174,6 +174,29 @@ grub_efinet_findcards (void) { grub_efi_simple_network_t *net; struct grub_net_card *card; + grub_efi_device_path_t *dp, *parent = NULL, *child = NULL; + + /* EDK2 UEFI PXE driver creates IPv4 and IPv6 messaging devices as + children of main MAC messaging device. We only need one device with + bound SNP per physical card, otherwise they compete with each other + when polling for incoming packets. + */ + dp = grub_efi_get_device_path (*handle); + if (!dp) + continue; + for (; ! GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp); dp = GRUB_EFI_NEXT_DEVICE_PATH (dp)) + { + parent = child; + child = dp; + } + if (child + && GRUB_EFI_DEVICE_PATH_TYPE (child) == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE + && (GRUB_EFI_DEVICE_PATH_SUBTYPE (child) == GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE + || GRUB_EFI_DEVICE_PATH_SUBTYPE (child) == GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE) + && parent + && GRUB_EFI_DEVICE_PATH_TYPE (parent) == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE + && GRUB_EFI_DEVICE_PATH_SUBTYPE (parent) == GRUB_EFI_MAC_ADDRESS_DEVICE_PATH_SUBTYPE) + continue; net = grub_efi_open_protocol (*handle, &net_io_guid, GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); @@ -251,7 +274,33 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, if (! cdp) continue; if (grub_efi_compare_device_paths (dp, cdp) != 0) - continue; + { + grub_efi_device_path_t *ldp, *dup_dp, *dup_ldp; + int match; + + /* EDK2 UEFI PXE driver creates pseudo devices with type IPv4/IPv6 + as children of Ethernet card and binds PXE and Load File protocols + to it. Loaded Image Device Path protocol will point to these pseudo + devices. We skip them when enumerating cards, so here we need to + find matching MAC device. + */ + ldp = grub_efi_find_last_device_path (dp); + if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE + || (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE + && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE)) + continue; + dup_dp = grub_efi_duplicate_device_path (dp); + if (!dup_dp) + continue; + dup_ldp = grub_efi_find_last_device_path (dup_dp); + dup_ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; + dup_ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; + dup_ldp->length = sizeof (*dup_ldp); + match = grub_efi_compare_device_paths (dup_dp, cdp) == 0; + grub_free (dup_dp); + if (!match) + continue; + } pxe = grub_efi_open_protocol (hnd, &pxe_io_guid, GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); if (! pxe) From 49426e9fd2e562c73a4f1206f32eff9e424a1a73 Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Thu, 7 May 2015 20:37:17 +0300 Subject: [PATCH 018/106] efinet: open Simple Network Protocol exclusively EDK2 network stack is based on Managed Network Protocol which is layered on top of Simple Management Protocol and does background polling. This polling races with grub for received (and probably trasmitted) packets which causes either serious slowdown or complete failure to load files. Open SNP device exclusively. This destroys all child MNP instances and stops background polling. Exclusive open cannot be done when enumerating cards, as it would destroy PXE information we need to autoconfigure interface; and it cannot be done during autoconfiguration as we need to do it for non-PXE boot as well. So move SNP open to card ->open method and add matching ->close to clean up. Based on patch from Mark Salter Also-By: Mark Salter Closes: 41731 --- grub-core/net/drivers/efi/efinet.c | 46 ++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c index 2b53e9ef6..5533515fd 100644 --- a/grub-core/net/drivers/efi/efinet.c +++ b/grub-core/net/drivers/efi/efinet.c @@ -142,9 +142,55 @@ get_card_packet (struct grub_net_card *dev) return nb; } +static grub_err_t +open_card (struct grub_net_card *dev) +{ + grub_efi_simple_network_t *net; + + /* Try to reopen SNP exlusively to close any active MNP protocol instance + that may compete for packet polling + */ + net = grub_efi_open_protocol (dev->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) + return grub_error (GRUB_ERR_NET_NO_CARD, "%s: net start failed", + dev->name); + + if (net->mode->state == GRUB_EFI_NETWORK_STOPPED) + return grub_error (GRUB_ERR_NET_NO_CARD, "%s: card stopped", + dev->name); + + if (net->mode->state == GRUB_EFI_NETWORK_STARTED + && efi_call_3 (net->initialize, net, 0, 0) != GRUB_EFI_SUCCESS) + return grub_error (GRUB_ERR_NET_NO_CARD, "%s: net initialize failed", + dev->name); + + efi_call_4 (grub_efi_system_table->boot_services->close_protocol, + dev->efi_net, &net_io_guid, + grub_efi_image_handle, dev->efi_handle); + dev->efi_net = net; + } + + /* If it failed we just try to run as best as we can */ + return GRUB_ERR_NONE; +} + +static void +close_card (struct grub_net_card *dev) +{ + efi_call_4 (grub_efi_system_table->boot_services->close_protocol, + dev->efi_net, &net_io_guid, + grub_efi_image_handle, dev->efi_handle); +} + static struct grub_net_card_driver efidriver = { .name = "efinet", + .open = open_card, + .close = close_card, .send = send_card_buffer, .recv = get_card_packet }; From 2dcf260d899f65cd84e4f676e03d76f51ae01736 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Thu, 7 May 2015 19:45:06 +0200 Subject: [PATCH 019/106] util/grub-mkrescue: Fix compilation --- util/grub-mkrescue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/grub-mkrescue.c b/util/grub-mkrescue.c index 5a7993fbb..451182647 100644 --- a/util/grub-mkrescue.c +++ b/util/grub-mkrescue.c @@ -452,7 +452,7 @@ main (int argc, char *argv[]) for (i = 1; i < argc; i++) { if (strcmp (argv[i], "-output") == 0) { - argp_argv[argp_argc++] = "--output"; + argp_argv[argp_argc++] = (char *) "--output"; i++; argp_argv[argp_argc++] = argv[i]; continue; From 6a5c78c8c85c890034974a297bfb009dff0954c6 Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Thu, 7 May 2015 22:13:34 +0300 Subject: [PATCH 020/106] Add asm-tests to tarball --- conf/Makefile.extra-dist | 1 + 1 file changed, 1 insertion(+) diff --git a/conf/Makefile.extra-dist b/conf/Makefile.extra-dist index db6cfd12e..ea6b9df3a 100644 --- a/conf/Makefile.extra-dist +++ b/conf/Makefile.extra-dist @@ -5,6 +5,7 @@ EXTRA_DIST += gentpl.py EXTRA_DIST += Makefile.util.def EXTRA_DIST += Makefile.utilgcry.def +EXTRA_DIST += asm-tests EXTRA_DIST += unicode EXTRA_DIST += util/import_gcry.py From 07258815e96aab2c72593d0129d17051cbf68d27 Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Fri, 8 May 2015 06:15:16 +0300 Subject: [PATCH 021/106] acpi: do not skip BIOS scan if EBDA length is zero EBDA layout is not standardized so we cannot assume first two bytes are length. Neither is it required by ACPI standard. HP 8710W is known to contain zeroes here. Closes: 45002 --- grub-core/commands/acpi.c | 4 ++++ grub-core/commands/i386/pc/acpi.c | 10 ++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/grub-core/commands/acpi.c b/grub-core/commands/acpi.c index 05a6dcad4..c3861f594 100644 --- a/grub-core/commands/acpi.c +++ b/grub-core/commands/acpi.c @@ -180,8 +180,10 @@ grub_acpi_create_ebda (void) struct grub_acpi_rsdp_v20 *v2; ebda = (grub_uint8_t *) (grub_addr_t) ((*((grub_uint16_t *)0x40e)) << 4); + grub_dprintf ("acpi", "EBDA @%p\n", ebda); if (ebda) ebda_kb_len = *(grub_uint16_t *) ebda; + grub_dprintf ("acpi", "EBDA length 0x%x\n", ebda_kb_len); if (ebda_kb_len > 16) ebda_kb_len = 0; ctx.ebda_len = (ebda_kb_len + 1) << 10; @@ -495,6 +497,8 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args) if (! rsdp) rsdp = grub_machine_acpi_get_rsdpv1 (); + grub_dprintf ("acpi", "RSDP @%p\n", rsdp); + if (rsdp) { grub_uint32_t *entry_ptr; diff --git a/grub-core/commands/i386/pc/acpi.c b/grub-core/commands/i386/pc/acpi.c index d415d2305..297f5d05f 100644 --- a/grub-core/commands/i386/pc/acpi.c +++ b/grub-core/commands/i386/pc/acpi.c @@ -29,14 +29,15 @@ grub_machine_acpi_get_rsdpv1 (void) grub_dprintf ("acpi", "Looking for RSDP. Scanning EBDA\n"); ebda = (grub_uint8_t *) ((* ((grub_uint16_t *) 0x40e)) << 4); ebda_len = * (grub_uint16_t *) ebda; - if (! ebda_len) - return 0; + if (! ebda_len) /* FIXME do we really need this check? */ + goto scan_bios; for (ptr = ebda; ptr < ebda + 0x400; ptr += 16) if (grub_memcmp (ptr, GRUB_RSDP_SIGNATURE, GRUB_RSDP_SIGNATURE_SIZE) == 0 && grub_byte_checksum (ptr, sizeof (struct grub_acpi_rsdp_v10)) == 0 && ((struct grub_acpi_rsdp_v10 *) ptr)->revision == 0) return (struct grub_acpi_rsdp_v10 *) ptr; +scan_bios: grub_dprintf ("acpi", "Looking for RSDP. Scanning BIOS\n"); for (ptr = (grub_uint8_t *) 0xe0000; ptr < (grub_uint8_t *) 0x100000; ptr += 16) @@ -56,8 +57,8 @@ grub_machine_acpi_get_rsdpv2 (void) grub_dprintf ("acpi", "Looking for RSDP. Scanning EBDA\n"); ebda = (grub_uint8_t *) ((* ((grub_uint16_t *) 0x40e)) << 4); ebda_len = * (grub_uint16_t *) ebda; - if (! ebda_len) - return 0; + if (! ebda_len) /* FIXME do we really need this check? */ + goto scan_bios; for (ptr = ebda; ptr < ebda + 0x400; ptr += 16) if (grub_memcmp (ptr, GRUB_RSDP_SIGNATURE, GRUB_RSDP_SIGNATURE_SIZE) == 0 && grub_byte_checksum (ptr, sizeof (struct grub_acpi_rsdp_v10)) == 0 @@ -67,6 +68,7 @@ grub_machine_acpi_get_rsdpv2 (void) == 0) return (struct grub_acpi_rsdp_v20 *) ptr; +scan_bios: grub_dprintf ("acpi", "Looking for RSDP. Scanning BIOS\n"); for (ptr = (grub_uint8_t *) 0xe0000; ptr < (grub_uint8_t *) 0x100000; ptr += 16) From 1570140f0362d9936f97a014a9fa5cecbca54f07 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 14 Jul 2014 17:21:29 +0200 Subject: [PATCH 022/106] 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 16ffd3f1e..4bd52d1e0 100644 --- a/grub-core/fs/xfs.c +++ b/grub-core/fs/xfs.c @@ -603,8 +603,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; From a139188eb559ee23f51540948ec84ef5948fb2d1 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 14 Jul 2014 17:21:30 +0200 Subject: [PATCH 023/106] 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 4bd52d1e0..0d704e9a4 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 @@ -506,13 +506,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 `..'. */ @@ -545,7 +544,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'; @@ -627,7 +625,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; @@ -689,7 +688,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); From 5082ea618439fe59956d071777be0c9c74fbbcf5 Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Wed, 13 May 2015 09:47:17 +0300 Subject: [PATCH 024/106] remove extra newlines in grub_util_* strings grub_util_{info,warn,error} already add trailing newlines, so remove them from format strings. Also trailing full stops are already added. --- grub-core/bus/emu/pci.c | 2 +- grub-core/disk/lvm.c | 40 +++++++++++++++++----------------- grub-core/osdep/linux/ofpath.c | 2 +- util/grub-install-common.c | 2 +- util/grub-install.c | 6 ++--- util/grub-mknetdir.c | 2 +- util/grub-pe2elf.c | 2 +- util/mkimage.c | 4 ++-- 8 files changed, 30 insertions(+), 30 deletions(-) diff --git a/grub-core/bus/emu/pci.c b/grub-core/bus/emu/pci.c index 663e5540c..267f2622d 100644 --- a/grub-core/bus/emu/pci.c +++ b/grub-core/bus/emu/pci.c @@ -55,7 +55,7 @@ grub_pci_device_map_range (grub_pci_device_t dev, grub_addr_t base, int err; err = pci_device_map_range (dev, base, size, PCI_DEV_MAP_FLAG_WRITABLE, &addr); if (err) - grub_util_error ("mapping 0x%llx failed (error %d)\n", + grub_util_error ("mapping 0x%llx failed (error %d)", (unsigned long long) base, err); return addr; } diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c index 9b97004d8..7b265c780 100644 --- a/grub-core/disk/lvm.c +++ b/grub-core/disk/lvm.c @@ -160,7 +160,7 @@ grub_lvm_detect (grub_disk_t disk, "we don't support multiple LVM data areas"); #ifdef GRUB_UTIL - grub_util_info ("we don't support multiple LVM data areas\n"); + grub_util_info ("we don't support multiple LVM data areas"); #endif goto fail; } @@ -189,7 +189,7 @@ grub_lvm_detect (grub_disk_t disk, grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "unknown LVM metadata header"); #ifdef GRUB_UTIL - grub_util_info ("unknown LVM metadata header\n"); + grub_util_info ("unknown LVM metadata header"); #endif goto fail2; } @@ -213,7 +213,7 @@ grub_lvm_detect (grub_disk_t disk, if (q == metadatabuf + mda_size) { #ifdef GRUB_UTIL - grub_util_info ("error parsing metadata\n"); + grub_util_info ("error parsing metadata"); #endif goto fail2; } @@ -230,7 +230,7 @@ grub_lvm_detect (grub_disk_t disk, if (p == NULL) { #ifdef GRUB_UTIL - grub_util_info ("couldn't find ID\n"); + grub_util_info ("couldn't find ID"); #endif goto fail3; } @@ -258,7 +258,7 @@ grub_lvm_detect (grub_disk_t disk, if (p == NULL) { #ifdef GRUB_UTIL - grub_util_info ("unknown extent size\n"); + grub_util_info ("unknown extent size"); #endif goto fail4; } @@ -306,7 +306,7 @@ grub_lvm_detect (grub_disk_t disk, if (p == NULL) { #ifdef GRUB_UTIL - grub_util_info ("unknown pe_start\n"); + grub_util_info ("unknown pe_start"); #endif goto pvs_fail; } @@ -315,7 +315,7 @@ grub_lvm_detect (grub_disk_t disk, if (p == NULL) { #ifdef GRUB_UTIL - grub_util_info ("error parsing pe_start\n"); + grub_util_info ("error parsing pe_start"); #endif goto pvs_fail; } @@ -402,7 +402,7 @@ grub_lvm_detect (grub_disk_t disk, if (p == NULL) { #ifdef GRUB_UTIL - grub_util_info ("couldn't find ID\n"); + grub_util_info ("couldn't find ID"); #endif goto lvs_fail; } @@ -422,7 +422,7 @@ grub_lvm_detect (grub_disk_t disk, if (p == NULL) { #ifdef GRUB_UTIL - grub_util_info ("unknown segment_count\n"); + grub_util_info ("unknown segment_count"); #endif goto lvs_fail; } @@ -436,7 +436,7 @@ grub_lvm_detect (grub_disk_t disk, if (p == NULL) { #ifdef GRUB_UTIL - grub_util_info ("unknown segment\n"); + grub_util_info ("unknown segment"); #endif goto lvs_segment_fail; } @@ -445,7 +445,7 @@ grub_lvm_detect (grub_disk_t disk, if (p == NULL) { #ifdef GRUB_UTIL - grub_util_info ("unknown start_extent\n"); + grub_util_info ("unknown start_extent"); #endif goto lvs_segment_fail; } @@ -453,7 +453,7 @@ grub_lvm_detect (grub_disk_t disk, if (p == NULL) { #ifdef GRUB_UTIL - grub_util_info ("unknown extent_count\n"); + grub_util_info ("unknown extent_count"); #endif goto lvs_segment_fail; } @@ -475,7 +475,7 @@ grub_lvm_detect (grub_disk_t disk, if (p == NULL) { #ifdef GRUB_UTIL - grub_util_info ("unknown stripe_count\n"); + grub_util_info ("unknown stripe_count"); #endif goto lvs_segment_fail; } @@ -491,7 +491,7 @@ grub_lvm_detect (grub_disk_t disk, if (p == NULL) { #ifdef GRUB_UTIL - grub_util_info ("unknown stripes\n"); + grub_util_info ("unknown stripes"); #endif goto lvs_segment_fail2; } @@ -533,7 +533,7 @@ grub_lvm_detect (grub_disk_t disk, if (p == NULL) { #ifdef GRUB_UTIL - grub_util_info ("unknown mirror_count\n"); + grub_util_info ("unknown mirror_count"); #endif goto lvs_segment_fail; } @@ -545,7 +545,7 @@ grub_lvm_detect (grub_disk_t disk, if (p == NULL) { #ifdef GRUB_UTIL - grub_util_info ("unknown mirrors\n"); + grub_util_info ("unknown mirrors"); #endif goto lvs_segment_fail2; } @@ -607,7 +607,7 @@ grub_lvm_detect (grub_disk_t disk, if (p == NULL) { #ifdef GRUB_UTIL - grub_util_info ("unknown device_count\n"); + grub_util_info ("unknown device_count"); #endif goto lvs_segment_fail; } @@ -618,7 +618,7 @@ grub_lvm_detect (grub_disk_t disk, if (p == NULL) { #ifdef GRUB_UTIL - grub_util_info ("unknown stripe_size\n"); + grub_util_info ("unknown stripe_size"); #endif goto lvs_segment_fail; } @@ -631,7 +631,7 @@ grub_lvm_detect (grub_disk_t disk, if (p == NULL) { #ifdef GRUB_UTIL - grub_util_info ("unknown raids\n"); + grub_util_info ("unknown raids"); #endif goto lvs_segment_fail2; } @@ -678,7 +678,7 @@ grub_lvm_detect (grub_disk_t disk, p2 = grub_strchr (p, '"'); if (p2) *p2 = 0; - grub_util_info ("unknown LVM type %s\n", p); + grub_util_info ("unknown LVM type %s", p); if (p2) *p2 ='"'; #endif diff --git a/grub-core/osdep/linux/ofpath.c b/grub-core/osdep/linux/ofpath.c index 05b1ecdf8..a79682a5e 100644 --- a/grub-core/osdep/linux/ofpath.c +++ b/grub-core/osdep/linux/ofpath.c @@ -539,7 +539,7 @@ grub_util_devname_to_ofpath (const char *sys_devname) ofpath = xstrdup ("floppy"); else { - grub_util_warn (_("unknown device type %s\n"), device); + grub_util_warn (_("unknown device type %s"), device); ofpath = NULL; } diff --git a/util/grub-install-common.c b/util/grub-install-common.c index 0364b327c..25983089f 100644 --- a/util/grub-install-common.c +++ b/util/grub-install-common.c @@ -494,7 +494,7 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix, tgt = grub_install_get_image_target (mkimage_target); if (!tgt) - grub_util_error (_("unknown target format %s\n"), mkimage_target); + grub_util_error (_("unknown target format %s"), mkimage_target); grub_install_generate_image (dir, prefix, fp, outname, modules.entries, memdisk_path, diff --git a/util/grub-install.c b/util/grub-install.c index 7b394c997..566272600 100644 --- a/util/grub-install.c +++ b/util/grub-install.c @@ -773,7 +773,7 @@ bless (grub_device_t dev, const char *path, int x86) err = grub_mac_bless_inode (dev, st.st_ino, S_ISDIR (st.st_mode), x86); if (err) grub_util_error ("%s", grub_errmsg); - grub_util_info ("blessed\n"); + grub_util_info ("blessed"); } static void @@ -1070,7 +1070,7 @@ main (int argc, char *argv[]) efidir_is_mac = 1; if (!efidir_is_mac && grub_strcmp (fs->name, "fat") != 0) - grub_util_error (_("%s doesn't look like an EFI partition.\n"), efidir); + grub_util_error (_("%s doesn't look like an EFI partition"), efidir); /* The EFI specification requires that an EFI System Partition must contain an "EFI" subdirectory, and that OS loaders are stored in @@ -1271,7 +1271,7 @@ main (int argc, char *argv[]) if (!config.is_cryptodisk_enabled && have_cryptodisk) grub_util_error (_("attempt to install to encrypted disk without cryptodisk enabled. " - "Set `%s' in file `%s'."), "GRUB_ENABLE_CRYPTODISK=y", + "Set `%s' in file `%s'"), "GRUB_ENABLE_CRYPTODISK=y", grub_util_get_config_filename ()); if (disk_module && grub_strcmp (disk_module, "ata") == 0) diff --git a/util/grub-mknetdir.c b/util/grub-mknetdir.c index 8366a1121..3813e8bc0 100644 --- a/util/grub-mknetdir.c +++ b/util/grub-mknetdir.c @@ -140,7 +140,7 @@ process_input_dir (const char *input_dir, enum grub_install_plat platform) prefix = xasprintf ("/%s", subdir); if (!targets[platform].mkimage_target) - grub_util_error (_("unsupported platform %s\n"), platsub); + grub_util_error (_("unsupported platform %s"), platsub); grub_cfg = grub_util_path_concat (2, grubdir, "grub.cfg"); cfg = grub_util_fopen (grub_cfg, "wb"); diff --git a/util/grub-pe2elf.c b/util/grub-pe2elf.c index f4abf70a3..0d4084a10 100644 --- a/util/grub-pe2elf.c +++ b/util/grub-pe2elf.c @@ -279,7 +279,7 @@ write_reloc_section (FILE* fp, const char *name, char *image, break; #endif default: - grub_util_error ("unknown pe relocation type %d\n", pe_rel->type); + grub_util_error ("unknown pe relocation type %d", pe_rel->type); } if (type == diff --git a/util/mkimage.c b/util/mkimage.c index 52265b557..35df99871 100644 --- a/util/mkimage.c +++ b/util/mkimage.c @@ -823,7 +823,7 @@ compress_kernel (const struct grub_install_image_target_desc *image_target, char if (image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS && (comp != GRUB_COMPRESSION_NONE)) - grub_util_error (_("unknown compression %d\n"), comp); + grub_util_error (_("unknown compression %d"), comp); *core_img = xmalloc (kernel_size); memcpy (*core_img, kernel_img, kernel_size); @@ -1234,7 +1234,7 @@ grub_install_generate_image (const char *dir, const char *prefix, name = "none_decompress.img"; break; default: - grub_util_error (_("unknown compression %d\n"), comp); + grub_util_error (_("unknown compression %d"), comp); } decompress_path = grub_util_get_path (dir, name); From 5370dcfdae66b60cff3507ad925300a679fe4117 Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Thu, 14 May 2015 07:50:33 +0300 Subject: [PATCH 025/106] zfs: fix integer truncation in zap_lookup Size after shift could exceed 16 bits; use grub_unit32_t for result. Reported and tested by: Kostya Berger Closes: 44448 --- grub-core/fs/zfs/zfs.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index 08ed453a6..aac6f2876 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -2071,10 +2071,10 @@ dmu_read (dnode_end_t * dn, grub_uint64_t blkid, void **buf, */ static grub_err_t mzap_lookup (mzap_phys_t * zapobj, grub_zfs_endian_t endian, - grub_uint16_t objsize, const char *name, grub_uint64_t * value, + grub_uint32_t objsize, const char *name, grub_uint64_t * value, int case_insensitive) { - grub_uint16_t i, chunks; + grub_uint32_t i, chunks; mzap_ent_phys_t *mzap_ent = zapobj->mz_chunk; if (objsize < MZAP_ENT_LEN) @@ -2486,7 +2486,7 @@ zap_lookup (dnode_end_t * zap_dnode, const char *name, grub_uint64_t *val, struct grub_zfs_data *data, int case_insensitive) { grub_uint64_t block_type; - grub_uint16_t size; + grub_uint32_t size; void *zapbuf; grub_err_t err; grub_zfs_endian_t endian; @@ -2494,7 +2494,7 @@ zap_lookup (dnode_end_t * zap_dnode, const char *name, grub_uint64_t *val, grub_dprintf ("zfs", "looking for '%s'\n", name); /* Read in the first block of the zap object data. */ - size = grub_zfs_to_cpu16 (zap_dnode->dn.dn_datablkszsec, + size = (grub_uint32_t) grub_zfs_to_cpu16 (zap_dnode->dn.dn_datablkszsec, zap_dnode->endian) << SPA_MINBLOCKSHIFT; err = dmu_read (zap_dnode, 0, &zapbuf, &endian, data); if (err) From 2498dc7a3aee638215ad47899031496b50633d55 Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Sun, 17 May 2015 14:16:36 +0300 Subject: [PATCH 026/106] hostdisk: fix crash with NULL device.map grub-macbless calls grub_util_biosdisk_init with NULL device.map. --- grub-core/kern/emu/hostdisk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c index a3b00c8f6..610518d0c 100644 --- a/grub-core/kern/emu/hostdisk.c +++ b/grub-core/kern/emu/hostdisk.c @@ -422,7 +422,7 @@ read_device_map (const char *dev_map) char buf[1024]; /* XXX */ int lineno = 0; - if (dev_map[0] == '\0') + if (!dev_map || dev_map[0] == '\0') { grub_util_info ("no device.map"); return; From a666c8bd18aee7bf1b202b6b8c0ffe953bd2c1b6 Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Sun, 17 May 2015 22:38:30 +0300 Subject: [PATCH 027/106] bootp: ignore gateway_ip (relay) field. From RFC1542: The 'giaddr' field is rather poorly named. It exists to facilitate the transfer of BOOTREQUEST messages from a client, through BOOTP relay agents, to servers on different networks than the client. Similarly, it facilitates the delivery of BOOTREPLY messages from the servers, through BOOTP relay agents, back to the client. In no case does it represent a general IP router to be used by the client. A BOOTP client MUST set the 'giaddr' field to zero (0.0.0.0) in all BOOTREQUEST messages it generates. A BOOTP client MUST NOT interpret the 'giaddr' field of a BOOTREPLY message to be the IP address of an IP router. A BOOTP client SHOULD completely ignore the contents of the 'giaddr' field in BOOTREPLY messages. Leave code ifdef'd out for the time being in case we see regression. Suggested by: Rink Springer Closes: 43396 --- docs/grub.texi | 6 ++++-- grub-core/net/bootp.c | 7 +++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/grub.texi b/docs/grub.texi index 4af22aff8..88bd75f38 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -5162,8 +5162,10 @@ by @var{shortname} which can be used to remove it (@pxref{net_del_route}). Perform configuration of @var{card} using DHCP protocol. If no card name is specified, try to configure all existing cards. If configuration was successful, interface with name @var{card}@samp{:dhcp} and configured -address is added to @var{card}. If server provided gateway information in -DHCP ACK packet, it is added as route entry with the name @var{card}@samp{:dhcp:gw}. Additionally the following DHCP options are recognized and processed: +address is added to @var{card}. +@comment If server provided gateway information in +@comment DHCP ACK packet, it is added as route entry with the name @var{card}@samp{:dhcp:gw}. +Additionally the following DHCP options are recognized and processed: @table @samp @item 1 (Subnet Mask) diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c index 613675533..4fdeac3ef 100644 --- a/grub-core/net/bootp.c +++ b/grub-core/net/bootp.c @@ -157,6 +157,12 @@ grub_net_configure_by_dhcp_ack (const char *name, hwaddr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; inter = grub_net_add_addr (name, card, &addr, &hwaddr, flags); +#if 0 + /* This is likely based on misunderstanding. gateway_ip refers to + address of BOOTP relay and should not be used after BOOTP transaction + is complete. + See RFC1542, 3.4 Interpretation of the 'giaddr' field + */ if (bp->gateway_ip) { grub_net_network_level_netaddress_t target; @@ -178,6 +184,7 @@ grub_net_configure_by_dhcp_ack (const char *name, target.ipv4.masksize = 32; grub_net_add_route (name, target, inter); } +#endif if (size > OFFSET_OF (boot_file, bp)) grub_env_set_net_property (name, "boot_file", bp->boot_file, From f4e62af000116de93f0c9d1c5f8aaf40934d5a01 Mon Sep 17 00:00:00 2001 From: Paul Menzel Date: Fri, 15 May 2015 17:35:00 +0200 Subject: [PATCH 028/106] cb_timestamps.c: Add new time stamp descriptions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the descriptions of the “core”, that means no vendorcode or payload, coreboot time stamps added up to coreboot commit a7d92441 (timestamps: You can never have enough of them!) [1]. Running `coreboot_boottime` in the GRUB command line interface now shows descriptions for all time stamps again on the ASRock E350M1. [1] http://review.coreboot.org/9608 --- grub-core/commands/i386/coreboot/cb_timestamps.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/grub-core/commands/i386/coreboot/cb_timestamps.c b/grub-core/commands/i386/coreboot/cb_timestamps.c index 07fbb0283..e72f38d6e 100644 --- a/grub-core/commands/i386/coreboot/cb_timestamps.c +++ b/grub-core/commands/i386/coreboot/cb_timestamps.c @@ -39,9 +39,17 @@ static const char *descs[] = { [2] = "before RAM init", [3] = "after RAM init", [4] = "end of romstage", + [5] = "start of verified boot", + [6] = "end of verified boot", [8] = "start of RAM copy", [9] = "end of RAM copy", [10] = "start of ramstage", + [11] = "start of bootblock", + [12] = "end of bootblock", + [13] = "starting to load romstage", + [14] = "finished loading romstage", + [15] = "starting LZMA decompress (ignore for x86)", + [16] = "finished LZMA decompress (ignore for x86)", [30] = "device enumerate", [40] = "device configure", [50] = "device enable", From 5e74a3e6dfc4e5992c423bf740a4b3604030b007 Mon Sep 17 00:00:00 2001 From: Paul Menzel Date: Sun, 24 May 2015 11:11:25 +0200 Subject: [PATCH 029/106] disk/ahci: Use defines `GRUB_ATA_STATUS_BUSY` and `GRUB_ATA_STATUS_DRQ` Instead of hard coding `0x88` use the macros defined in `disk/ata.h`. --- grub-core/disk/ahci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c index d6bdbddf6..7f7572404 100644 --- a/grub-core/disk/ahci.c +++ b/grub-core/disk/ahci.c @@ -565,14 +565,14 @@ grub_ahci_pciinit (grub_pci_device_t dev, while (grub_get_time_ms () < endtime) { for (i = 0; i < nports; i++) - if (adevs[i] && (adevs[i]->hba->ports[adevs[i]->port].task_file_data & 0x88)) + if (adevs[i] && (adevs[i]->hba->ports[adevs[i]->port].task_file_data & (GRUB_ATA_STATUS_BUSY | GRUB_ATA_STATUS_DRQ))) break; if (i == nports) break; } for (i = 0; i < nports; i++) - if (adevs[i] && (adevs[i]->hba->ports[adevs[i]->port].task_file_data & 0x88)) + if (adevs[i] && (adevs[i]->hba->ports[adevs[i]->port].task_file_data & (GRUB_ATA_STATUS_BUSY | GRUB_ATA_STATUS_DRQ))) { grub_dprintf ("ahci", "port %d is busy\n", i); failed_adevs[i] = adevs[i]; From c856be6bca6f963a9a2c91eda954ab687bc7e573 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Wed, 27 May 2015 08:37:55 +0200 Subject: [PATCH 030/106] multiboot1: never place modules in low memory. While in theory permitted by the spec, modules rarely fit in low memory anyway and not every kernel is able to handle modules in low memory anyway. At least VMWare is known not to be able to handle modules at arbitrary locations. --- grub-core/loader/multiboot.c | 1 + 1 file changed, 1 insertion(+) diff --git a/grub-core/loader/multiboot.c b/grub-core/loader/multiboot.c index 4b71f3363..fd8f28e21 100644 --- a/grub-core/loader/multiboot.c +++ b/grub-core/loader/multiboot.c @@ -333,6 +333,7 @@ grub_cmd_module (grub_command_t cmd __attribute__ ((unused)), return grub_errno; #ifndef GRUB_USE_MULTIBOOT2 + lowest_addr = 0x100000; if (grub_multiboot_quirks & GRUB_MULTIBOOT_QUIRK_MODULES_AFTER_KERNEL) lowest_addr = ALIGN_UP (highest_load + 1048576, 4096); #endif From cad5cc0f5d3d3630ccfbe242552958b13f2120d6 Mon Sep 17 00:00:00 2001 From: Toomas Soome Date: Thu, 16 Apr 2015 08:24:38 +0300 Subject: [PATCH 031/106] zfs extensible_dataset and large_blocks feature support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit large blocks basically use extensible dataset feature, or to be exact, setting recordsize above 128k will trigger large_block feature to be enabled and storing such blocks is using feature extensible dataset. so the extensible dataset is prerequisite. Changes implement read support extensible dataset… instead of fixed DMU types they dont specify type, making it possible to use fat zap objects from bonus area. --- grub-core/fs/zfs/zfs.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index aac6f2876..f9ca0e75e 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -283,6 +283,8 @@ static const char *spa_feature_names[] = { "org.illumos:lz4_compress", "com.delphix:hole_birth", "com.delphix:embedded_data", + "com.delphix:extensible_dataset", + "org.open-zfs:large_blocks", NULL }; @@ -3080,7 +3082,7 @@ get_filesystem_dnode (dnode_end_t * mosmdn, char *fsname, grub_dprintf ("zfs", "alive\n"); - err = dnode_get (mosmdn, objnum, DMU_OT_DSL_DIR, mdn, data); + err = dnode_get (mosmdn, objnum, 0, mdn, data); if (err) return err; @@ -3113,7 +3115,7 @@ get_filesystem_dnode (dnode_end_t * mosmdn, char *fsname, if (err) return err; - err = dnode_get (mosmdn, objnum, DMU_OT_DSL_DIR, mdn, data); + err = dnode_get (mosmdn, objnum, 0, mdn, data); if (err) return err; @@ -3268,8 +3270,7 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, grub_dprintf ("zfs", "endian = %d\n", subvol->mdn.endian); - err = dnode_get (&(data->mos), headobj, DMU_OT_DSL_DATASET, &subvol->mdn, - data); + err = dnode_get (&(data->mos), headobj, 0, &subvol->mdn, data); if (err) { grub_free (fsname); @@ -3665,8 +3666,11 @@ zfs_mount (grub_device_t dev) if (ub->ub_version >= SPA_VERSION_FEATURES && check_mos_features(&((objset_phys_t *) osp)->os_meta_dnode,ub_endian, data) != 0) - return NULL; - + { + grub_error (GRUB_ERR_BAD_FS, "Unsupported features in pool"); + return NULL; + } + /* Got the MOS. Save it at the memory addr MOS. */ grub_memmove (&(data->mos.dn), &((objset_phys_t *) osp)->os_meta_dnode, DNODE_SIZE); @@ -3963,7 +3967,7 @@ fill_fs_info (struct grub_dirhook_info *info, { headobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&mdn.dn))->dd_head_dataset_obj, mdn.endian); - err = dnode_get (&(data->mos), headobj, DMU_OT_DSL_DATASET, &mdn, data); + err = dnode_get (&(data->mos), headobj, 0, &mdn, data); if (err) { grub_dprintf ("zfs", "failed here\n"); From fd73b3d00881abae3daf820fe0009434edf2e3d4 Mon Sep 17 00:00:00 2001 From: Paul Menzel Date: Sun, 24 May 2015 23:27:46 +0200 Subject: [PATCH 032/106] Correct spelling of *scheduled* Run the command below $ git grep -l schedulded | xargs sed -i 's/schedulded/scheduled/g' and revert the change in `ChangeLog-2015`. Including "miscellaneous" spelling fix noted by richardvoigt@gmail.com --- gentpl.py | 2 +- grub-core/disk/ahci.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gentpl.py b/gentpl.py index f177883f8..37b1f45bf 100644 --- a/gentpl.py +++ b/gentpl.py @@ -82,7 +82,7 @@ GROUPS["softdiv"] = GROUPS["arm"] + ["ia64_efi"] GROUPS["no_softdiv"] = GRUB_PLATFORMS[:] for i in GROUPS["softdiv"]: GROUPS["no_softdiv"].remove(i) -# Miscelaneous groups schedulded to disappear in future +# Miscellaneous groups scheduled to disappear in future GROUPS["i386_coreboot_multiboot_qemu"] = ["i386_coreboot", "i386_multiboot", "i386_qemu"] GROUPS["nopc"] = GRUB_PLATFORMS[:]; GROUPS["nopc"].remove("i386_pc") diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c index 7f7572404..4e8619ce3 100644 --- a/grub-core/disk/ahci.c +++ b/grub-core/disk/ahci.c @@ -1002,7 +1002,7 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev, if (parms->write) grub_memcpy ((char *) grub_dma_get_virt (bufc), parms->buffer, parms->size); - grub_dprintf ("ahci", "AHCI command schedulded\n"); + grub_dprintf ("ahci", "AHCI command scheduled\n"); grub_dprintf ("ahci", "AHCI tfd = %x\n", dev->hba->ports[dev->port].task_file_data); grub_dprintf ("ahci", "AHCI inten = %x\n", From dec7718878f8a4566cd2894ab8970e1bec19dbb9 Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Sat, 30 May 2015 19:36:41 +0300 Subject: [PATCH 033/106] Clarify use of superusers variable and menu entry access superusers controls both CLI and editing. Also explicitly mention that empty superusers disables them. "Access to menuentry" is a bit vague - change to "execute menuentry" to make it obvious, what access is granted. --- docs/grub.texi | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/grub.texi b/docs/grub.texi index 88bd75f38..b9f41a73e 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -5428,10 +5428,12 @@ In order to enable authentication support, the @samp{superusers} environment variable must be set to a list of usernames, separated by any of spaces, commas, semicolons, pipes, or ampersands. Superusers are permitted to use the GRUB command line, edit menu entries, and execute any menu entry. If -@samp{superusers} is set, then use of the command line is automatically -restricted to superusers. +@samp{superusers} is set, then use of the command line and editing of menu +entries are automatically restricted to superusers. Setting @samp{superusers} +to empty string effectively disables both access to CLI and editing of menu +entries. -Other users may be given access to specific menu entries by giving a list of +Other users may be allowed to execute specific menu entries by giving a list of usernames (as above) using the @option{--users} option to the @samp{menuentry} command (@pxref{menuentry}). If the @option{--unrestricted} option is used for a menu entry, then that entry is unrestricted. From ca59c24bd0e2a90db764065e24829775aa2b363c Mon Sep 17 00:00:00 2001 From: Paul Menzel Date: Wed, 27 May 2015 22:48:57 +0200 Subject: [PATCH 034/106] disk/ahci.c: Add port number to port debug messages Currently, some messages cannot be mapped to the port they belong to as the port number is missing from the output. So add `port: n` to the debug messages. --- grub-core/disk/ahci.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c index 4e8619ce3..da5fead26 100644 --- a/grub-core/disk/ahci.c +++ b/grub-core/disk/ahci.c @@ -355,7 +355,7 @@ grub_ahci_pciinit (grub_pci_device_t dev, if (adevs[i]) { adevs[i]->hba->ports[adevs[i]->port].sata_error = adevs[i]->hba->ports[adevs[i]->port].sata_error; - grub_dprintf ("ahci", "err: %x\n", + grub_dprintf ("ahci", "port: %d, err: %x\n", adevs[i]->port, adevs[i]->hba->ports[adevs[i]->port].sata_error); adevs[i]->command_list_chunk = grub_memalign_dma32 (1024, sizeof (struct grub_ahci_cmd_head) * 32); @@ -440,7 +440,7 @@ grub_ahci_pciinit (grub_pci_device_t dev, adevs[i]->hba->ports[adevs[i]->port].intstatus = ~0; // adevs[i]->hba->ports[adevs[i]->port].fbs = 0; - grub_dprintf ("ahci", "err: %x\n", + grub_dprintf ("ahci", "port: %d, err: %x\n", adevs[i]->port, adevs[i]->hba->ports[adevs[i]->port].sata_error); adevs[i]->rfis = grub_memalign_dma32 (4096, @@ -480,7 +480,7 @@ grub_ahci_pciinit (grub_pci_device_t dev, for (i = 0; i < nports; i++) if (adevs[i]) { - grub_dprintf ("ahci", "err: %x\n", + grub_dprintf ("ahci", "port: %d, err: %x\n", adevs[i]->port, adevs[i]->hba->ports[adevs[i]->port].sata_error); fr_running |= (1 << i); @@ -488,7 +488,7 @@ grub_ahci_pciinit (grub_pci_device_t dev, adevs[i]->hba->ports[adevs[i]->port].command |= GRUB_AHCI_HBA_PORT_CMD_POWER_ON; adevs[i]->hba->ports[adevs[i]->port].command |= 1 << 28; - grub_dprintf ("ahci", "err: %x\n", + grub_dprintf ("ahci", "port: %d, err: %x\n", adevs[i]->port, adevs[i]->hba->ports[adevs[i]->port].sata_error); } @@ -515,26 +515,26 @@ grub_ahci_pciinit (grub_pci_device_t dev, for (i = 0; i < nports; i++) if (adevs[i]) { - grub_dprintf ("ahci", "err: %x\n", + grub_dprintf ("ahci", "port %d, err: %x\n", adevs[i]->port, adevs[i]->hba->ports[adevs[i]->port].sata_error); adevs[i]->hba->ports[adevs[i]->port].command |= GRUB_AHCI_HBA_PORT_CMD_POWER_ON; adevs[i]->hba->ports[adevs[i]->port].command |= GRUB_AHCI_HBA_PORT_CMD_SPIN_UP; - grub_dprintf ("ahci", "err: %x\n", + grub_dprintf ("ahci", "port %d, err: %x\n", adevs[i]->port, adevs[i]->hba->ports[adevs[i]->port].sata_error); adevs[i]->hba->ports[adevs[i]->port].sata_error = ~0; - grub_dprintf ("ahci", "err: %x\n", + grub_dprintf ("ahci", "port %d, err: %x\n", adevs[i]->port, adevs[i]->hba->ports[adevs[i]->port].sata_error); - grub_dprintf ("ahci", "offset: %x, tfd:%x, CMD: %x\n", + grub_dprintf ("ahci", "port %d, offset: %x, tfd:%x, CMD: %x\n", adevs[i]->port, (int) ((char *) &adevs[i]->hba->ports[adevs[i]->port].task_file_data - (char *) adevs[i]->hba), adevs[i]->hba->ports[adevs[i]->port].task_file_data, adevs[i]->hba->ports[adevs[i]->port].command); - grub_dprintf ("ahci", "err: %x\n", + grub_dprintf ("ahci", "port %d, err: %x\n", adevs[i]->port, adevs[i]->hba->ports[adevs[i]->port].sata_error); } @@ -542,13 +542,13 @@ grub_ahci_pciinit (grub_pci_device_t dev, for (i = 0; i < nports; i++) if (adevs[i]) { - grub_dprintf ("ahci", "offset: %x, tfd:%x, CMD: %x\n", + grub_dprintf ("ahci", "port %d, offset: %x, tfd:%x, CMD: %x\n", adevs[i]->port, (int) ((char *) &adevs[i]->hba->ports[adevs[i]->port].task_file_data - (char *) adevs[i]->hba), adevs[i]->hba->ports[adevs[i]->port].task_file_data, adevs[i]->hba->ports[adevs[i]->port].command); - grub_dprintf ("ahci", "err: %x\n", + grub_dprintf ("ahci", "port: %d, err: %x\n", adevs[i]->port, adevs[i]->hba->ports[adevs[i]->port].sata_error); adevs[i]->hba->ports[adevs[i]->port].command From 3ac342205dc81293bb8e2d91b8c5ebe124b4ad35 Mon Sep 17 00:00:00 2001 From: dann frazier Date: Thu, 21 May 2015 10:28:48 -0600 Subject: [PATCH 035/106] arm64/setjmp: Add missing license macro Including the setjmp module in an arm64-efi image will cause it to immediately exit with an "incompatible license" error. The source file includes a GPLv3+ boilerplate, so fix this by declaring a GPLv3+ license using the GRUB_MOD_LICENSE macro. Signed-off-by: dann frazier --- grub-core/lib/arm64/setjmp.S | 2 ++ 1 file changed, 2 insertions(+) diff --git a/grub-core/lib/arm64/setjmp.S b/grub-core/lib/arm64/setjmp.S index adaafe40f..eabfd99b2 100644 --- a/grub-core/lib/arm64/setjmp.S +++ b/grub-core/lib/arm64/setjmp.S @@ -17,8 +17,10 @@ */ #include +#include .file "setjmp.S" +GRUB_MOD_LICENSE "GPLv3+" .text /* From 43d4231432838821cabe4f6aea4f0f50e87af9c4 Mon Sep 17 00:00:00 2001 From: Leif Lindholm Date: Tue, 2 Jun 2015 15:41:09 +0100 Subject: [PATCH 036/106] configure.ac: clean up arm64 soft-float handling Fix compilation with gcc 5.1 (avoid internal compiler error), by replacing explicit -march +nofp+nosimd options with -mgeneral-regs-only. This also enables the removal of some further conditional build flag setting. --- configure.ac | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/configure.ac b/configure.ac index 891c14ff3..fd8a62ead 100644 --- a/configure.ac +++ b/configure.ac @@ -686,9 +686,9 @@ if test x"$platform" != xemu ; then AC_CACHE_CHECK([for options to get soft-float], grub_cv_target_cc_soft_float, [ grub_cv_target_cc_soft_float=no if test "x$target_cpu" = xarm64; then - CFLAGS="$TARGET_CFLAGS -march=armv8-a+nofp+nosimd -Werror" + CFLAGS="$TARGET_CFLAGS -mgeneral-regs-only -Werror" AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], - [grub_cv_target_cc_soft_float="-march=armv8-a+nofp+nosimd"], []) + [grub_cv_target_cc_soft_float="-mgeneral-regs-only"], []) fi if test "x$target_cpu" = xia64; then CFLAGS="$TARGET_CFLAGS -mno-inline-float-divide -mno-inline-sqrt -Werror" @@ -720,15 +720,7 @@ if test x"$platform" != xemu ; then TARGET_CFLAGS="$TARGET_CFLAGS $grub_cv_target_cc_soft_float" ;; esac - case x"$grub_cv_target_cc_soft_float" in - x"-march=armv8-a+nofp+nosimd") - # +nosimd disables also the cache opcodes that we need in asm. - TARGET_CCASFLAGS="$TARGET_CCASFLAGS -march=armv8-a+nofp" - ;; - *) - TARGET_CCASFLAGS="$TARGET_CCASFLAGS $grub_cv_target_cc_soft_float" - ;; - esac + TARGET_CCASFLAGS="$TARGET_CCASFLAGS $grub_cv_target_cc_soft_float" fi From 697eceff6a168e8712fb7b784b333e0aeb925958 Mon Sep 17 00:00:00 2001 From: Toomas Soome Date: Thu, 4 Jun 2015 19:41:54 +0300 Subject: [PATCH 037/106] multiboot_header_tag_module_align fix to confirm multiboot specification --- include/multiboot2.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/multiboot2.h b/include/multiboot2.h index 3ccff15fc..9d4862759 100644 --- a/include/multiboot2.h +++ b/include/multiboot2.h @@ -156,9 +156,6 @@ struct multiboot_header_tag_module_align multiboot_uint16_t type; multiboot_uint16_t flags; multiboot_uint32_t size; - multiboot_uint32_t width; - multiboot_uint32_t height; - multiboot_uint32_t depth; }; struct multiboot_color From d3ffeb9a9a54148af610cd122028783217d30699 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 1 Jun 2015 14:28:45 +0200 Subject: [PATCH 038/106] xfs: Add helpers for inode size Add helpers to return size of XFS inode on disk and when loaded in memory. Signed-off-by: Jan Kara --- grub-core/fs/xfs.c | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c index 0d704e9a4..26d8147a9 100644 --- a/grub-core/fs/xfs.c +++ b/grub-core/fs/xfs.c @@ -255,6 +255,24 @@ grub_xfs_inode_offset (struct grub_xfs_data *data, data->sblock.log2_inode); } +static inline grub_size_t +grub_xfs_inode_size(struct grub_xfs_data *data) +{ + return 1 << data->sblock.log2_inode; +} + +/* + * Returns size occupied by XFS inode stored in memory - we store struct + * grub_fshelp_node there but on disk inode size may be actually larger than + * struct grub_xfs_inode so we need to account for that so that we can read + * from disk directly into in-memory structure. + */ +static inline grub_size_t +grub_xfs_fshelp_size(struct grub_xfs_data *data) +{ + return sizeof (struct grub_fshelp_node) - sizeof (struct grub_xfs_inode) + + grub_xfs_inode_size(data); +} static grub_err_t grub_xfs_read_inode (struct grub_xfs_data *data, grub_uint64_t ino, @@ -264,8 +282,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 +315,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)); @@ -456,9 +474,7 @@ static int iterate_dir_call_hook (grub_uint64_t ino, const char *filename, struct grub_fshelp_node *fdiro; grub_err_t err; - fdiro = grub_malloc (sizeof (struct grub_fshelp_node) - - sizeof (struct grub_xfs_inode) - + (1 << ctx->diro->data->sblock.log2_inode) + 1); + fdiro = grub_malloc (grub_xfs_fshelp_size(ctx->diro->data) + 1); if (!fdiro) { grub_print_error (); @@ -682,7 +698,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; @@ -797,10 +813,7 @@ grub_xfs_open (struct grub_file *file, const char *name) if (fdiro != &data->diropen) { - grub_memcpy (&data->diropen, fdiro, - sizeof (struct grub_fshelp_node) - - sizeof (struct grub_xfs_inode) - + (1 << data->sblock.log2_inode)); + grub_memcpy (&data->diropen, fdiro, grub_xfs_fshelp_size(data)); grub_free (fdiro); } From b6e80c7778b708c1632d957d00507aad60d9e255 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 1 Jun 2015 14:28:46 +0200 Subject: [PATCH 039/106] xfs: V5 filesystem format support Add support for new XFS on disk format. We have to handle optional filetype fields in directory entries, additional CRC, LSN, UUID entries in some structures, etc. Signed-off-by: Jan Kara --- grub-core/fs/xfs.c | 332 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 252 insertions(+), 80 deletions(-) diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c index 26d8147a9..f00e43e7d 100644 --- a/grub-core/fs/xfs.c +++ b/grub-core/fs/xfs.c @@ -34,6 +34,50 @@ 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_ATTRBIT 0x0010 +#define XFS_SB_VERSION_NLINKBIT 0x0020 +#define XFS_SB_VERSION_QUOTABIT 0x0040 +#define XFS_SB_VERSION_ALIGNBIT 0x0080 +#define XFS_SB_VERSION_DALIGNBIT 0x0100 +#define XFS_SB_VERSION_LOGV2BIT 0x0400 +#define XFS_SB_VERSION_SECTORBIT 0x0800 +#define XFS_SB_VERSION_EXTFLGBIT 0x1000 +#define XFS_SB_VERSION_DIRV2BIT 0x2000 +#define XFS_SB_VERSION_MOREBITSBIT 0x8000 +#define XFS_SB_VERSION_BITS_SUPPORTED \ + (XFS_SB_VERSION_NUMBITS | \ + XFS_SB_VERSION_ATTRBIT | \ + XFS_SB_VERSION_NLINKBIT | \ + XFS_SB_VERSION_QUOTABIT | \ + XFS_SB_VERSION_ALIGNBIT | \ + XFS_SB_VERSION_DALIGNBIT | \ + XFS_SB_VERSION_LOGV2BIT | \ + XFS_SB_VERSION_SECTORBIT | \ + XFS_SB_VERSION_EXTFLGBIT | \ + XFS_SB_VERSION_DIRV2BIT | \ + XFS_SB_VERSION_MOREBITSBIT) + +/* Recognized xfs format versions */ +#define XFS_SB_VERSION_4 4 /* Good old XFS filesystem */ +#define XFS_SB_VERSION_5 5 /* CRC enabled filesystem */ + +/* features2 field flags */ +#define XFS_SB_VERSION2_LAZYSBCOUNTBIT 0x00000002 /* Superblk counters */ +#define XFS_SB_VERSION2_ATTR2BIT 0x00000008 /* Inline attr rework */ +#define XFS_SB_VERSION2_PROJID32BIT 0x00000080 /* 32-bit project ids */ +#define XFS_SB_VERSION2_FTYPE 0x00000200 /* inode type in dir */ +#define XFS_SB_VERSION2_BITS_SUPPORTED \ + (XFS_SB_VERSION2_LAZYSBCOUNTBIT | \ + XFS_SB_VERSION2_ATTR2BIT | \ + XFS_SB_VERSION2_PROJID32BIT | \ + XFS_SB_VERSION2_FTYPE) + +/* incompat feature flags */ +#define XFS_SB_FEAT_INCOMPAT_FTYPE (1 << 0) /* filetype in dirent */ +#define XFS_SB_FEAT_INCOMPAT_SUPPORTED \ + (XFS_SB_FEAT_INCOMPAT_FTYPE) struct grub_xfs_sblock { @@ -45,7 +89,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 +100,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 +120,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 +145,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,19 +179,11 @@ 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; +#define XFS_V2_INODE_SIZE sizeof(struct grub_xfs_inode) +#define XFS_V3_INODE_SIZE (XFS_V2_INODE_SIZE + 76) + struct grub_xfs_dirblock_tail { grub_uint32_t leaf_count; @@ -157,6 +205,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 +214,71 @@ static grub_dl_t my_mod; +static int grub_xfs_sb_hascrc(struct grub_xfs_data *data) +{ + return (data->sblock.version & grub_cpu_to_be16_compile_time(XFS_SB_VERSION_NUMBITS)) == + grub_cpu_to_be16_compile_time(XFS_SB_VERSION_5); +} + +static int grub_xfs_sb_hasftype(struct grub_xfs_data *data) +{ + if ((data->sblock.version & grub_cpu_to_be16_compile_time(XFS_SB_VERSION_NUMBITS)) == + grub_cpu_to_be16_compile_time(XFS_SB_VERSION_5) && + data->sblock.sb_features_incompat & grub_cpu_to_be32_compile_time(XFS_SB_FEAT_INCOMPAT_FTYPE)) + return 1; + if (data->sblock.version & grub_cpu_to_be16_compile_time(XFS_SB_VERSION_MOREBITSBIT) && + data->sblock.features2 & grub_cpu_to_be32_compile_time(XFS_SB_VERSION2_FTYPE)) + return 1; + return 0; +} + +static int grub_xfs_sb_valid(struct grub_xfs_data *data) +{ + grub_dprintf("xfs", "Validating superblock\n"); + if (grub_strncmp ((char *) (data->sblock.magic), "XFSB", 4) + || data->sblock.log2_bsize < GRUB_DISK_SECTOR_BITS + || ((int) data->sblock.log2_bsize + + (int) data->sblock.log2_dirblk) >= 27) + { + grub_error (GRUB_ERR_BAD_FS, "not a XFS filesystem"); + return 0; + } + if ((data->sblock.version & grub_cpu_to_be16_compile_time(XFS_SB_VERSION_NUMBITS)) == + grub_cpu_to_be16_compile_time(XFS_SB_VERSION_5)) + { + grub_dprintf("xfs", "XFS v5 superblock detected\n"); + if (data->sblock.sb_features_incompat & + grub_cpu_to_be32_compile_time(~XFS_SB_FEAT_INCOMPAT_SUPPORTED)) + { + grub_error (GRUB_ERR_BAD_FS, "XFS filesystem has unsupported " + "incompatible features"); + return 0; + } + return 1; + } + else if ((data->sblock.version & grub_cpu_to_be16_compile_time(XFS_SB_VERSION_NUMBITS)) == + grub_cpu_to_be16_compile_time(XFS_SB_VERSION_4)) + { + grub_dprintf("xfs", "XFS v4 superblock detected\n"); + if (!(data->sblock.version & grub_cpu_to_be16_compile_time(XFS_SB_VERSION_DIRV2BIT))) + { + grub_error (GRUB_ERR_BAD_FS, "XFS filesystem without V2 directories " + "is unsupported"); + return 0; + } + if (data->sblock.version & grub_cpu_to_be16_compile_time(~XFS_SB_VERSION_BITS_SUPPORTED) || + (data->sblock.version & grub_cpu_to_be16_compile_time(XFS_SB_VERSION_MOREBITSBIT) && + data->sblock.features2 & grub_cpu_to_be16_compile_time(~XFS_SB_VERSION2_BITS_SUPPORTED))) + { + grub_error (GRUB_ERR_BAD_FS, "XFS filesystem has unsupported version " + "bits"); + return 0; + } + return 1; + } + return 0; +} + /* Filetype information as used in inodes. */ #define FILETYPE_INO_MASK 0170000 #define FILETYPE_INO_REG 0100000 @@ -219,18 +334,6 @@ GRUB_XFS_EXTENT_SIZE (grub_xfs_extent *exts, int ex) 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, @@ -274,6 +377,85 @@ grub_xfs_fshelp_size(struct grub_xfs_data *data) + grub_xfs_inode_size(data); } +static void * +grub_xfs_inode_data(struct grub_xfs_inode *inode) +{ + if (inode->version <= 2) + return ((char *)inode) + XFS_V2_INODE_SIZE; + return ((char *)inode) + XFS_V3_INODE_SIZE; +} + +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 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) + ALIGN_UP(size, 8)); +} + +static grub_uint64_t * +grub_xfs_btree_keys(struct grub_xfs_data *data, + struct grub_xfs_btree_node *leaf) +{ + grub_uint64_t *keys = (grub_uint64_t *)(leaf + 1); + + if (data->hascrc) + keys += 6; /* skip crc, uuid, ... */ + return keys; +} + static grub_err_t grub_xfs_read_inode (struct grub_xfs_data *data, grub_uint64_t ino, struct grub_xfs_inode *inode) @@ -281,6 +463,8 @@ grub_xfs_read_inode (struct grub_xfs_data *data, grub_uint64_t ino, grub_uint64_t block = grub_xfs_inode_block (data, ino); int offset = grub_xfs_inode_offset (data, ino); + grub_dprintf("xfs", "Reading inode (%"PRIuGRUB_UINT64_T") - %"PRIuGRUB_UINT64_T", %d\n", + ino, block, offset); /* Read the inode. */ if (grub_disk_read (data->disk, block, offset, grub_xfs_inode_size(data), inode)) @@ -303,6 +487,7 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) if (node->inode.format == XFS_INODE_FORMAT_BTREE) { + struct grub_xfs_btree_root *root; const grub_uint64_t *keys; int recoffset; @@ -310,15 +495,15 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) 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; @@ -340,7 +525,10 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) 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"); @@ -348,8 +536,8 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) } 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))); } @@ -359,7 +547,7 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) 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 { @@ -417,7 +605,7 @@ grub_xfs_read_symlink (grub_fshelp_node_t 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: { @@ -512,23 +700,18 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, { 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)) @@ -537,12 +720,10 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, 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. */ @@ -567,10 +748,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, 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; } @@ -597,15 +775,11 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, >> 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, @@ -617,13 +791,11 @@ 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 < 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) @@ -631,14 +803,16 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, 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), @@ -655,8 +829,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, 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); @@ -681,19 +854,14 @@ 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)) goto fail; - if (grub_strncmp ((char *) (data->sblock.magic), "XFSB", 4) - || data->sblock.log2_bsize < GRUB_DISK_SECTOR_BITS - || ((int) data->sblock.log2_bsize - + (int) data->sblock.log2_dirblk) >= 27) - { - grub_error (GRUB_ERR_BAD_FS, "not a XFS filesystem"); - goto fail; - } + if (!grub_xfs_sb_valid(data)) + goto fail; data = grub_realloc (data, sizeof (struct grub_xfs_data) @@ -708,9 +876,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 %"PRIuGRUB_UINT64_T"\n", + grub_cpu_to_be64(data->sblock.rootino)); grub_xfs_read_inode (data, data->diropen.ino, &data->diropen.inode); From df2aaf94b8d76b1ff7479ad5dc990f3efa30e419 Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Fri, 12 Jun 2015 09:40:00 +0300 Subject: [PATCH 040/106] NEWS: XFS v5 support --- NEWS | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS b/NEWS index e417ebad1..ad572ffe1 100644 --- a/NEWS +++ b/NEWS @@ -17,6 +17,7 @@ New in 2.02: files. * ZFS features support. * ZFS LZ4 support. + * XFS V5 format support. * New/improved terminal and video support: * Monochrome text (matching `hercules' in GRUB Legacy). From f4b1b48a837a034748a103adc7e9fd719a39ce42 Mon Sep 17 00:00:00 2001 From: Paul Menzel Date: Thu, 28 May 2015 19:14:19 +0200 Subject: [PATCH 041/106] disk/ahci.c: Use defines `GRUB_AHCI_HBA_PORT_CMD_SPIN_UP` and `GRUB_AHCI_HBA_PORT_CMD_POWER_ON` Instead of hard coding `2` and `4` use the macros defined already at the top of the file. As a consequence, wrap the now too long line. --- grub-core/disk/ahci.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c index da5fead26..f4725e8c1 100644 --- a/grub-core/disk/ahci.c +++ b/grub-core/disk/ahci.c @@ -552,7 +552,9 @@ grub_ahci_pciinit (grub_pci_device_t dev, adevs[i]->hba->ports[adevs[i]->port].sata_error); adevs[i]->hba->ports[adevs[i]->port].command - = (adevs[i]->hba->ports[adevs[i]->port].command & 0x0fffffff) | (1 << 28) | 2 | 4; + = (adevs[i]->hba->ports[adevs[i]->port].command & 0x0fffffff) | (1 << 28) + | GRUB_AHCI_HBA_PORT_CMD_SPIN_UP + | GRUB_AHCI_HBA_PORT_CMD_POWER_ON; /* struct grub_disk_ata_pass_through_parms parms2; grub_memset (&parms2, 0, sizeof (parms2)); From c945ca75c3b2b900040b905323b1226cb60a1166 Mon Sep 17 00:00:00 2001 From: Mark Salter Date: Fri, 15 Aug 2014 12:22:43 -0400 Subject: [PATCH 042/106] Fix exit to EFI firmware The current code for EFI grub_exit() calls grub_efi_fini() before returning to firmware. In the case of ARM, this leaves a timer event running which could lead to a firmware crash. This patch changes this so that grub_machine_fini() is called with a NORETURN flag. This allows machine-specific shutdown to happen as well as the shutdown done by grub_efi_fini(). Signed-off-by: Mark Salter --- grub-core/kern/arm/efi/init.c | 2 +- grub-core/kern/efi/efi.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/grub-core/kern/arm/efi/init.c b/grub-core/kern/arm/efi/init.c index a6ae03475..2572ca8b7 100644 --- a/grub-core/kern/arm/efi/init.c +++ b/grub-core/kern/arm/efi/init.c @@ -67,7 +67,7 @@ grub_machine_fini (int flags) b = grub_efi_system_table->boot_services; - efi_call_3 (b->set_timer, tmr_evt, GRUB_EFI_TIMER_PERIODIC, 0); + efi_call_3 (b->set_timer, tmr_evt, GRUB_EFI_TIMER_CANCEL, 0); efi_call_1 (b->close_event, tmr_evt); grub_efi_fini (); diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c index 49a150133..2e7783468 100644 --- a/grub-core/kern/efi/efi.c +++ b/grub-core/kern/efi/efi.c @@ -27,6 +27,7 @@ #include #include #include +#include /* The handle of GRUB itself. Filled in by the startup code. */ grub_efi_handle_t grub_efi_image_handle; @@ -156,7 +157,7 @@ grub_efi_get_loaded_image (grub_efi_handle_t image_handle) void grub_exit (void) { - grub_efi_fini (); + grub_machine_fini (GRUB_LOADER_FLAG_NORETURN); efi_call_4 (grub_efi_system_table->boot_services->exit, grub_efi_image_handle, GRUB_EFI_SUCCESS, 0, 0); for (;;) ; From afd0f21b2027310fda52b00ac1b964041d39a363 Mon Sep 17 00:00:00 2001 From: Paulo Flabiano Smorigo Date: Mon, 15 Jun 2015 09:10:19 -0300 Subject: [PATCH 043/106] Add flag for powerpc ieee1275 to avoid unneeded optimizations --- conf/Makefile.common | 3 +++ 1 file changed, 3 insertions(+) diff --git a/conf/Makefile.common b/conf/Makefile.common index 96e58c9a4..fcb8d2e1c 100644 --- a/conf/Makefile.common +++ b/conf/Makefile.common @@ -17,6 +17,9 @@ endif if COND_arm64 CFLAGS_PLATFORM += -mcmodel=large endif +if COND_powerpc_ieee1275 + CFLAGS_PLATFORM += -mcpu=powerpc +endif #FIXME: discover and check XEN headers CPPFLAGS_XEN = -I/usr/include From b27af387ea56123bfb101f2129490fa2df704d22 Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Tue, 16 Jun 2015 19:49:32 +0300 Subject: [PATCH 044/106] NEWS: mention libgcc removal --- NEWS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS b/NEWS index ad572ffe1..6e33909de 100644 --- a/NEWS +++ b/NEWS @@ -146,6 +146,9 @@ New in 2.02: Python 2.6. * modinfo.sh contains build information now. * Added many new tests to improve robustness. + * Target is built without libgcc now. Necessary builtins are reimplemented + directly. This removes requirement for target-specific runtime on build + system. * Revision control moved to git. From f348aee7b33dd85e7da62b497a96a7319a0bf9dd Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Tue, 16 Jun 2015 19:52:45 +0300 Subject: [PATCH 045/106] efinet: enable hardware filters when opening interface Exclusive open on SNP will close all existing protocol instances which may disable all receive filters on interface. Reinstall them after we opened protocol exclusively. Also follow UEFI specification recommendation and stop interfaces when closing them: Unexpected system errors, reboots and hangs can occur if an OS is loaded and the network devices are not Shutdown() and Stopped(). Also by: Mark Salter Closes: 45204 --- grub-core/net/drivers/efi/efinet.c | 25 +++++++++++++++++++++++++ include/grub/efi/api.h | 20 +++++++++++++++++--- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c index 5533515fd..70b26af94 100644 --- a/grub-core/net/drivers/efi/efinet.c +++ b/grub-core/net/drivers/efi/efinet.c @@ -168,6 +168,29 @@ open_card (struct grub_net_card *dev) return grub_error (GRUB_ERR_NET_NO_CARD, "%s: net initialize failed", dev->name); + /* Enable hardware receive filters if driver declares support for it. + We need unicast and broadcast and additionaly all nodes and + solicited multicast for IPv6. Solicited multicast is per-IPv6 + address and we currently do not have API to do it so simply + try to enable receive of all multicast packets or evertyhing in + the worst case (i386 PXE driver always enables promiscuous too). + + This does trust firmware to do what it claims to do. + */ + if (net->mode->receive_filter_mask) + { + grub_uint32_t filters = GRUB_EFI_SIMPLE_NETWORK_RECEIVE_UNICAST | + GRUB_EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST | + GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST; + + filters &= net->mode->receive_filter_mask; + if (!(filters & GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST)) + filters |= (net->mode->receive_filter_mask & + GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS); + + efi_call_6 (net->receive_filters, net, filters, 0, 0, 0, NULL); + } + efi_call_4 (grub_efi_system_table->boot_services->close_protocol, dev->efi_net, &net_io_guid, grub_efi_image_handle, dev->efi_handle); @@ -181,6 +204,8 @@ open_card (struct grub_net_card *dev) static void close_card (struct grub_net_card *dev) { + efi_call_1 (dev->efi_net->shutdown, dev->efi_net); + efi_call_1 (dev->efi_net->stop, dev->efi_net); efi_call_4 (grub_efi_system_table->boot_services->close_protocol, dev->efi_net, &net_io_guid, grub_efi_image_handle, dev->efi_handle); diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h index e5dd543a8..1a5e38c1e 100644 --- a/include/grub/efi/api.h +++ b/include/grub/efi/api.h @@ -1501,17 +1501,31 @@ enum GRUB_EFI_NETWORK_INITIALIZED, }; +enum + { + GRUB_EFI_SIMPLE_NETWORK_RECEIVE_UNICAST = 0x01, + GRUB_EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST = 0x02, + GRUB_EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST = 0x04, + GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS = 0x08, + GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST = 0x10, + }; + struct grub_efi_simple_network { grub_uint64_t revision; grub_efi_status_t (*start) (struct grub_efi_simple_network *this); - void (*stop) (void); + grub_efi_status_t (*stop) (struct grub_efi_simple_network *this); grub_efi_status_t (*initialize) (struct grub_efi_simple_network *this, grub_efi_uintn_t extra_rx, grub_efi_uintn_t extra_tx); void (*reset) (void); - void (*shutdown) (void); - void (*receive_filters) (void); + grub_efi_status_t (*shutdown) (struct grub_efi_simple_network *this); + grub_efi_status_t (*receive_filters) (struct grub_efi_simple_network *this, + grub_uint32_t enable, + grub_uint32_t disable, + grub_efi_boolean_t reset_mcast_filter, + grub_efi_uintn_t mcast_filter_count, + grub_efi_mac_address_t *mcast_filter); void (*station_address) (void); void (*statistics) (void); void (*mcastiptomac) (void); From 7af839a108857714b04cfc9384afa0b6d34c10c2 Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Thu, 18 Jun 2015 20:09:47 +0300 Subject: [PATCH 046/106] tests: regression tests for "." and ".." directory entries --- tests/util/grub-fs-tester.in | 60 ++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/tests/util/grub-fs-tester.in b/tests/util/grub-fs-tester.in index e9e85c2a8..5107ca17a 100644 --- a/tests/util/grub-fs-tester.in +++ b/tests/util/grub-fs-tester.in @@ -1121,6 +1121,36 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE + fi fi + case x"$fs" in + x"zfs"*) + LSROUT=$(run_grubfstest ls -- -la "($GRUBDEVICE)/grub fs@/.");; + *) + LSROUT=$(run_grubfstest ls -- -la "($GRUBDEVICE)/.");; + esac + if echo "$LSROUT" | grep -F " $BASEFILE" | grep "$BLOCKCNT" > /dev/null; then + : + else + echo DOT IN ROOTDIR FAIL + echo "$LSROUT" + TZ=UTC ls --time-style=+%Y%m%d%H%M%S.%N -l "$MNTPOINTRO" + exit 1 + fi + + case x"$fs" in + x"zfs"*) + LSROUT=$(run_grubfstest ls -- -la "($GRUBDEVICE)/grub fs@/..");; + *) + LSROUT=$(run_grubfstest ls -- -la "($GRUBDEVICE)/..");; + esac + if echo "$LSROUT" | grep -F " $BASEFILE" | grep "$BLOCKCNT" > /dev/null; then + : + else + echo DOTDOT IN ROOTDIR FAIL + echo "$LSROUT" + TZ=UTC ls --time-style=+%Y%m%d%H%M%S.%N -l "$MNTPOINTRO" + exit 1 + fi + case x"$fs" in x"zfs"*) LSROUT=$(run_grubfstest ls -- -l "($GRUBDEVICE)/grub fs@/////sdir");; @@ -1151,6 +1181,36 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE + exit 1 fi + case x"$fs" in + x"zfs"*) + LSROUT=$(run_grubfstest ls -- -l "($GRUBDEVICE)/grub fs@/sdir/.");; + *) + LSROUT=$(run_grubfstest ls -- -l "($GRUBDEVICE)/sdir/.");; + esac + if echo "$LSROUT" | grep -F " 2.img" | grep $BLOCKCNT > /dev/null; then + : + else + echo DOT IN SUBDIR FAIL + echo "$LSROUT" + TZ=UTC ls --time-style=+%Y%m%d%H%M%S.%N -l "$MNTPOINTRO/$OSDIR/sdir" + exit 1 + fi + + case x"$fs" in + x"zfs"*) + LSROUT=$(run_grubfstest ls -- -l "($GRUBDEVICE)/grub fs@/sdir/../sdir");; + *) + LSROUT=$(run_grubfstest ls -- -l "($GRUBDEVICE)/sdir/../sdir");; + esac + if echo "$LSROUT" | grep -F " 2.img" | grep $BLOCKCNT > /dev/null; then + : + else + echo DOTDOT IN SUBDIR FAIL + echo "$LSROUT" + TZ=UTC ls --time-style=+%Y%m%d%H%M%S.%N -l "$MNTPOINTRO/$OSDIR/ssdir" + exit 1 + fi + LSOUT=`run_grubfstest ls -- -l "($GRUBDEVICE)"` if [ x"$NOFSLABEL" = xy ]; then : From 7bb7140df2b6fd5c1fee6c47488724bc256e957a Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Thu, 18 Jun 2015 20:09:47 +0300 Subject: [PATCH 047/106] fat: fix handling of "." and ".." directory entries Emulate dot and dotdot in root directory. For other directories do not add separator between name and extension for these two special entries. Closes: 45335 --- grub-core/fs/fat.c | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/grub-core/fs/fat.c b/grub-core/fs/fat.c index 71537ff44..827708c18 100644 --- a/grub-core/fs/fat.c +++ b/grub-core/fs/fat.c @@ -829,7 +829,9 @@ grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data, i--; } - *filep++ = '.'; + /* XXX should we check that dir position is 0 or 1? */ + if (i > 2 || filep[0] != '.' || (i == 2 && filep[1] != '.')) + *filep++ = '.'; for (i = 8; i < 11 && ctxt->dir.name[i]; i++) *filep++ = grub_tolower (ctxt->dir.name[i]); @@ -871,9 +873,31 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data, return 0; } - /* Extract a directory name. */ - while (*path == '/') - path++; + do + { + /* Extract a directory name. */ + while (*path == '/') + path++; + + /* Emulate special "." and ".." entries in root directory */ + if (data->file_cluster == data->root_cluster) + { + if (*path != '.') + break; + if (!path[1] || path[1] == '/') + { + path++; + continue; + } + if (path[1] == '.' && (!path[2] || path[2] == '/')) + { + path += 2; + continue; + } + } + break; + } + while (1); dirp = grub_strchr (path, '/'); if (dirp) @@ -935,6 +959,9 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data, data->file_size = grub_le_to_cpu32 (ctxt.dir.file_size); data->file_cluster = ((grub_le_to_cpu16 (ctxt.dir.first_cluster_high) << 16) | grub_le_to_cpu16 (ctxt.dir.first_cluster_low)); + /* If directory points to root, starting cluster is 0 */ + if (!data->file_cluster) + data->file_cluster = data->root_cluster; #endif data->cur_cluster_num = ~0U; From 8067fe28edcedacf2507132baaab65dc3c4bb3d5 Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Fri, 19 Jun 2015 17:35:17 +0300 Subject: [PATCH 048/106] syslinux_parse: make print_escaped actually stop before `to' The only current user is mboot.c32 which unfortunately is not covered by regression tests. --- grub-core/lib/syslinux_parse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/lib/syslinux_parse.c b/grub-core/lib/syslinux_parse.c index 153260b54..ba71a4831 100644 --- a/grub-core/lib/syslinux_parse.c +++ b/grub-core/lib/syslinux_parse.c @@ -772,7 +772,7 @@ print_escaped (struct output_buffer *outbuf, if (err) return err; outbuf->buf[outbuf->ptr++] = '\''; - for (ptr = from; *ptr; ptr++) + for (ptr = from; *ptr && ptr < to; ptr++) { if (*ptr == '\'') { From 48cd9dc104082d4106ccd81fa3feec0d514ddd08 Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Fri, 19 Jun 2015 18:38:25 +0300 Subject: [PATCH 049/106] syslinux_parse: assorted issues found by Coverity 1. Remove unneeded NULL check CID: 96607 2. Do not allocate storage for initrd, copy it directly from input buffer. Avoids memory leak in failure path. CID: 96604 3. Unchecked error return from print() CID: 96601, 73595 --- grub-core/lib/syslinux_parse.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/grub-core/lib/syslinux_parse.c b/grub-core/lib/syslinux_parse.c index ba71a4831..28ba3aef0 100644 --- a/grub-core/lib/syslinux_parse.c +++ b/grub-core/lib/syslinux_parse.c @@ -874,7 +874,9 @@ print_config (struct output_buffer *outbuf, print_string ("#"); print_file (outbuf, menu, filename, NULL); print_string (" "); - print (outbuf, newname, grub_strlen (newname)); + err = print (outbuf, newname, grub_strlen (newname)); + if (err) + return err; print_string (":\n"); for (menuptr = menu; menuptr; menuptr = menuptr->parent, depth++) @@ -944,8 +946,8 @@ write_entry (struct output_buffer *outbuf, { case KERNEL_LINUX: { - char *ptr; - char *initrd = NULL; + const char *ptr; + const char *initrd = NULL, *initrde= NULL; for (ptr = curentry->append; ptr && *ptr; ptr++) if ((ptr == curentry->append || grub_isspace (ptr[-1])) && grub_strncasecmp (ptr, "initrd=", sizeof ("initrd=") - 1) @@ -953,12 +955,8 @@ write_entry (struct output_buffer *outbuf, break; if (ptr && *ptr) { - char *ptr2; - initrd = grub_strdup(ptr + sizeof ("initrd=") - 1); - if (!initrd) - return grub_errno; - for (ptr2 = initrd; *ptr2 && !grub_isspace (*ptr2); ptr2++); - *ptr2 = 0; + initrd = ptr + sizeof ("initrd=") - 1; + for (initrde = initrd; *initrde && !grub_isspace (*initrde); initrde++); } print_string (" if test x$grub_platform = xpc; then " "linux_suffix=16; else linux_suffix= ; fi\n"); @@ -966,7 +964,11 @@ write_entry (struct output_buffer *outbuf, print_file (outbuf, menu, curentry->kernel_file, NULL); print_string (" "); if (curentry->append) - print (outbuf, curentry->append, grub_strlen (curentry->append)); + { + err = print (outbuf, curentry->append, grub_strlen (curentry->append)); + if (err) + return err; + } print_string ("\n"); if (initrd || curentry->initrds) { @@ -974,7 +976,7 @@ write_entry (struct output_buffer *outbuf, print_string (" initrd$linux_suffix "); if (initrd) { - print_file (outbuf, menu, initrd, NULL); + print_file (outbuf, menu, initrd, initrde); print_string (" "); } for (lst = curentry->initrds; lst; lst = lst->next) @@ -985,7 +987,6 @@ write_entry (struct output_buffer *outbuf, print_string ("\n"); } - grub_free (initrd); } break; case KERNEL_CHAINLOADER: @@ -1197,8 +1198,7 @@ write_entry (struct output_buffer *outbuf, ptr++; i386e = ptr; } - if (lme) - *lme = '\0'; + *lme = '\0'; if (paee) *paee = '\0'; if (i386e) From 10a6d2d91562231d3b21fb0c64adf88805a6fbec Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Fri, 19 Jun 2015 18:38:25 +0300 Subject: [PATCH 050/106] unix/relpath: memory leak Found by Coverity scan. CID: 96606 --- grub-core/osdep/unix/relpath.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/grub-core/osdep/unix/relpath.c b/grub-core/osdep/unix/relpath.c index 8fdc3a73a..f719950fd 100644 --- a/grub-core/osdep/unix/relpath.c +++ b/grub-core/osdep/unix/relpath.c @@ -51,7 +51,10 @@ grub_make_system_path_relative_to_its_root (const char *path) #ifdef __linux__ ret = grub_make_system_path_relative_to_its_root_os (p); if (ret) - return ret; + { + free (p); + return ret; + } #endif /* For ZFS sub-pool filesystems. */ From 5d0ee3d7a1a1381cb75111f2992d5d97b301894f Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Fri, 19 Jun 2015 18:38:25 +0300 Subject: [PATCH 051/106] unix/getroot: memory leak Found by Coverity scan. CID: 96605 --- grub-core/osdep/unix/getroot.c | 1 + 1 file changed, 1 insertion(+) diff --git a/grub-core/osdep/unix/getroot.c b/grub-core/osdep/unix/getroot.c index b98b2dfb0..14d483fb1 100644 --- a/grub-core/osdep/unix/getroot.c +++ b/grub-core/osdep/unix/getroot.c @@ -544,6 +544,7 @@ grub_guess_root_devices (const char *dir_in) if (stat (dir, &st) < 0) grub_util_error (_("cannot stat `%s': %s"), dir, strerror (errno)); + free (dir); dev = st.st_dev; From 15ba6a40be2ce73f89d781ffdfc0e19e43a4d80f Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Fri, 19 Jun 2015 18:38:25 +0300 Subject: [PATCH 052/106] zfs: memory leak Found by Coverity scan. CID: 96603 --- grub-core/fs/zfs/zfs.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index f9ca0e75e..252cefdc6 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -3668,6 +3668,8 @@ zfs_mount (grub_device_t dev) data) != 0) { grub_error (GRUB_ERR_BAD_FS, "Unsupported features in pool"); + grub_free (osp); + zfs_unmount (data); return NULL; } From 4db569ca6a471aff9f2669d6e3a2fbb33f563425 Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Fri, 19 Jun 2015 18:38:25 +0300 Subject: [PATCH 053/106] xfs: silence Coverity overflow warning inode size cannot really overflow integer, but Coverity does not know it. CID: 96602 --- grub-core/fs/xfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c index f00e43e7d..724929155 100644 --- a/grub-core/fs/xfs.c +++ b/grub-core/fs/xfs.c @@ -361,7 +361,7 @@ grub_xfs_inode_offset (struct grub_xfs_data *data, static inline grub_size_t grub_xfs_inode_size(struct grub_xfs_data *data) { - return 1 << data->sblock.log2_inode; + return (grub_size_t)1 << data->sblock.log2_inode; } /* From fbdd37e7f947ae39208ce0b6f0dd17e958cd5b8e Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Fri, 19 Jun 2015 20:47:43 +0300 Subject: [PATCH 054/106] zfs: fix memory leak Found by: Coverity scan. CID: 73647 --- grub-core/fs/zfs/zfs.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index 252cefdc6..c4ead29fb 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -2882,7 +2882,10 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, err = dmu_read (&(dnode_path->dn), block, &t, 0, data); if (err) - return err; + { + grub_free (sym_value); + return err; + } movesize = sym_sz - block * blksz; if (movesize > blksz) From 03f1f24e37d59e79b6c011cb51bab215cc7ec9cd Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Fri, 19 Jun 2015 20:47:43 +0300 Subject: [PATCH 055/106] grub-probe: restructure code to make static analysis easier Current code in probe() could not be verified to not contain memory leaks. Restructure code and ensure grub_device_close is always called at the end of loop. Calms down Coverity scan. CID: 73739 --- util/grub-probe.c | 86 ++++++++++++++--------------------------------- 1 file changed, 25 insertions(+), 61 deletions(-) diff --git a/util/grub-probe.c b/util/grub-probe.c index 6075cb3fc..4013229cb 100644 --- a/util/grub-probe.c +++ b/util/grub-probe.c @@ -485,23 +485,18 @@ probe (const char *path, char **device_names, char delim) printf (" "); else printf ("\n"); - - grub_device_close (dev); - continue; } - if ((print == PRINT_COMPATIBILITY_HINT || print == PRINT_BIOS_HINT + else if ((print == PRINT_COMPATIBILITY_HINT || print == PRINT_BIOS_HINT || print == PRINT_IEEE1275_HINT || print == PRINT_BAREMETAL_HINT || print == PRINT_EFI_HINT || print == PRINT_ARC_HINT) && dev->disk->dev->id != GRUB_DISK_DEVICE_HOSTDISK_ID) { grub_util_fprint_full_disk_name (stdout, dev->disk->name, dev); putchar (delim); - grub_device_close (dev); - continue; } - if (print == PRINT_COMPATIBILITY_HINT) + else if (print == PRINT_COMPATIBILITY_HINT) { const char *map; char *biosname; @@ -519,16 +514,14 @@ probe (const char *path, char **device_names, char delim) { grub_util_fprint_full_disk_name (stdout, biosname, dev); putchar (delim); + free (biosname); + /* Compatibility hint is one device only. */ + grub_device_close (dev); + break; } - free (biosname); - grub_device_close (dev); - /* Compatibility hint is one device only. */ - if (biosname) - break; - continue; } - if (print == PRINT_BIOS_HINT) + else if (print == PRINT_BIOS_HINT) { char *biosname; biosname = grub_util_guess_bios_drive (*curdev); @@ -536,12 +529,10 @@ probe (const char *path, char **device_names, char delim) { grub_util_fprint_full_disk_name (stdout, biosname, dev); putchar (delim); + free (biosname); } - free (biosname); - grub_device_close (dev); - continue; } - if (print == PRINT_IEEE1275_HINT) + else if (print == PRINT_IEEE1275_HINT) { const char *osdev = grub_util_biosdisk_get_osdev (dev->disk); char *ofpath = grub_util_devname_to_ofpath (osdev); @@ -565,11 +556,8 @@ probe (const char *path, char **device_names, char delim) free (ofpath); putchar (delim); } - - grub_device_close (dev); - continue; } - if (print == PRINT_EFI_HINT) + else if (print == PRINT_EFI_HINT) { char *biosname; const char *map; @@ -585,14 +573,11 @@ probe (const char *path, char **device_names, char delim) { grub_util_fprint_full_disk_name (stdout, biosname, dev); putchar (delim); + free (biosname); } - - free (biosname); - grub_device_close (dev); - continue; } - if (print == PRINT_BAREMETAL_HINT) + else if (print == PRINT_BAREMETAL_HINT) { char *biosname; const char *map; @@ -609,14 +594,11 @@ probe (const char *path, char **device_names, char delim) { grub_util_fprint_full_disk_name (stdout, biosname, dev); putchar (delim); + free (biosname); } - - free (biosname); - grub_device_close (dev); - continue; } - if (print == PRINT_ARC_HINT) + else if (print == PRINT_ARC_HINT) { const char *map; @@ -626,46 +608,28 @@ probe (const char *path, char **device_names, char delim) grub_util_fprint_full_disk_name (stdout, map, dev); putchar (delim); } - - /* FIXME */ - grub_device_close (dev); - continue; } - if (print == PRINT_ABSTRACTION) - { - probe_abstraction (dev->disk, delim); - grub_device_close (dev); - continue; - } + else if (print == PRINT_ABSTRACTION) + probe_abstraction (dev->disk, delim); - if (print == PRINT_CRYPTODISK_UUID) - { - probe_cryptodisk_uuid (dev->disk, delim); - grub_device_close (dev); - continue; - } + else if (print == PRINT_CRYPTODISK_UUID) + probe_cryptodisk_uuid (dev->disk, delim); - if (print == PRINT_PARTMAP) - { - /* Check if dev->disk itself is contained in a partmap. */ - probe_partmap (dev->disk, delim); - grub_device_close (dev); - continue; - } + else if (print == PRINT_PARTMAP) + /* Check if dev->disk itself is contained in a partmap. */ + probe_partmap (dev->disk, delim); - if (print == PRINT_MSDOS_PARTTYPE) + else if (print == PRINT_MSDOS_PARTTYPE) { if (dev->disk->partition && strcmp(dev->disk->partition->partmap->name, "msdos") == 0) printf ("%02x", dev->disk->partition->msdostype); putchar (delim); - grub_device_close (dev); - continue; } - if (print == PRINT_GPT_PARTTYPE) + else if (print == PRINT_GPT_PARTTYPE) { if (dev->disk->partition && strcmp (dev->disk->partition->partmap->name, "gpt") == 0) @@ -694,9 +658,9 @@ probe (const char *path, char **device_names, char delim) dev->disk->partition = p; } putchar (delim); - grub_device_close (dev); - continue; } + + grub_device_close (dev); } end: From 4358e0c81ec506ad9400f053b3f1f41597285833 Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Fri, 19 Jun 2015 20:47:44 +0300 Subject: [PATCH 056/106] grub-probe: fix memory leak in probe (ofpath) Found by: Coverity scan. CID: 73772 --- util/grub-probe.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/util/grub-probe.c b/util/grub-probe.c index 4013229cb..b1f533626 100644 --- a/util/grub-probe.c +++ b/util/grub-probe.c @@ -429,7 +429,7 @@ probe (const char *path, char **device_names, char delim) if (print == PRINT_HINT_STR) { const char *osdev = grub_util_biosdisk_get_osdev (dev->disk); - const char *ofpath = osdev ? grub_util_devname_to_ofpath (osdev) : 0; + char *ofpath = osdev ? grub_util_devname_to_ofpath (osdev) : 0; char *biosname, *bare, *efi; const char *map; @@ -443,6 +443,7 @@ probe (const char *path, char **device_names, char delim) grub_util_fprint_full_disk_name (stdout, tmp, dev); printf ("' "); free (tmp); + free (ofpath); } biosname = grub_util_guess_bios_drive (*curdev); From 72ccf92c3937fda8f101b62e6ec8eb389aa8a915 Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Sat, 20 Jun 2015 09:23:43 +0300 Subject: [PATCH 057/106] NEWS: emu libusb support removed --- NEWS | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS b/NEWS index 6e33909de..4abd873de 100644 --- a/NEWS +++ b/NEWS @@ -149,6 +149,7 @@ New in 2.02: * Target is built without libgcc now. Necessary builtins are reimplemented directly. This removes requirement for target-specific runtime on build system. + * emu libusb support removed (was broken and unmaintained). * Revision control moved to git. From 0fb886cde97b8b65eceece62440194523530737a Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Sat, 20 Jun 2015 23:38:17 +0300 Subject: [PATCH 058/106] search: fix use after free Found by: Coverity scan. CID: 96715 --- grub-core/commands/search.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/commands/search.c b/grub-core/commands/search.c index 16143a34c..440303a4e 100644 --- a/grub-core/commands/search.c +++ b/grub-core/commands/search.c @@ -210,10 +210,10 @@ try (struct search_ctx *ctx) /* Cache entry was outdated. Remove it. */ if (!ctx->count) { + *prev = cache_ent->next; grub_free (cache_ent->key); grub_free (cache_ent->value); grub_free (cache_ent); - *prev = cache_ent->next; } } From c069460259b0a3ed77c4035267250dc2b82f1cb4 Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Sat, 20 Jun 2015 23:38:17 +0300 Subject: [PATCH 059/106] efi/chainloader: fix use after free Found by: Coverity scan. CID: 96714 --- grub-core/loader/efi/chainloader.c | 1 + 1 file changed, 1 insertion(+) diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c index 233237018..ec23cf4ed 100644 --- a/grub-core/loader/efi/chainloader.c +++ b/grub-core/loader/efi/chainloader.c @@ -351,6 +351,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), loaded_image->device_handle = dev_handle; grub_file_close (file); + file = NULL; if (argc > 1) { From cd816bd23683de5fecc0aeafaed9e2b850b70dd8 Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Sat, 20 Jun 2015 23:38:18 +0300 Subject: [PATCH 060/106] disk/scsi: fix use after free Found by: Coverity scan. CID: 96713 --- grub-core/disk/scsi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/grub-core/disk/scsi.c b/grub-core/disk/scsi.c index 92084d0f8..4c6923f8b 100644 --- a/grub-core/disk/scsi.c +++ b/grub-core/disk/scsi.c @@ -615,9 +615,10 @@ grub_scsi_open (const char *name, grub_disk_t disk) if (scsi->blocksize & (scsi->blocksize - 1) || !scsi->blocksize) { + grub_error (GRUB_ERR_IO, "invalid sector size %d", + scsi->blocksize); grub_free (scsi); - return grub_error (GRUB_ERR_IO, "invalid sector size %d", - scsi->blocksize); + return grub_errno; } for (disk->log_sector_size = 0; (1U << disk->log_sector_size) < scsi->blocksize; From e261fcf4c6c3381691875e02549c5723ca06da7d Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Sat, 20 Jun 2015 23:38:18 +0300 Subject: [PATCH 061/106] xnu: fix use after free Found by: Coverity scan. CID: 96706 --- grub-core/loader/i386/xnu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/loader/i386/xnu.c b/grub-core/loader/i386/xnu.c index e0506a676..2fe1fdc1f 100644 --- a/grub-core/loader/i386/xnu.c +++ b/grub-core/loader/i386/xnu.c @@ -269,9 +269,9 @@ grub_xnu_devprop_add_property (struct grub_xnu_devprop_device_descriptor *dev, prop->data = grub_malloc (prop->length); if (!prop->data) { - grub_free (prop); grub_free (prop->name); grub_free (prop->name16); + grub_free (prop); return grub_errno; } grub_memcpy (prop->data, data, prop->length); From cf0b0306d818e1b79745420b2bdca449ba881130 Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Sat, 20 Jun 2015 23:38:18 +0300 Subject: [PATCH 062/106] usb: fix use after free Found by: Coverity scan. CID: 96704 --- grub-core/bus/usb/usbtrans.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/bus/usb/usbtrans.c b/grub-core/bus/usb/usbtrans.c index b614997f2..ee8680853 100644 --- a/grub-core/bus/usb/usbtrans.c +++ b/grub-core/bus/usb/usbtrans.c @@ -311,8 +311,8 @@ grub_usb_bulk_finish_readwrite (grub_usb_transfer_t transfer) transfer->size + 1); grub_free (transfer->transactions); - grub_free (transfer); grub_dma_free (transfer->data_chunk); + grub_free (transfer); } static grub_usb_err_t From a6f7d1abce848da5593ccc39492ef5c1df11a33c Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Sat, 20 Jun 2015 23:38:18 +0300 Subject: [PATCH 063/106] reed_solomon: fix memory leak Found by: Coverity scan. CID: 96688 --- grub-core/lib/reed_solomon.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/grub-core/lib/reed_solomon.c b/grub-core/lib/reed_solomon.c index 7263cbc04..ee9fa7b4f 100644 --- a/grub-core/lib/reed_solomon.c +++ b/grub-core/lib/reed_solomon.c @@ -362,7 +362,7 @@ grub_reed_solomon_add_redundancy (void *buffer, grub_size_t data_size, /* Nothing to do. */ if (!rs) - return; + goto exit; init_powx (); @@ -388,6 +388,7 @@ grub_reed_solomon_add_redundancy (void *buffer, grub_size_t data_size, #ifndef TEST assert (grub_memcmp (tmp, buffer, data_size) == 0); #endif +exit: free (tmp); } #endif From 20211c0077a6eb9a0949fe9cb5778c7f69d28894 Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Sat, 20 Jun 2015 23:38:18 +0300 Subject: [PATCH 064/106] loader/bsd: fix memory leak Found by: Coverity scan. CID: 96686 --- grub-core/loader/i386/bsdXX.c | 40 +++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/grub-core/loader/i386/bsdXX.c b/grub-core/loader/i386/bsdXX.c index 9e36cd4b6..cfb44c080 100644 --- a/grub-core/loader/i386/bsdXX.c +++ b/grub-core/loader/i386/bsdXX.c @@ -417,7 +417,10 @@ SUFFIX (grub_netbsd_load_elf_meta) (struct grub_relocator *relocator, err = read_headers (file, filename, &e, &shdr); if (err) - return err; + { + grub_free (shdr); + return grub_errno; + } for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) (shdr + e.e_shnum * e.e_shentsize); @@ -426,7 +429,10 @@ SUFFIX (grub_netbsd_load_elf_meta) (struct grub_relocator *relocator, break; if (s >= (Elf_Shdr *) ((char *) shdr + e.e_shnum * e.e_shentsize)) - return GRUB_ERR_NONE; + { + grub_free (shdr); + return GRUB_ERR_NONE; + } symsize = s->sh_size; symsh = s; s = (Elf_Shdr *) (shdr + e.e_shentsize * s->sh_link); @@ -443,7 +449,7 @@ SUFFIX (grub_netbsd_load_elf_meta) (struct grub_relocator *relocator, err = grub_relocator_alloc_chunk_addr (relocator, &ch, symtarget, chunk_size); if (err) - return err; + goto out; sym_chunk = get_virtual_current_address (ch); } @@ -482,29 +488,41 @@ SUFFIX (grub_netbsd_load_elf_meta) (struct grub_relocator *relocator, } if (grub_file_seek (file, symsh->sh_offset) == (grub_off_t) -1) - return grub_errno; + { + err = grub_errno; + goto out; + } if (grub_file_read (file, curload, symsize) != (grub_ssize_t) symsize) { if (! grub_errno) - return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), - filename); - return grub_errno; + err = grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + filename); + else + err = grub_errno; + goto out; } curload += ALIGN_UP (symsize, sizeof (grub_freebsd_addr_t)); if (grub_file_seek (file, strsh->sh_offset) == (grub_off_t) -1) - return grub_errno; + { + err = grub_errno; + goto out; + } if (grub_file_read (file, curload, strsize) != (grub_ssize_t) strsize) { if (! grub_errno) - return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), - filename); - return grub_errno; + err = grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + filename); + else + err = grub_errno; + goto out; } err = grub_bsd_add_meta (NETBSD_BTINFO_SYMTAB, &symtab, sizeof (symtab)); +out: + grub_free (shdr); if (err) return err; From 2a3ebf94283171f919fee5a0e35e497d800816fb Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Sat, 20 Jun 2015 23:38:18 +0300 Subject: [PATCH 065/106] normal: fix memory leak Found by: Coverity scan. CID: 96685 --- grub-core/normal/cmdline.c | 1 + 1 file changed, 1 insertion(+) diff --git a/grub-core/normal/cmdline.c b/grub-core/normal/cmdline.c index 204d15a4b..a36180d75 100644 --- a/grub-core/normal/cmdline.c +++ b/grub-core/normal/cmdline.c @@ -389,6 +389,7 @@ grub_cmdline_get (const char *prompt_translated) if (!unicode_msg) { grub_free (buf); + grub_free (cl_terms); return 0; } msg_len = grub_utf8_to_ucs4 (unicode_msg, msg_len - 1, From eb33e61b31902a5493468895aaf83fa0b4f5f59d Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Sat, 20 Jun 2015 23:38:18 +0300 Subject: [PATCH 066/106] multiboot: fix memory leak Found by: Coverity scan. CID: 96684 --- grub-core/loader/multiboot_elfxx.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/grub-core/loader/multiboot_elfxx.c b/grub-core/loader/multiboot_elfxx.c index 9dc21a1ba..6a220bdc1 100644 --- a/grub-core/loader/multiboot_elfxx.c +++ b/grub-core/loader/multiboot_elfxx.c @@ -169,7 +169,10 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, const char *filename, voi return grub_errno; if (grub_file_seek (file, ehdr->e_shoff) == (grub_off_t) -1) - return grub_errno; + { + grub_free (shdr); + return grub_errno; + } if (grub_file_read (file, shdr, ehdr->e_shnum * ehdr->e_shentsize) != (grub_ssize_t) ehdr->e_shnum * ehdr->e_shentsize) From 4a857e63c189a756e7c6099306faa41cf173ad28 Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Sat, 20 Jun 2015 23:38:18 +0300 Subject: [PATCH 067/106] loader/bsd: free memory leaks Found by: Coverity scan. CID: 96682 --- grub-core/loader/i386/bsdXX.c | 43 +++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/grub-core/loader/i386/bsdXX.c b/grub-core/loader/i386/bsdXX.c index cfb44c080..53ae37c1e 100644 --- a/grub-core/loader/i386/bsdXX.c +++ b/grub-core/loader/i386/bsdXX.c @@ -292,13 +292,13 @@ SUFFIX (grub_freebsd_load_elf_meta) (struct grub_relocator *relocator, err = read_headers (file, filename, &e, &shdr); if (err) - return err; + goto out; err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA | FREEBSD_MODINFOMD_ELFHDR, &e, sizeof (e)); if (err) - return err; + goto out; for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) (shdr + e.e_shnum * e.e_shentsize); @@ -307,7 +307,10 @@ SUFFIX (grub_freebsd_load_elf_meta) (struct grub_relocator *relocator, break; if (s >= (Elf_Shdr *) ((char *) shdr + e.e_shnum * e.e_shentsize)) - return grub_error (GRUB_ERR_BAD_OS, N_("no symbol table")); + { + err = grub_error (GRUB_ERR_BAD_OS, N_("no symbol table")); + goto out; + } symoff = s->sh_offset; symsize = s->sh_size; symentsize = s->sh_entsize; @@ -325,7 +328,7 @@ SUFFIX (grub_freebsd_load_elf_meta) (struct grub_relocator *relocator, err = grub_relocator_alloc_chunk_addr (relocator, &ch, symtarget, chunk_size); if (err) - return err; + goto out; sym_chunk = get_virtual_current_address (ch); } @@ -337,28 +340,38 @@ SUFFIX (grub_freebsd_load_elf_meta) (struct grub_relocator *relocator, curload += sizeof (grub_freebsd_addr_t); if (grub_file_seek (file, symoff) == (grub_off_t) -1) - return grub_errno; + { + err = grub_errno; + goto out; + } sym = (Elf_Sym *) curload; if (grub_file_read (file, curload, symsize) != (grub_ssize_t) symsize) { if (! grub_errno) - return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), - filename); - return grub_errno; + err = grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + filename); + else + err = grub_errno; + goto out; } curload += symsize; *((grub_freebsd_addr_t *) curload) = strsize; curload += sizeof (grub_freebsd_addr_t); if (grub_file_seek (file, stroff) == (grub_off_t) -1) - return grub_errno; + { + err = grub_errno; + goto out; + } str = (char *) curload; if (grub_file_read (file, curload, strsize) != (grub_ssize_t) strsize) { if (! grub_errno) - return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), - filename); - return grub_errno; + err = grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + filename); + else + err = grub_errno; + goto out; } for (i = 0; @@ -378,18 +391,20 @@ SUFFIX (grub_freebsd_load_elf_meta) (struct grub_relocator *relocator, FREEBSD_MODINFOMD_DYNAMIC, &dynamic, sizeof (dynamic)); if (err) - return err; + goto out; } err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA | FREEBSD_MODINFOMD_SSYM, &symstart, sizeof (symstart)); if (err) - return err; + goto out; err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA | FREEBSD_MODINFOMD_ESYM, &symend, sizeof (symend)); +out: + grub_free (shdr); if (err) return err; From 47490ada3ddc24a323a654cef7828f604d9b871a Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Sat, 20 Jun 2015 23:38:19 +0300 Subject: [PATCH 068/106] ohci: fix memory leak Found by: Coverity scan. CID: 96679 --- grub-core/bus/usb/ohci.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/grub-core/bus/usb/ohci.c b/grub-core/bus/usb/ohci.c index d27bfe7fb..f0be533d4 100644 --- a/grub-core/bus/usb/ohci.c +++ b/grub-core/bus/usb/ohci.c @@ -750,7 +750,10 @@ grub_ohci_setup_transfer (grub_usb_controller_t dev, { cdata->td_head_virt = grub_ohci_alloc_td (o); if (!cdata->td_head_virt) - return GRUB_USB_ERR_INTERNAL; /* We don't need de-allocate ED */ + { + grub_free (cdata); + return GRUB_USB_ERR_INTERNAL; /* We don't need de-allocate ED */ + } /* We can set td_head only when ED is not active, i.e. * when it is newly allocated. */ cdata->ed_virt->td_head From e7e05cae8d4bd48fb3221297fe3b388aeab47f37 Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Sat, 20 Jun 2015 23:38:19 +0300 Subject: [PATCH 069/106] efi/serial: fix memory leak Found by: Coverity scan. CID: 96678 --- grub-core/term/efi/serial.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/grub-core/term/efi/serial.c b/grub-core/term/efi/serial.c index c0911ad7b..4c94723c5 100644 --- a/grub-core/term/efi/serial.c +++ b/grub-core/term/efi/serial.c @@ -173,7 +173,10 @@ grub_efiserial_init (void) port->name = grub_malloc (sizeof ("efiXXXXXXXXXXXXXXXXXXXX")); if (!port->name) - return; + { + grub_free (port); + return; + } grub_snprintf (port->name, sizeof ("efiXXXXXXXXXXXXXXXXXXXX"), "efi%d", num_serial++); From 152695d0faefe763b2198048e6f3e905a8c0c786 Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Sat, 20 Jun 2015 23:38:19 +0300 Subject: [PATCH 070/106] normal: fix memory leak Found by: Coverity scan. CID: 96677 --- grub-core/normal/context.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/grub-core/normal/context.c b/grub-core/normal/context.c index 7e0a696f3..ee53d4a68 100644 --- a/grub-core/normal/context.c +++ b/grub-core/normal/context.c @@ -64,7 +64,10 @@ grub_env_new_context (int export_all) return grub_errno; menu = grub_zalloc (sizeof (*menu)); if (! menu) - return grub_errno; + { + grub_free (context); + return grub_errno; + } context->prev = grub_current_context; grub_current_context = context; From 2f01f08103aac50878c8ed704df5bfddf7443c5a Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Sat, 20 Jun 2015 23:38:19 +0300 Subject: [PATCH 071/106] password_pbkdf2: fix memory leak Found by: Coverity scan. CID: 96676 --- grub-core/commands/password_pbkdf2.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/grub-core/commands/password_pbkdf2.c b/grub-core/commands/password_pbkdf2.c index 0dd1aef3d..c6a77c8c5 100644 --- a/grub-core/commands/password_pbkdf2.c +++ b/grub-core/commands/password_pbkdf2.c @@ -104,7 +104,10 @@ grub_cmd_password (grub_command_t cmd __attribute__ ((unused)), pass->c = grub_strtoul (ptr, &ptr, 0); if (grub_errno) - return grub_errno; + { + grub_free (pass); + return grub_errno; + } if (*ptr != '.') { grub_free (pass); From 5af859bb77c80583d4412a44929b33bb344b05f3 Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Sat, 20 Jun 2015 23:38:19 +0300 Subject: [PATCH 072/106] search_wrap: fix memory leak Found by: Coverity scan. CID: 96675 --- grub-core/commands/search_wrap.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/grub-core/commands/search_wrap.c b/grub-core/commands/search_wrap.c index 3f75fecdf..d7fd26b94 100644 --- a/grub-core/commands/search_wrap.c +++ b/grub-core/commands/search_wrap.c @@ -175,7 +175,10 @@ grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args) var = "root"; } else - return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); + { + grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); + goto out; + } if (state[SEARCH_LABEL].set) grub_search_label (id, var, state[SEARCH_NO_FLOPPY].set, @@ -187,8 +190,10 @@ grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args) grub_search_fs_file (id, var, state[SEARCH_NO_FLOPPY].set, hints, nhints); else - return grub_error (GRUB_ERR_INVALID_COMMAND, "unspecified search type"); + grub_error (GRUB_ERR_INVALID_COMMAND, "unspecified search type"); +out: + grub_free (hints); return grub_errno; } From 867c9b7bec3446daa6a14a553c404ea26548242b Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Sat, 20 Jun 2015 23:38:19 +0300 Subject: [PATCH 073/106] loader/bsd: free memory leaks Found by: Coverity scan. CID: 96671, 96658, 96653 --- grub-core/loader/i386/bsdXX.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/grub-core/loader/i386/bsdXX.c b/grub-core/loader/i386/bsdXX.c index 53ae37c1e..051ff06b5 100644 --- a/grub-core/loader/i386/bsdXX.c +++ b/grub-core/loader/i386/bsdXX.c @@ -563,7 +563,10 @@ SUFFIX(grub_openbsd_find_ramdisk) (grub_file_t file, err = read_headers (file, filename, &e, &shdr); if (err) - return err; + { + grub_free (shdr); + return err; + } for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) (shdr + e.e_shnum * e.e_shentsize); @@ -616,7 +619,11 @@ SUFFIX(grub_openbsd_find_ramdisk) (grub_file_t file, } if (grub_file_seek (file, stroff) == (grub_off_t) -1) - return grub_errno; + { + grub_free (syms); + grub_free (strs); + return grub_errno; + } if (grub_file_read (file, strs, strsize) != (grub_ssize_t) strsize) { grub_free (syms); From 806bb7999dab556ffa12db976480a129a43e8a68 Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Fri, 26 Jun 2015 09:25:30 +0300 Subject: [PATCH 074/106] loader/bsd: fix memory leak Found by: Coverity scan. CID: 96662, 96665 --- grub-core/loader/i386/bsdXX.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/grub-core/loader/i386/bsdXX.c b/grub-core/loader/i386/bsdXX.c index 051ff06b5..9f57cfa82 100644 --- a/grub-core/loader/i386/bsdXX.c +++ b/grub-core/loader/i386/bsdXX.c @@ -84,11 +84,11 @@ SUFFIX (grub_freebsd_load_elfmodule_obj) (struct grub_relocator *relocator, grub_size_t chunk_size = 0; void *chunk_src; + curload = module = ALIGN_PAGE (*kern_end); + err = read_headers (file, argv[0], &e, &shdr); if (err) - return err; - - curload = module = ALIGN_PAGE (*kern_end); + goto out; for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) ((char *) shdr + e.e_shnum * e.e_shentsize); @@ -109,7 +109,7 @@ SUFFIX (grub_freebsd_load_elfmodule_obj) (struct grub_relocator *relocator, err = grub_relocator_alloc_chunk_addr (relocator, &ch, module, chunk_size); if (err) - return err; + goto out; chunk_src = get_virtual_current_address (ch); } @@ -135,7 +135,7 @@ SUFFIX (grub_freebsd_load_elfmodule_obj) (struct grub_relocator *relocator, err = load (file, argv[0], (grub_uint8_t *) chunk_src + curload - *kern_end, s->sh_offset, s->sh_size); if (err) - return err; + goto out; break; case SHT_NOBITS: grub_memset ((grub_uint8_t *) chunk_src + curload - *kern_end, 0, @@ -159,6 +159,8 @@ SUFFIX (grub_freebsd_load_elfmodule_obj) (struct grub_relocator *relocator, | FREEBSD_MODINFOMD_SHDR, shdr, e.e_shnum * e.e_shentsize); +out: + grub_free (shdr); return err; } @@ -177,11 +179,11 @@ SUFFIX (grub_freebsd_load_elfmodule) (struct grub_relocator *relocator, grub_size_t chunk_size = 0; void *chunk_src; + curload = module = ALIGN_PAGE (*kern_end); + err = read_headers (file, argv[0], &e, &shdr); if (err) - return err; - - curload = module = ALIGN_PAGE (*kern_end); + goto out; for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) ((char *) shdr + e.e_shnum * e.e_shentsize); @@ -207,7 +209,7 @@ SUFFIX (grub_freebsd_load_elfmodule) (struct grub_relocator *relocator, err = grub_relocator_alloc_chunk_addr (relocator, &ch, module, chunk_size); if (err) - return err; + goto out; chunk_src = get_virtual_current_address (ch); } @@ -235,7 +237,7 @@ SUFFIX (grub_freebsd_load_elfmodule) (struct grub_relocator *relocator, + s->sh_addr - *kern_end, s->sh_offset, s->sh_size); if (err) - return err; + goto out; break; case SHT_NOBITS: grub_memset ((grub_uint8_t *) chunk_src + module @@ -265,6 +267,10 @@ SUFFIX (grub_freebsd_load_elfmodule) (struct grub_relocator *relocator, grub_freebsd_add_meta_module (argv[0], FREEBSD_MODTYPE_ELF_MODULE, argc - 1, argv + 1, module, curload - module); +out: + grub_free (shdr); + if (err) + return err; return SUFFIX (grub_freebsd_load_elf_meta) (relocator, file, argv[0], kern_end); } From c058e85615fde15d9593ff0377cf3de94a906fac Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Fri, 26 Jun 2015 09:25:30 +0300 Subject: [PATCH 075/106] chainloader: fix resoource leak Found by: Coverity scan. CID: 96651 --- grub-core/loader/efi/chainloader.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c index ec23cf4ed..522a716e3 100644 --- a/grub-core/loader/efi/chainloader.c +++ b/grub-core/loader/efi/chainloader.c @@ -350,9 +350,6 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), } loaded_image->device_handle = dev_handle; - grub_file_close (file); - file = NULL; - if (argc > 1) { int i, len; @@ -382,6 +379,9 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), loaded_image->load_options_size = len; } + grub_file_close (file); + grub_device_close (dev); + grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0); return 0; From 7a210304ebfd6d704b4fc08fe496a0c417441879 Mon Sep 17 00:00:00 2001 From: Michael Chang Date: Mon, 22 Jun 2015 16:45:27 +0800 Subject: [PATCH 076/106] Fix missing byte order conversion in get_btrfs_fs_prefix function Since btrfs on-disk format uses little-endian, the searched item types (ROOT_REF, INODE_REF) need converting the byte order in order to function properly on big-endian systems. --- grub-core/osdep/linux/getroot.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/grub-core/osdep/linux/getroot.c b/grub-core/osdep/linux/getroot.c index a2e360f52..3978c7114 100644 --- a/grub-core/osdep/linux/getroot.c +++ b/grub-core/osdep/linux/getroot.c @@ -316,9 +316,9 @@ get_btrfs_fs_prefix (const char *mount_path) tree_id = sargs.buf[2]; br = (struct grub_btrfs_root_backref *) (sargs.buf + 4); - inode_id = br->inode_id; + inode_id = grub_le_to_cpu64 (br->inode_id); name = br->name; - namelen = br->n; + namelen = grub_le_to_cpu16 (br->n); } else { @@ -345,7 +345,7 @@ get_btrfs_fs_prefix (const char *mount_path) ir = (struct grub_btrfs_inode_ref *) (sargs.buf + 4); name = ir->name; - namelen = ir->n; + namelen = grub_le_to_cpu16 (ir->n); } old = ret; ret = xmalloc (namelen + (old ? strlen (old) : 0) + 2); From 0d7c7f751dc5a8338497bef8b38f78153c4f0464 Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Sun, 5 Jul 2015 08:21:38 +0300 Subject: [PATCH 077/106] use TARGET_LDFLAGS in grub_PROG_OBJCOPY_ABSOLUTE That's what Makefile will use and it is required if unusual flags must be passed to linker (e.g. to build ppc32 code on ppc64le with clang). --- acinclude.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acinclude.m4 b/acinclude.m4 index 609c4f2f6..526f97a3a 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -93,7 +93,7 @@ else fi grub_cv_prog_objcopy_absolute=yes for link_addr in 0x2000 0x8000 0x7C00; do - if AC_TRY_COMMAND([${CC-cc} ${CFLAGS} -nostdlib ${TARGET_IMG_LDFLAGS_AC} ${TARGET_IMG_BASE_LDOPT},$link_addr conftest.o -o conftest.exec]); then : + if AC_TRY_COMMAND([${CC-cc} ${TARGET_CFLAGS} ${TARGET_LDFLAGS} -nostdlib ${TARGET_IMG_LDFLAGS_AC} ${TARGET_IMG_BASE_LDOPT},$link_addr conftest.o -o conftest.exec]); then : else AC_MSG_ERROR([${CC-cc} cannot link at address $link_addr]) fi From 54e7dbbcb93b913514e3e9f8f29e6372ea34ff32 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Thu, 16 Jul 2015 10:59:33 +0200 Subject: [PATCH 078/106] grub_ext2_read_block: Fix return type on error. --- grub-core/fs/ext2.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/grub-core/fs/ext2.c b/grub-core/fs/ext2.c index 5199cb0c1..cdce63bcc 100644 --- a/grub-core/fs/ext2.c +++ b/grub-core/fs/ext2.c @@ -538,8 +538,9 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) shift = 2; goto indirect; } - return grub_error (GRUB_ERR_BAD_FS, - "ext2fs doesn't support quadruple indirect blocks"); + grub_error (GRUB_ERR_BAD_FS, + "ext2fs doesn't support quadruple indirect blocks"); + return -1; indirect: do { @@ -554,7 +555,7 @@ indirect: & ((1 << log_perblock) - 1)) * sizeof (indir), sizeof (indir), &indir)) - return grub_errno; + return -1; } while (shift--); return grub_le_to_cpu32 (indir); From ff3c2007ef22b4385ff189b60aaf1f9de3dff24b Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Thu, 16 Jul 2015 12:46:02 +0200 Subject: [PATCH 079/106] XFS: Fix wrong alignment treatment. --- grub-core/fs/xfs.c | 87 ++++++++++++++++++++++++++++------------------ 1 file changed, 53 insertions(+), 34 deletions(-) diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c index 724929155..46de6aff3 100644 --- a/grub-core/fs/xfs.c +++ b/grub-core/fs/xfs.c @@ -136,7 +136,13 @@ struct grub_xfs_dir2_entry grub_uint8_t len; } GRUB_PACKED; -typedef grub_uint32_t grub_xfs_extent[4]; +struct grub_xfs_extent +{ + /* This should be a bitfield but bietfields are unportable, so just have + a raw array and functions extracting useful info from it. + */ + grub_uint32_t raw[4]; +} GRUB_PACKED; struct grub_xfs_btree_node { @@ -147,20 +153,20 @@ struct grub_xfs_btree_node grub_uint64_t right; /* In V5 here follow crc, uuid, etc. */ /* Then follow keys and block pointers */ -} GRUB_PACKED; +} GRUB_PACKED; struct grub_xfs_btree_root { grub_uint16_t level; grub_uint16_t numrecs; grub_uint64_t keys[1]; -} GRUB_PACKED; +} GRUB_PACKED; struct grub_xfs_time { grub_uint32_t sec; grub_uint32_t nanosec; -} GRUB_PACKED; +} GRUB_PACKED; struct grub_xfs_inode { @@ -313,25 +319,25 @@ GRUB_XFS_FSB_TO_BLOCK (struct grub_xfs_data *data, grub_disk_addr_t fsb) } static inline grub_uint64_t -GRUB_XFS_EXTENT_OFFSET (grub_xfs_extent *exts, int ex) +GRUB_XFS_EXTENT_OFFSET (struct grub_xfs_extent *exts, int ex) { - return ((grub_be_to_cpu32 (exts[ex][0]) & ~(1 << 31)) << 23 - | grub_be_to_cpu32 (exts[ex][1]) >> 9); + return ((grub_be_to_cpu32 (exts[ex].raw[0]) & ~(1 << 31)) << 23 + | grub_be_to_cpu32 (exts[ex].raw[1]) >> 9); } static inline grub_uint64_t -GRUB_XFS_EXTENT_BLOCK (grub_xfs_extent *exts, int ex) +GRUB_XFS_EXTENT_BLOCK (struct grub_xfs_extent *exts, int ex) { - return ((grub_uint64_t) (grub_be_to_cpu32 (exts[ex][1]) + return ((grub_uint64_t) (grub_be_to_cpu32 (exts[ex].raw[1]) & (0x1ff)) << 43 - | (grub_uint64_t) grub_be_to_cpu32 (exts[ex][2]) << 11 - | grub_be_to_cpu32 (exts[ex][3]) >> 21); + | (grub_uint64_t) grub_be_to_cpu32 (exts[ex].raw[2]) << 11 + | grub_be_to_cpu32 (exts[ex].raw[3]) >> 21); } static inline grub_uint64_t -GRUB_XFS_EXTENT_SIZE (grub_xfs_extent *exts, int ex) +GRUB_XFS_EXTENT_SIZE (struct grub_xfs_extent *exts, int ex) { - return (grub_be_to_cpu32 (exts[ex][3]) & ((1 << 21) - 1)); + return (grub_be_to_cpu32 (exts[ex].raw[3]) & ((1 << 21) - 1)); } @@ -377,7 +383,10 @@ grub_xfs_fshelp_size(struct grub_xfs_data *data) + grub_xfs_inode_size(data); } -static void * +/* This should return void * but XFS code is error-prone with alignment, so + return char to retain cast-align. + */ +static char * grub_xfs_inode_data(struct grub_xfs_inode *inode) { if (inode->version <= 2) @@ -388,20 +397,20 @@ grub_xfs_inode_data(struct grub_xfs_inode *inode) 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))); + /* + With small inode numbers the header is 4 bytes smaller because of + smaller parent pointer + */ + return (struct grub_xfs_dir_entry *) + (((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); + return ((grub_uint8_t *)(de + 1)) + de->len - 1 + (data->hasftype ? 1 : 0); } static struct grub_xfs_dir_entry * @@ -445,14 +454,17 @@ grub_xfs_next_de(struct grub_xfs_data *data, struct grub_xfs_dir2_entry *de) return (struct grub_xfs_dir2_entry *)(((char *)de) + ALIGN_UP(size, 8)); } -static grub_uint64_t * +/* This should return void * but XFS code is error-prone with alignment, so + return char to retain cast-align. + */ +static char * grub_xfs_btree_keys(struct grub_xfs_data *data, struct grub_xfs_btree_node *leaf) { - grub_uint64_t *keys = (grub_uint64_t *)(leaf + 1); + char *keys = (char *)(leaf + 1); if (data->hascrc) - keys += 6; /* skip crc, uuid, ... */ + keys += 48; /* skip crc, uuid, ... */ return keys; } @@ -476,28 +488,34 @@ grub_xfs_read_inode (struct grub_xfs_data *data, grub_uint64_t ino, return 0; } +static grub_uint64_t +get_fsb (const void *keys, int idx) +{ + const char *p = (const char *) keys + sizeof(grub_uint64_t) * idx; + return grub_be_to_cpu64 (grub_get_unaligned64 (p)); +} static grub_disk_addr_t grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) { struct grub_xfs_btree_node *leaf = 0; int ex, nrec; - grub_xfs_extent *exts; + struct grub_xfs_extent *exts; grub_uint64_t ret = 0; if (node->inode.format == XFS_INODE_FORMAT_BTREE) { struct grub_xfs_btree_root *root; - const grub_uint64_t *keys; + const char *keys; int recoffset; leaf = grub_malloc (node->data->bsize); if (leaf == 0) return 0; - root = grub_xfs_inode_data(&node->inode); + root = (struct grub_xfs_btree_root *) grub_xfs_inode_data(&node->inode); nrec = grub_be_to_cpu16 (root->numrecs); - keys = &root->keys[0]; + keys = (char *) &root->keys[0]; if (node->inode.fork_offset) recoffset = (node->inode.fork_offset - 1) / 2; else @@ -510,7 +528,7 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) for (i = 0; i < nrec; i++) { - if (fileblock < grub_be_to_cpu64 (keys[i])) + if (fileblock < get_fsb(keys, i)) break; } @@ -520,8 +538,9 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) grub_free (leaf); return 0; } + if (grub_disk_read (node->data->disk, - GRUB_XFS_FSB_TO_BLOCK (node->data, grub_be_to_cpu64 (keys[i - 1 + recoffset])) << (node->data->sblock.log2_bsize - GRUB_DISK_SECTOR_BITS), + GRUB_XFS_FSB_TO_BLOCK (node->data, get_fsb (keys, i - 1 + recoffset)) << (node->data->sblock.log2_bsize - GRUB_DISK_SECTOR_BITS), 0, node->data->bsize, leaf)) return 0; @@ -542,12 +561,12 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) / (2 * sizeof (grub_uint64_t))); } while (leaf->level); - exts = (grub_xfs_extent *) keys; + exts = (struct grub_xfs_extent *) keys; } else if (node->inode.format == XFS_INODE_FORMAT_EXT) { nrec = grub_be_to_cpu32 (node->inode.nextents); - exts = grub_xfs_inode_data(&node->inode); + exts = (struct grub_xfs_extent *) grub_xfs_inode_data(&node->inode); } else { @@ -700,7 +719,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, { case XFS_INODE_FORMAT_INO: { - struct grub_xfs_dir_header *head = grub_xfs_inode_data(&diro->inode); + struct grub_xfs_dir_header *head = (struct grub_xfs_dir_header *) grub_xfs_inode_data(&diro->inode); struct grub_xfs_dir_entry *de = grub_xfs_inline_de(head); int smallino = !head->largeino; int i; From 61c778f6402d540a2da7b2d034de7a920ca38c1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bernhard=20=C3=9Cbelacker?= Date: Mon, 20 Jul 2015 14:06:45 +0200 Subject: [PATCH 080/106] loader/linux: Make trailer initrd entry aligned again. Regression from commit: loader/linux: do not pad initrd with zeroes at the end a8c473288d3f0a5e17a903a5121dea1a695dda3b Wimboot fails since the change above because it expects the "trailer" initrd element on an aligned address. This issue shows only when newc_name is used and the last initrd entry has a not aligned size. --- grub-core/loader/linux.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/grub-core/loader/linux.c b/grub-core/loader/linux.c index d2cd591f6..be6fa0f4d 100644 --- a/grub-core/loader/linux.c +++ b/grub-core/loader/linux.c @@ -213,6 +213,7 @@ grub_initrd_init (int argc, char *argv[], if (newc) { + initrd_ctx->size = ALIGN_UP (initrd_ctx->size, 4); initrd_ctx->size += ALIGN_UP (sizeof (struct newc_head) + sizeof ("TRAILER!!!") - 1, 4); free_dir (root); @@ -290,7 +291,11 @@ grub_initrd_load (struct grub_linux_initrd_context *initrd_ctx, ptr += cursize; } if (newc) - ptr = make_header (ptr, "TRAILER!!!", sizeof ("TRAILER!!!") - 1, 0, 0); + { + grub_memset (ptr, 0, ALIGN_UP_OVERHEAD (cursize, 4)); + ptr += ALIGN_UP_OVERHEAD (cursize, 4); + ptr = make_header (ptr, "TRAILER!!!", sizeof ("TRAILER!!!") - 1, 0, 0); + } free_dir (root); root = 0; return GRUB_ERR_NONE; From 5c46165a7cefe8b5319bdc10839a3bc5dee40826 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Wed, 22 Jul 2015 01:54:59 +0200 Subject: [PATCH 081/106] configure.ac: Handle powerpc64le compiler Also-by: Paulo Flabiano Smorigo --- configure.ac | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/configure.ac b/configure.ac index fd8a62ead..e54b9df12 100644 --- a/configure.ac +++ b/configure.ac @@ -116,6 +116,7 @@ if test "x$with_platform" = x; then x86_64-*) platform=pc ;; powerpc-*) platform=ieee1275 ;; powerpc64-*) platform=ieee1275 ;; + powerpc64le-*) platform=ieee1275 ;; sparc64-*) platform=ieee1275 ;; mipsel-*) platform=loongson ;; mips-*) platform=arc ;; @@ -138,6 +139,7 @@ case "$target_cpu"-"$platform" in x86_64-none) ;; x86_64-*) target_cpu=i386 ;; powerpc64-ieee1275) target_cpu=powerpc ;; + powerpc64le-ieee1275) target_cpu=powerpc ;; esac # Check if the platform is supported, make final adjustments. @@ -560,6 +562,41 @@ AC_COMPILE_IFELSE( ]])], [grub_cv_cc_target_clang=no], [grub_cv_cc_target_clang=yes])]) +if test x$target_cpu = xpowerpc; then + AC_CACHE_CHECK([for options to get big-endian compilation], grub_cv_target_cc_big_endian, [ + grub_cv_target_cc_big_endian=no + for cand in "-target powerpc -Wl,-EB" "-target powerpc" \ + "-target powerpc-linux-gnu -Wl,-EB" "-target powerpc-linux-gnu" \ + "-mbig-endian"; do + if test x"$grub_cv_target_cc_big_endian" != xno ; then + break + fi + CFLAGS="$TARGET_CFLAGS $cand -Werror" + AC_LINK_IFELSE([AC_LANG_PROGRAM([[ +#if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && (__ORDER_BIG_ENDIAN__ != __BYTE_ORDER__) +#error still little endian +#endif +asm (".globl start; start:"); +void __main (void); +void __main (void) {} +int main (void); +]], [[]])], + [grub_cv_target_cc_big_endian="$cand"], []) + done + ]) + + if test x"$grub_cv_target_cc_big_endian" = xno ; then + AC_MSG_ERROR([could not force big-endian]) + fi + + skip_linkflags="$(echo "$grub_cv_target_cc_big_endian"|sed 's@-Wl,-EB@@')" + + TARGET_CFLAGS="$TARGET_CFLAGS $skip_linkflags" + TARGET_CPPFLAGS="$TARGET_CPPFLAGS $skip_linkflags" + TARGET_CCASFLAGS="$TARGET_CCASFLAGS $skip_linkflags" + TARGET_LDFLAGS="$TARGET_LDFLAGS $grub_cv_target_cc_big_endian" +fi + AC_CACHE_CHECK([for options to compile assembly], [grub_cv_cc_target_asm_compile], [ test_program= case "x$target_cpu-$platform" in From 9f27f9f69163bf6b41d8b4dc959f1baefa6f674e Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Wed, 22 Jul 2015 01:57:40 +0200 Subject: [PATCH 082/106] dmraid_nvidia: Set a name to usable value to avoid null dereference. Reported by: Andrei Borzenkov --- grub-core/disk/dmraid_nvidia.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/disk/dmraid_nvidia.c b/grub-core/disk/dmraid_nvidia.c index 881508cf2..060279124 100644 --- a/grub-core/disk/dmraid_nvidia.c +++ b/grub-core/disk/dmraid_nvidia.c @@ -172,7 +172,7 @@ grub_dmraid_nv_detect (grub_disk_t disk, return grub_diskfilter_make_raid (sizeof (sb.array.signature), uuid, sb.array.total_volumes, - NULL, disk_size, + "nv", disk_size, sb.array.stripe_block_size, GRUB_RAID_LAYOUT_LEFT_ASYMMETRIC, level); From 389d509df0d59445b0efcc7c6138d743ad573765 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Wed, 22 Jul 2015 20:39:14 +0200 Subject: [PATCH 083/106] diskfilter: Make name a const char to fix compilation error. --- grub-core/disk/diskfilter.c | 2 +- include/grub/diskfilter.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/grub-core/disk/diskfilter.c b/grub-core/disk/diskfilter.c index c4f6678b6..6f901c0ad 100644 --- a/grub-core/disk/diskfilter.c +++ b/grub-core/disk/diskfilter.c @@ -1007,7 +1007,7 @@ grub_diskfilter_vg_register (struct grub_diskfilter_vg *vg) struct grub_diskfilter_vg * grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb, - char *name, grub_uint64_t disk_size, + const char *name, grub_uint64_t disk_size, grub_uint64_t stripe_size, int layout, int level) { diff --git a/include/grub/diskfilter.h b/include/grub/diskfilter.h index 1aedcd3df..d89273c1b 100644 --- a/include/grub/diskfilter.h +++ b/include/grub/diskfilter.h @@ -172,7 +172,7 @@ grub_diskfilter_unregister (grub_diskfilter_t diskfilter) struct grub_diskfilter_vg * grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb, - char *name, grub_uint64_t disk_size, + const char *name, grub_uint64_t disk_size, grub_uint64_t stripe_size, int layout, int level); From f250c337f1a5ab648709c899d14fcf086f5c3aff Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Wed, 22 Jul 2015 20:40:13 +0200 Subject: [PATCH 084/106] ARM: provide __aeabi_memclr* and __aeabi_memcpy* symbols Fixes compilation with recent clang. --- grub-core/kern/compiler-rt.c | 15 +++++++++++++++ include/grub/compiler-rt.h | 7 +++++++ 2 files changed, 22 insertions(+) diff --git a/grub-core/kern/compiler-rt.c b/grub-core/kern/compiler-rt.c index d4cc15513..5cfcb3907 100644 --- a/grub-core/kern/compiler-rt.c +++ b/grub-core/kern/compiler-rt.c @@ -381,9 +381,24 @@ __aeabi_idiv (grub_int32_t a, grub_int32_t b) __attribute__ ((alias ("__divsi3"))); void *__aeabi_memcpy (void *dest, const void *src, grub_size_t n) __attribute__ ((alias ("grub_memcpy"))); +void *__aeabi_memcpy4 (void *dest, const void *src, grub_size_t n) + __attribute__ ((alias ("grub_memcpy"))); +void *__aeabi_memcpy8 (void *dest, const void *src, grub_size_t n) + __attribute__ ((alias ("grub_memcpy"))); void *__aeabi_memset (void *s, int c, grub_size_t n) __attribute__ ((alias ("memset"))); +void +__aeabi_memclr (void *s, grub_size_t n) +{ + grub_memset (s, 0, n); +} + +void __aeabi_memclr4 (void *s, grub_size_t n) + __attribute__ ((alias ("__aeabi_memclr"))); +void __aeabi_memclr8 (void *s, grub_size_t n) + __attribute__ ((alias ("__aeabi_memclr"))); + int __aeabi_ulcmp (grub_uint64_t a, grub_uint64_t b) { diff --git a/include/grub/compiler-rt.h b/include/grub/compiler-rt.h index 9265c7e80..dc73649a5 100644 --- a/include/grub/compiler-rt.h +++ b/include/grub/compiler-rt.h @@ -88,7 +88,14 @@ EXPORT_FUNC (__aeabi_lmul) (grub_uint64_t a, grub_uint64_t b); void * EXPORT_FUNC (__aeabi_memcpy) (void *dest, const void *src, grub_size_t n); void * +EXPORT_FUNC (__aeabi_memcpy4) (void *dest, const void *src, grub_size_t n); +void * +EXPORT_FUNC (__aeabi_memcpy8) (void *dest, const void *src, grub_size_t n); +void * EXPORT_FUNC(__aeabi_memset) (void *s, int c, grub_size_t n); +void EXPORT_FUNC(__aeabi_memclr) (void *s, grub_size_t n); +void EXPORT_FUNC(__aeabi_memclr4) (void *s, grub_size_t n); +void EXPORT_FUNC(__aeabi_memclr8) (void *s, grub_size_t n); grub_uint64_t EXPORT_FUNC (__aeabi_lasr) (grub_uint64_t u, int b); From eecdbebc8416467c029ab05d1c457901c4701c26 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Wed, 22 Jul 2015 20:47:56 +0200 Subject: [PATCH 085/106] Remove mips_attributes. mips_attributes was introduced to work around clang problems with -msoft-float. Those problems are now fixed and moreover .gnu_attributes itself is unportable and creates problem with clang. Revert "mips: Fix soft-float handling." This partially reverts commit 6a4ecd276ed39f66be0ad6ff0f8ff67598098605. --- grub-core/boot/mips/startup_raw.S | 2 -- grub-core/kern/mips/cache.S | 2 -- grub-core/kern/mips/startup.S | 2 -- grub-core/lib/mips/relocator_asm.S | 2 -- include/grub/mips/kernel.h | 4 ---- 5 files changed, 12 deletions(-) diff --git a/grub-core/boot/mips/startup_raw.S b/grub-core/boot/mips/startup_raw.S index fd95c3134..ca3413bbe 100644 --- a/grub-core/boot/mips/startup_raw.S +++ b/grub-core/boot/mips/startup_raw.S @@ -21,7 +21,6 @@ #include #include #include -#include #include #define BASE_ADDR 8 @@ -33,7 +32,6 @@ .globl __start, _start, start .set noreorder .set nomacro - mips_attributes __start: _start: start: diff --git a/grub-core/kern/mips/cache.S b/grub-core/kern/mips/cache.S index e83960fcc..fa6897e14 100644 --- a/grub-core/kern/mips/cache.S +++ b/grub-core/kern/mips/cache.S @@ -1,10 +1,8 @@ #include -#include .set noreorder .set nomacro - mips_attributes FUNCTION (grub_arch_sync_caches) #include "cache_flush.S" diff --git a/grub-core/kern/mips/startup.S b/grub-core/kern/mips/startup.S index 337aca914..339ab337e 100644 --- a/grub-core/kern/mips/startup.S +++ b/grub-core/kern/mips/startup.S @@ -21,7 +21,6 @@ #include #include #include -#include #include #define BASE_ADDR 8 @@ -29,7 +28,6 @@ .globl __start, _start, start .set noreorder .set nomacro - mips_attributes __start: _start: start: diff --git a/grub-core/lib/mips/relocator_asm.S b/grub-core/lib/mips/relocator_asm.S index 959893ca9..1d142a4f3 100644 --- a/grub-core/lib/mips/relocator_asm.S +++ b/grub-core/lib/mips/relocator_asm.S @@ -17,13 +17,11 @@ */ #include -#include .p2align 4 /* force 16-byte alignment */ .set noreorder .set nomacro - mips_attributes VARIABLE (grub_relocator_forward_start) move $a0, $9 diff --git a/include/grub/mips/kernel.h b/include/grub/mips/kernel.h index d0e09ddc6..07b08848d 100644 --- a/include/grub/mips/kernel.h +++ b/include/grub/mips/kernel.h @@ -21,8 +21,4 @@ #include -#ifdef ASM_FILE -#define mips_attributes .gnu_attribute 4, 3 -#endif - #endif /* ! GRUB_KERNEL_MACHINE_HEADER */ From 80783ea646b98b263df30cb3c75cef773729a1b2 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Wed, 22 Jul 2015 21:40:55 +0200 Subject: [PATCH 086/106] fwstart: Replace blt with bltz. blt A, $zero, B and bltz A, B are equivalent but clang recognizes only later, so use it. Resulting binary is unchanged. --- grub-core/boot/mips/loongson/fwstart.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/boot/mips/loongson/fwstart.S b/grub-core/boot/mips/loongson/fwstart.S index 71bab6dc8..c95b38ac0 100644 --- a/grub-core/boot/mips/loongson/fwstart.S +++ b/grub-core/boot/mips/loongson/fwstart.S @@ -344,7 +344,7 @@ printhex: nop srl $t1, $a0, 28 addiu $t1, $t1, -10 - blt $t1, $zero, 2f + bltz $t1, 2f sll $a0, $a0, 4 addiu $t1, $t1, 'A'-10-'0' 2: addiu $t1, $t1, '0'+10 From 63411b14be3da8d376d9d52a06c08c8ae36761da Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Wed, 22 Jul 2015 21:41:58 +0200 Subject: [PATCH 087/106] fwstart: Add missing argument to p2align. Resulting binary is unchanged as it happens we were already aligned by chance. --- grub-core/boot/mips/loongson/fwstart.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/boot/mips/loongson/fwstart.S b/grub-core/boot/mips/loongson/fwstart.S index c95b38ac0..921dbd1f1 100644 --- a/grub-core/boot/mips/loongson/fwstart.S +++ b/grub-core/boot/mips/loongson/fwstart.S @@ -547,7 +547,7 @@ gpio_dump: #endif gpio_dump_end: - .p2align + .p2align 3 write_dumpreg: ld $t2, 0($t6) From 248bc1d0fcdd7729ee225de9e8a293b61d9a3de0 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Wed, 22 Jul 2015 21:42:41 +0200 Subject: [PATCH 088/106] fwstart: Fix loading of address of read_spd_fail. --- grub-core/boot/mips/loongson/fwstart.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/boot/mips/loongson/fwstart.S b/grub-core/boot/mips/loongson/fwstart.S index 921dbd1f1..28c634614 100644 --- a/grub-core/boot/mips/loongson/fwstart.S +++ b/grub-core/boot/mips/loongson/fwstart.S @@ -398,7 +398,7 @@ read_spd: move $t2, $a0 move $t3, $ra lui $a0, %hi(read_spd_fail) - addiu $a0, $a0, %hi(read_spd_fail) + addiu $a0, $a0, %lo(read_spd_fail) /* Send START. */ lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE_2F) From ca73ae446c426661a8f05196df279e8b973fead9 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Thu, 23 Jul 2015 02:15:46 +0200 Subject: [PATCH 089/106] arm-emu: Add __aeabi_memcpy* and __aeabi_memclr* symbols. Fixes compilation with clang. --- configure.ac | 2 +- include/grub/compiler-rt-emu.h | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index e54b9df12..c864311f7 100644 --- a/configure.ac +++ b/configure.ac @@ -1181,7 +1181,7 @@ fi # Check for libgcc symbols if test x"$platform" = xemu; then -AC_CHECK_FUNCS(__udivsi3 __umodsi3 __divsi3 __modsi3 __divdi3 __moddi3 __udivdi3 __umoddi3 __ctzdi2 __ctzsi2 __aeabi_uidiv __aeabi_uidivmod __aeabi_idiv __aeabi_idivmod __aeabi_ulcmp __muldi3 __aeabi_lmul __aeabi_memcpy __aeabi_memset __aeabi_lasr __aeabi_llsl __aeabi_llsr _restgpr_14_x __ucmpdi2 __ashldi3 __ashrdi3 __lshrdi3 __bswapsi2 __bswapdi2 __bzero __register_frame_info __deregister_frame_info ___chkstk_ms __chkstk_ms) +AC_CHECK_FUNCS(__udivsi3 __umodsi3 __divsi3 __modsi3 __divdi3 __moddi3 __udivdi3 __umoddi3 __ctzdi2 __ctzsi2 __aeabi_uidiv __aeabi_uidivmod __aeabi_idiv __aeabi_idivmod __aeabi_ulcmp __muldi3 __aeabi_lmul __aeabi_memcpy __aeabi_memcpy4 __aeabi_memcpy8 __aeabi_memclr __aeabi_memclr4 __aeabi_memclr8 __aeabi_memset __aeabi_lasr __aeabi_llsl __aeabi_llsr _restgpr_14_x __ucmpdi2 __ashldi3 __ashrdi3 __lshrdi3 __bswapsi2 __bswapdi2 __bzero __register_frame_info __deregister_frame_info ___chkstk_ms __chkstk_ms) fi if test "x$TARGET_APPLE_LINKER" = x1 ; then diff --git a/include/grub/compiler-rt-emu.h b/include/grub/compiler-rt-emu.h index edc82999e..b21425d9e 100644 --- a/include/grub/compiler-rt-emu.h +++ b/include/grub/compiler-rt-emu.h @@ -115,11 +115,36 @@ void * EXPORT_FUNC (__aeabi_memcpy) (void *dest, const void *src, grub_size_t n); #endif +#ifdef HAVE___AEABI_MEMCPY4 +void * +EXPORT_FUNC (__aeabi_memcpy4) (void *dest, const void *src, grub_size_t n); +#endif + +#ifdef HAVE___AEABI_MEMCPY8 +void * +EXPORT_FUNC (__aeabi_memcpy8) (void *dest, const void *src, grub_size_t n); +#endif + #ifdef HAVE___AEABI_MEMSET void * EXPORT_FUNC(__aeabi_memset) (void *s, int c, grub_size_t n); #endif +#ifdef HAVE___AEABI_MEMCLR +void * +EXPORT_FUNC(__aeabi_memclr) (void *s, grub_size_t n); +#endif + +#ifdef HAVE___AEABI_MEMCLR4 +void * +EXPORT_FUNC(__aeabi_memclr4) (void *s, grub_size_t n); +#endif + +#ifdef HAVE___AEABI_MEMCLR8 +void * +EXPORT_FUNC(__aeabi_memclr8) (void *s, grub_size_t n); +#endif + #ifdef HAVE___AEABI_LASR grub_uint64_t EXPORT_FUNC (__aeabi_lasr) (grub_uint64_t u, int b); From f34a42208153e520d5239be1cea2ca1fbfced9e0 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Thu, 23 Jul 2015 19:01:00 +0200 Subject: [PATCH 090/106] archelp: Fix handling of dot and dotdot at the end of the name. Fixes cpio_test and tar_test. --- grub-core/fs/archelp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/grub-core/fs/archelp.c b/grub-core/fs/archelp.c index c85cbfac2..707f9a658 100644 --- a/grub-core/fs/archelp.c +++ b/grub-core/fs/archelp.c @@ -34,12 +34,12 @@ canonicalize (char *name) iptr++; if (iptr[0] == '.' && (iptr[1] == '/' || iptr[1] == 0)) { - iptr += 2; + iptr++; continue; } if (iptr[0] == '.' && iptr[1] == '.' && (iptr[2] == '/' || iptr[2] == 0)) { - iptr += 3; + iptr += 2; if (optr == name) continue; for (optr -= 2; optr >= name && *optr != '/'; optr--); From d0d90d78485f9b53c80962faa617c30d55380032 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Thu, 23 Jul 2015 19:04:55 +0200 Subject: [PATCH 091/106] exclude.pot: Add missing blacklisted strings. --- po/exclude.pot | Bin 140095 -> 140903 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/po/exclude.pot b/po/exclude.pot index ab52e99905363232a840cf86e09563b5f8dba229..0a9b215eaf1971bf2a2af8a36e9605043de38e36 100644 GIT binary patch delta 430 zcmdmgjN|zkj)oS-ElmHECJQieO?OCQ)ECLgsZdBu%*;tmQP4;&D#|ZXP)(V;wV!6}I)iN&dt8JVR) z8kCJJ%wZbxi_-P-3sUoRtI~?CauSQufv(8OPtKlvQ4_3|*U-Wou2_HiL}y0n=>mHg zd8Qj2V&q{op1$x9qoja-T6ugyPGU(~eo=0Gac0$Y#`{2J51N3=q#GHzS@KIu3MM=H g$W5P6$H*yfVhZ<|t}aNbv_uKyoZ^xq1tlde08?O(c>n+a delta 50 zcmaEUhGYLRj)oS-ElmHECU3A1Vlp?Lele0!R6?~lCQr3k0gRNma*NZ8ONtbfl(+!q C+7Pe+ From 81ca24a59cdab59503a8f13586da3b62a52d7460 Mon Sep 17 00:00:00 2001 From: Ignat Korchagin Date: Thu, 23 Jul 2015 21:13:09 +0300 Subject: [PATCH 092/106] efi: fix memory leak in variable handling --- grub-core/kern/efi/efi.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c index 2e7783468..490edefe5 100644 --- a/grub-core/kern/efi/efi.c +++ b/grub-core/kern/efi/efi.c @@ -206,6 +206,7 @@ grub_efi_set_variable(const char *var, const grub_efi_guid_t *guid, | GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS | GRUB_EFI_VARIABLE_RUNTIME_ACCESS), datasize, data); + grub_free (var16); if (status == GRUB_EFI_SUCCESS) return GRUB_ERR_NONE; @@ -237,8 +238,11 @@ grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid, status = efi_call_5 (r->get_variable, var16, guid, NULL, &datasize, NULL); - if (!datasize) - return NULL; + if (status != GRUB_EFI_SUCCESS || !datasize) + { + grub_free (var16); + return NULL; + } data = grub_malloc (datasize); if (!data) From 02a249005fe5e53905fd809a74f65d1b1333a0e0 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Fri, 24 Jul 2015 01:13:27 +0200 Subject: [PATCH 093/106] reiserfs: Fix handling of first entry in the directory. Fixes garbage being added to "." filename. --- grub-core/fs/reiserfs.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/grub-core/fs/reiserfs.c b/grub-core/fs/reiserfs.c index b78166554..39736f63c 100644 --- a/grub-core/fs/reiserfs.c +++ b/grub-core/fs/reiserfs.c @@ -783,12 +783,30 @@ grub_reiserfs_iterate_dir (grub_fshelp_node_t item, struct grub_reiserfs_key entry_key; enum grub_fshelp_filetype entry_type; char *entry_name; + char *entry_name_end = 0; + char c; if (!(entry_state & GRUB_REISERFS_VISIBLE_MASK)) continue; entry_name = (((char *) directory_headers) + grub_le_to_cpu16 (directory_header->location)); + if (entry_number == 0) + { + entry_name_end = (char *) block_header + + grub_le_to_cpu16 (item_headers[block_position].item_location) + + grub_le_to_cpu16 (item_headers[block_position].item_size); + } + else + { + entry_name_end = (((char *) directory_headers) + + grub_le_to_cpu16 (directory_headers[entry_number - 1].location)); + } + if (entry_name_end < entry_name || entry_name_end > (char *) block_header + block_size) + { + entry_name_end = (char *) block_header + block_size; + } + entry_key.directory_id = directory_header->directory_id; entry_key.object_id = directory_header->object_id; entry_key.u.v2.offset_type = 0; @@ -935,7 +953,7 @@ grub_reiserfs_iterate_dir (grub_fshelp_node_t item, else { /* Pseudo file ".." never has stat block. */ - if (grub_strcmp (entry_name, "..")) + if (entry_name_end == entry_name + 2 && grub_memcmp (entry_name, "..", 2) != 0) grub_dprintf ("reiserfs", "Warning : %s has no stat block !\n", entry_name); @@ -943,18 +961,21 @@ grub_reiserfs_iterate_dir (grub_fshelp_node_t item, goto next; } } + + c = *entry_name_end; + *entry_name_end = 0; if (hook (entry_name, entry_type, entry_item, hook_data)) { + *entry_name_end = c; grub_dprintf ("reiserfs", "Found : %s, type=%d\n", entry_name, entry_type); ret = 1; goto found; } + *entry_name_end = c; next: - *entry_name = 0; /* Make sure next entry name (which is just - before this one in disk order) stops before - the current one. */ + ; } if (next_offset == 0) From 049dcfa03c2217f3af9f108d3f41229b8155c534 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Fri, 24 Jul 2015 01:15:32 +0200 Subject: [PATCH 094/106] xfs: Fix handling of symlink with crc-enabled filesystem. --- grub-core/fs/xfs.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c index 46de6aff3..a03526b32 100644 --- a/grub-core/fs/xfs.c +++ b/grub-core/fs/xfs.c @@ -604,13 +604,13 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) POS. Return the amount of read bytes in READ. */ static grub_ssize_t grub_xfs_read_file (grub_fshelp_node_t node, - grub_disk_read_hook_t read_hook, void *read_hook_data, - grub_off_t pos, grub_size_t len, char *buf) + grub_disk_read_hook_t read_hook, void *read_hook_data, + grub_off_t pos, grub_size_t len, char *buf, grub_uint32_t header_size) { return grub_fshelp_read_file (node->data->disk, node, read_hook, read_hook_data, pos, len, buf, grub_xfs_read_block, - grub_be_to_cpu64 (node->inode.size), + grub_be_to_cpu64 (node->inode.size) + header_size, node->data->sblock.log2_bsize - GRUB_DISK_SECTOR_BITS, 0); } @@ -619,7 +619,13 @@ grub_xfs_read_file (grub_fshelp_node_t node, static char * grub_xfs_read_symlink (grub_fshelp_node_t node) { - int size = grub_be_to_cpu64 (node->inode.size); + grub_ssize_t size = grub_be_to_cpu64 (node->inode.size); + + if (size < 0) + { + grub_error (GRUB_ERR_BAD_FS, "invalid symlink"); + return 0; + } switch (node->inode.format) { @@ -630,12 +636,17 @@ grub_xfs_read_symlink (grub_fshelp_node_t node) { char *symlink; grub_ssize_t numread; + int off = 0; + + if (node->data->hascrc) + off = 56; symlink = grub_malloc (size + 1); if (!symlink) return 0; - numread = grub_xfs_read_file (node, 0, 0, 0, size, symlink); + node->inode.size = grub_be_to_cpu64 (size + off); + numread = grub_xfs_read_file (node, 0, 0, off, size, symlink, off); if (numread != size) { grub_free (symlink); @@ -802,7 +813,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, numread = grub_xfs_read_file (dir, 0, 0, blk << dirblk_log2, - dirblk_size, dirblock); + dirblk_size, dirblock, 0); if (numread != dirblk_size) return 0; @@ -1034,7 +1045,7 @@ grub_xfs_read (grub_file_t file, char *buf, grub_size_t len) return grub_xfs_read_file (&data->diropen, file->read_hook, file->read_hook_data, - file->offset, len, buf); + file->offset, len, buf, 0); } From 900fca88ac7dd8a4767cd1edc71b8ee6737eaa75 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Fri, 24 Jul 2015 01:16:30 +0200 Subject: [PATCH 095/106] xfs_test: Test both crc and non-crc filesystems. --- tests/util/grub-fs-tester.in | 17 ++++++++++++++--- tests/xfs_test.in | 1 + 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/tests/util/grub-fs-tester.in b/tests/util/grub-fs-tester.in index 5107ca17a..6fcac31c3 100644 --- a/tests/util/grub-fs-tester.in +++ b/tests/util/grub-fs-tester.in @@ -40,6 +40,10 @@ case x"$fs" in MINLOGSECSIZE=9 # OS LIMITATION: GNU/Linux doesn't accept > 4096 MAXLOGSECSIZE=12;; + xxfs_crc) + MINLOGSECSIZE=9 + # OS LIMITATION: GNU/Linux doesn't accept > 1024 + MAXLOGSECSIZE=10;; xzfs*) # OS LIMITATION: zfs-fuse hangs when creating zpool with sectors <=256B. MINLOGSECSIZE=9 @@ -142,6 +146,10 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE + MINBLKSIZE=$SECSIZE # OS Limitation: GNU/Linux doesn't accept > 4096 MAXBLKSIZE=4096;; + xxfs_crc) + # OS Limitation: GNU/Linux doesn't accept != 1024 + MINBLKSIZE=1024 + MAXBLKSIZE=1024;; xudf) MINBLKSIZE=1024 MAXBLKSIZE=4096;; @@ -287,7 +295,7 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE + x"ufs1" | x"ufs1_sun" | x"ufs2") FSLABEL="grubtest""ieurrucnenreeiurueurewf";; # FS LIMITATION: XFS label is at most 12 UTF-8 characters - x"xfs") + x"xfs"|x"xfs_crc") FSLABEL="géт 😁к";; # FS LIMITATION: FAT labels limited to 11 characters, no international characters or lowercase x"vfat"* | xmsdos*) @@ -465,7 +473,7 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE + case x"$fs" in # FIXME: Not sure about BtrFS, NTFS, JFS, AFS, UDF and SFS. Check it. # FS LIMITATION: as far as I know those FS don't store their last modification date. - x"jfs_caseins" | x"jfs" | x"xfs"| x"btrfs"* | x"reiserfs_old" | x"reiserfs" \ + x"jfs_caseins" | x"jfs" | x"xfs" | x"xfs_crc" | x"btrfs"* | x"reiserfs_old" | x"reiserfs" \ | x"bfs" | x"afs" \ | x"tarfs" | x"cpio_"* | x"minix" | x"minix2" \ | x"minix3" | x"ntfs"* | x"udf" | x"sfs"*) @@ -758,7 +766,10 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE + xext*) MKE2FS_DEVICE_SECTSIZE=$SECSIZE "mkfs.$fs" -b $BLKSIZE -L "$FSLABEL" -q "${LODEVICES[0]}" ;; xxfs) - "mkfs.xfs" -b size=$BLKSIZE -s size=$SECSIZE -L "$FSLABEL" -q "${LODEVICES[0]}" ;; + "mkfs.xfs" -m crc=0 -b size=$BLKSIZE -s size=$SECSIZE -L "$FSLABEL" -q "${LODEVICES[0]}" ;; + xxfs_crc) + MOUNTFS="xfs" + "mkfs.xfs" -m crc=1 -b size=$BLKSIZE -s size=$SECSIZE -L "$FSLABEL" -q "${LODEVICES[0]}" ;; *) echo "Add appropriate mkfs command here" exit 1 diff --git a/tests/xfs_test.in b/tests/xfs_test.in index 173b1cfe6..3807e2e5c 100644 --- a/tests/xfs_test.in +++ b/tests/xfs_test.in @@ -16,4 +16,5 @@ if ! which mkfs.xfs >/dev/null 2>&1; then fi +"@builddir@/grub-fs-tester" xfs_crc "@builddir@/grub-fs-tester" xfs From 333855c6469d52a7a555ea55834182603981ea0e Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Fri, 24 Jul 2015 01:17:04 +0200 Subject: [PATCH 096/106] zfs_test: Skip dotdot in volume root test. Given special semantics of ZFS it's far from clear what the expected result is. Just skip it for now --- tests/util/grub-fs-tester.in | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/tests/util/grub-fs-tester.in b/tests/util/grub-fs-tester.in index 6fcac31c3..29ae69153 100644 --- a/tests/util/grub-fs-tester.in +++ b/tests/util/grub-fs-tester.in @@ -1149,18 +1149,19 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE + case x"$fs" in x"zfs"*) - LSROUT=$(run_grubfstest ls -- -la "($GRUBDEVICE)/grub fs@/..");; + ;; *) - LSROUT=$(run_grubfstest ls -- -la "($GRUBDEVICE)/..");; + LSROUT=$(run_grubfstest ls -- -la "($GRUBDEVICE)/.."); + if echo "$LSROUT" | grep -F " $BASEFILE" | grep "$BLOCKCNT" > /dev/null; then + : + else + echo DOTDOT IN ROOTDIR FAIL + echo "$LSROUT" + TZ=UTC ls --time-style=+%Y%m%d%H%M%S.%N -l "$MNTPOINTRO" + exit 1 + fi + ;; esac - if echo "$LSROUT" | grep -F " $BASEFILE" | grep "$BLOCKCNT" > /dev/null; then - : - else - echo DOTDOT IN ROOTDIR FAIL - echo "$LSROUT" - TZ=UTC ls --time-style=+%Y%m%d%H%M%S.%N -l "$MNTPOINTRO" - exit 1 - fi case x"$fs" in x"zfs"*) From d5847bf59443ef54c838fe5be1ecd47443c7807b Mon Sep 17 00:00:00 2001 From: Ignat Korchagin Date: Fri, 24 Jul 2015 20:46:02 +0300 Subject: [PATCH 097/106] efi: fix GetVariable return status check in 81ca24a GetVariable should return EFI_BUFFER_TOO_SMALL if given buffer of size zero; commit incorrectly checked for EFI_SUCCESS. --- grub-core/kern/efi/efi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c index 490edefe5..caf9bcc41 100644 --- a/grub-core/kern/efi/efi.c +++ b/grub-core/kern/efi/efi.c @@ -238,7 +238,7 @@ grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid, status = efi_call_5 (r->get_variable, var16, guid, NULL, &datasize, NULL); - if (status != GRUB_EFI_SUCCESS || !datasize) + if (status != GRUB_EFI_BUFFER_TOO_SMALL || !datasize) { grub_free (var16); return NULL; From 368ecfc3a031bd3b03bcaae776d6f276f79af157 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Mon, 27 Jul 2015 12:39:41 +0200 Subject: [PATCH 098/106] Add transform_data as a variant of data with substitutions. This fixrs name mismatch for grub.chrp with transform_program_name='s,grub,grub2,g' --- gentpl.py | 15 +++++++++++++++ grub-core/Makefile.core.def | 14 +++++++------- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/gentpl.py b/gentpl.py index 37b1f45bf..76971d3ce 100644 --- a/gentpl.py +++ b/gentpl.py @@ -834,6 +834,20 @@ def data(defn, platform): var_add("dist_" + installdir(defn) + "_DATA", platform_sources(defn, platform)) gvar_add("dist_noinst_DATA", extra_dist(defn)) +def transform_data(defn, platform): + name = defn['name'] + + var_add(installdir(defn) + "_DATA", name) + + rule(name, "$(top_builddir)/config.status " + platform_sources(defn, platform) + platform_dependencies(defn, platform), """ +(for x in """ + platform_sources(defn, platform) + """; do cat $(srcdir)/"$$x"; done) | $(top_builddir)/config.status --file=$@:- +chmod a+x """ + name + """ +""") + + gvar_add("CLEANFILES", name) + gvar_add("EXTRA_DIST", extra_dist(defn)) + gvar_add("dist_noinst_DATA", platform_sources(defn, platform)) + def script(defn, platform): name = defn['name'] @@ -881,6 +895,7 @@ rules("library", library) rules("program", program) rules("script", script) rules("data", data) +rules("transform_data", transform_data) write_output(section='decl') write_output() diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index a6101dec7..9764cd235 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1,43 +1,43 @@ AutoGen definitions Makefile.tpl; -script = { +transform_data = { installdir = noinst; name = gensyminfo.sh; common = gensyminfo.sh.in; }; -script = { +transform_data = { installdir = noinst; name = genmod.sh; common = genmod.sh.in; }; -script = { +transform_data = { installdir = noinst; name = modinfo.sh; common = modinfo.sh.in; }; -script = { +transform_data = { installdir = platform; name = gmodule.pl; common = gmodule.pl.in; }; -script = { +transform_data = { installdir = platform; name = gdb_grub; common = gdb_grub.in; }; -script = { +transform_data = { installdir = platform; name = grub.chrp; common = boot/powerpc/grub.chrp.in; enable = powerpc_ieee1275; }; -script = { +transform_data = { installdir = platform; name = bootinfo.txt; common = boot/powerpc/bootinfo.txt.in; From a2721778e5234fc87af7c3bf2b7cfdaca3abfa60 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Mon, 27 Jul 2015 12:42:47 +0200 Subject: [PATCH 099/106] grub-install: Use a+ in fopen rather than r+. r+ does not create a file if none exists. --- util/grub-install.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/grub-install.c b/util/grub-install.c index 566272600..df5c7e520 100644 --- a/util/grub-install.c +++ b/util/grub-install.c @@ -1727,7 +1727,7 @@ main (int argc, char *argv[]) grub_elf = grub_util_path_concat (2, core_services, "grub.elf"); grub_install_copy_file (imgfile, grub_elf, 1); - f = grub_util_fopen (mach_kernel, "r+"); + f = grub_util_fopen (mach_kernel, "a+"); if (!f) grub_util_error (_("Can't create file: %s"), strerror (errno)); fclose (f); From 4622f4e1ee569d5841bf8bb080430dc28b1c5665 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Mon, 27 Jul 2015 12:44:19 +0200 Subject: [PATCH 100/106] Switch procfs to use archelp. This fixes handling of "." and "..". --- Makefile.util.def | 2 +- grub-core/fs/proc.c | 84 ++++++++++++++++++++++++++++++--------------- 2 files changed, 58 insertions(+), 28 deletions(-) diff --git a/Makefile.util.def b/Makefile.util.def index 3cb6b21d3..db7e8ec2a 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -48,6 +48,7 @@ library = { common = grub-core/partmap/gpt.c; common = grub-core/partmap/msdos.c; common = grub-core/fs/proc.c; + common = grub-core/fs/archelp.c; }; library = { @@ -91,7 +92,6 @@ library = { common = grub-core/fs/bfs.c; common = grub-core/fs/btrfs.c; common = grub-core/fs/cbfs.c; - common = grub-core/fs/archelp.c; common = grub-core/fs/cpio.c; common = grub-core/fs/cpio_be.c; common = grub-core/fs/odc.c; diff --git a/grub-core/fs/proc.c b/grub-core/fs/proc.c index a03469ec6..31f3aa9a4 100644 --- a/grub-core/fs/proc.c +++ b/grub-core/fs/proc.c @@ -22,6 +22,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -74,6 +75,44 @@ grub_procdev_write (grub_disk_t disk __attribute ((unused)), return GRUB_ERR_OUT_OF_RANGE; } +struct grub_archelp_data +{ + struct grub_procfs_entry *entry, *next_entry; +}; + +static void +grub_procfs_rewind (struct grub_archelp_data *data) +{ + data->entry = NULL; + data->next_entry = grub_procfs_entries; +} + +static grub_err_t +grub_procfs_find_file (struct grub_archelp_data *data, char **name, + grub_int32_t *mtime, + grub_uint32_t *mode) +{ + data->entry = data->next_entry; + if (!data->entry) + { + *mode = GRUB_ARCHELP_ATTR_END; + return GRUB_ERR_NONE; + } + data->next_entry = data->entry->next; + *mode = GRUB_ARCHELP_ATTR_FILE | GRUB_ARCHELP_ATTR_NOTIME; + *name = grub_strdup (data->entry->name); + *mtime = 0; + if (!*name) + return grub_errno; + return GRUB_ERR_NONE; +} + +static struct grub_archelp_ops arcops = + { + .find_file = grub_procfs_find_file, + .rewind = grub_procfs_rewind + }; + static grub_ssize_t grub_procfs_read (grub_file_t file, char *buf, grub_size_t len) { @@ -99,44 +138,35 @@ static grub_err_t grub_procfs_dir (grub_device_t device, const char *path, grub_fs_dir_hook_t hook, void *hook_data) { - const char *ptr; - struct grub_dirhook_info info; - struct grub_procfs_entry *entry; - - grub_memset (&info, 0, sizeof (info)); + struct grub_archelp_data data; /* Check if the disk is our dummy disk. */ if (grub_strcmp (device->disk->name, "proc")) return grub_error (GRUB_ERR_BAD_FS, "not a procfs"); - for (ptr = path; *ptr == '/'; ptr++); - if (*ptr) - return 0; - FOR_LIST_ELEMENTS((entry), (grub_procfs_entries)) - if (hook (entry->name, &info, hook_data)) - return 0; - return 0; + + grub_procfs_rewind (&data); + + return grub_archelp_dir (&data, &arcops, + path, hook, hook_data); } static grub_err_t grub_procfs_open (struct grub_file *file, const char *path) { - const char *pathptr; - struct grub_procfs_entry *entry; + grub_err_t err; + struct grub_archelp_data data; + grub_size_t sz; - for (pathptr = path; *pathptr == '/'; pathptr++); + grub_procfs_rewind (&data); - FOR_LIST_ELEMENTS((entry), (grub_procfs_entries)) - if (grub_strcmp (pathptr, entry->name) == 0) - { - grub_size_t sz; - file->data = entry->get_contents (&sz); - if (!file->data) - return grub_errno; - file->size = sz; - return GRUB_ERR_NONE; - } - - return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), path); + err = grub_archelp_open (&data, &arcops, path); + if (err) + return err; + file->data = data.entry->get_contents (&sz); + if (!file->data) + return grub_errno; + file->size = sz; + return GRUB_ERR_NONE; } static struct grub_disk_dev grub_procfs_dev = { From fa93b0e4f5dd8d218da1c32c71c2bffd48eab89b Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Mon, 27 Jul 2015 12:45:35 +0200 Subject: [PATCH 101/106] fshelp: Add handling of "." and ".." and grub_fshelp_find_file_lookup. Recent tests have discovered that many of our filesystems have flawed handling of "." and "..". Rather than attempting to fix it in filesystems themselves, make the common code fshelp aware of "." and ".." and handle them in this layer. Add grub_fshelp_find_file_lookup for easy conversion of BFS, HFS and exFAT which have the same problem and don't use fshelp. --- grub-core/fs/fshelp.c | 324 ++++++++++++++++++++++++++++-------------- include/grub/fshelp.h | 11 ++ 2 files changed, 228 insertions(+), 107 deletions(-) diff --git a/grub-core/fs/fshelp.c b/grub-core/fs/fshelp.c index b899bed04..4c902adf3 100644 --- a/grub-core/fs/fshelp.c +++ b/grub-core/fs/fshelp.c @@ -30,169 +30,287 @@ GRUB_MOD_LICENSE ("GPLv3+"); typedef int (*iterate_dir_func) (grub_fshelp_node_t dir, grub_fshelp_iterate_dir_hook_t hook, void *data); +typedef grub_err_t (*lookup_file_func) (grub_fshelp_node_t dir, + const char *name, + grub_fshelp_node_t *foundnode, + enum grub_fshelp_filetype *foundtype); typedef char *(*read_symlink_func) (grub_fshelp_node_t node); +struct stack_element { + struct stack_element *parent; + grub_fshelp_node_t node; + enum grub_fshelp_filetype type; +}; + /* Context for grub_fshelp_find_file. */ struct grub_fshelp_find_file_ctx { + /* Inputs. */ const char *path; - grub_fshelp_node_t rootnode, currroot, currnode, oldnode; - enum grub_fshelp_filetype foundtype; + grub_fshelp_node_t rootnode; + + /* Global options. */ int symlinknest; - const char *name; - const char *next; - enum grub_fshelp_filetype type; + + /* Current file being traversed and its parents. */ + struct stack_element *currnode; }; /* Helper for find_file_iter. */ static void free_node (grub_fshelp_node_t node, struct grub_fshelp_find_file_ctx *ctx) { - if (node != ctx->rootnode && node != ctx->currroot) + if (node != ctx->rootnode) grub_free (node); } +static void +pop_element (struct grub_fshelp_find_file_ctx *ctx) +{ + struct stack_element *el; + el = ctx->currnode; + ctx->currnode = el->parent; + free_node (el->node, ctx); + grub_free (el); +} + +static void +free_stack (struct grub_fshelp_find_file_ctx *ctx) +{ + while (ctx->currnode) + pop_element (ctx); +} + +static void +go_up_a_level (struct grub_fshelp_find_file_ctx *ctx) +{ + if (!ctx->currnode->parent) + return; + pop_element (ctx); +} + +static grub_err_t +push_node (struct grub_fshelp_find_file_ctx *ctx, grub_fshelp_node_t node, enum grub_fshelp_filetype filetype) +{ + struct stack_element *nst; + nst = grub_malloc (sizeof (*nst)); + if (!nst) + return grub_errno; + nst->node = node; + nst->type = filetype & ~GRUB_FSHELP_CASE_INSENSITIVE; + nst->parent = ctx->currnode; + ctx->currnode = nst; + return GRUB_ERR_NONE; +} + +static grub_err_t +go_to_root (struct grub_fshelp_find_file_ctx *ctx) +{ + free_stack (ctx); + return push_node (ctx, ctx->rootnode, GRUB_FSHELP_DIR); +} + +struct grub_fshelp_find_file_iter_ctx +{ + const char *name; + grub_fshelp_node_t *foundnode; + enum grub_fshelp_filetype *foundtype; +}; + /* Helper for grub_fshelp_find_file. */ static int find_file_iter (const char *filename, enum grub_fshelp_filetype filetype, grub_fshelp_node_t node, void *data) { - struct grub_fshelp_find_file_ctx *ctx = data; + struct grub_fshelp_find_file_iter_ctx *ctx = data; if (filetype == GRUB_FSHELP_UNKNOWN || ((filetype & GRUB_FSHELP_CASE_INSENSITIVE) - ? grub_strncasecmp (ctx->name, filename, ctx->next - ctx->name) - : grub_strncmp (ctx->name, filename, ctx->next - ctx->name)) - || filename[ctx->next - ctx->name]) + ? grub_strcasecmp (ctx->name, filename) + : grub_strcmp (ctx->name, filename))) { grub_free (node); return 0; } /* The node is found, stop iterating over the nodes. */ - ctx->type = filetype & ~GRUB_FSHELP_CASE_INSENSITIVE; - ctx->oldnode = ctx->currnode; - ctx->currnode = node; - + *ctx->foundnode = node; + *ctx->foundtype = filetype; return 1; } static grub_err_t -find_file (const char *currpath, grub_fshelp_node_t currroot, - grub_fshelp_node_t *currfound, - iterate_dir_func iterate_dir, read_symlink_func read_symlink, +directory_find_file (grub_fshelp_node_t node, const char *name, grub_fshelp_node_t *foundnode, + enum grub_fshelp_filetype *foundtype, iterate_dir_func iterate_dir) +{ + int found; + struct grub_fshelp_find_file_iter_ctx ctx = { + .foundnode = foundnode, + .foundtype = foundtype, + .name = name + }; + found = iterate_dir (node, find_file_iter, &ctx); + if (! found) + { + if (grub_errno) + return grub_errno; + } + return GRUB_ERR_NONE; +} + +static grub_err_t +find_file (char *currpath, + iterate_dir_func iterate_dir, lookup_file_func lookup_file, + read_symlink_func read_symlink, struct grub_fshelp_find_file_ctx *ctx) { - ctx->currroot = currroot; - ctx->name = currpath; - ctx->type = GRUB_FSHELP_DIR; - ctx->currnode = currroot; - ctx->oldnode = currroot; - - for (;;) + char *name, *next; + grub_err_t err; + for (name = currpath; ; name = next) { - int found; + char c; + grub_fshelp_node_t foundnode = NULL; + enum grub_fshelp_filetype foundtype = 0; /* Remove all leading slashes. */ - while (*ctx->name == '/') - ctx->name++; + while (*name == '/') + name++; /* Found the node! */ - if (! *ctx->name) - { - *currfound = ctx->currnode; - ctx->foundtype = ctx->type; - return 0; - } + if (! *name) + return 0; /* Extract the actual part from the pathname. */ - for (ctx->next = ctx->name; *ctx->next && *ctx->next != '/'; ctx->next++); + for (next = name; *next && *next != '/'; next++); /* At this point it is expected that the current node is a directory, check if this is true. */ - if (ctx->type != GRUB_FSHELP_DIR) + if (ctx->currnode->type != GRUB_FSHELP_DIR) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); + + /* Don't rely on fs providing actual . in the listing. */ + if (next - name == 1 && name[0] == '.') + continue; + + /* Don't rely on fs providing actual .. in the listing. */ + if (next - name == 2 && name[0] == '.' && name[1] == '.') { - free_node (ctx->currnode, ctx); - ctx->currnode = 0; - return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); + go_up_a_level (ctx); + continue; } /* Iterate over the directory. */ - found = iterate_dir (ctx->currnode, find_file_iter, ctx); - if (! found) - { - free_node (ctx->currnode, ctx); - ctx->currnode = 0; - if (grub_errno) - return grub_errno; + c = *next; + *next = '\0'; + if (lookup_file) + err = lookup_file (ctx->currnode->node, name, &foundnode, &foundtype); + else + err = directory_find_file (ctx->currnode->node, name, &foundnode, &foundtype, iterate_dir); + *next = c; - break; - } + if (err) + return err; + if (!foundnode) + break; + + push_node (ctx, foundnode, foundtype); + /* Read in the symlink and follow it. */ - if (ctx->type == GRUB_FSHELP_SYMLINK) + if (ctx->currnode->type == GRUB_FSHELP_SYMLINK) { char *symlink; - const char *next; /* Test if the symlink does not loop. */ if (++ctx->symlinknest == 8) - { - free_node (ctx->currnode, ctx); - free_node (ctx->oldnode, ctx); - ctx->currnode = 0; - ctx->oldnode = 0; - return grub_error (GRUB_ERR_SYMLINK_LOOP, - N_("too deep nesting of symlinks")); - } + return grub_error (GRUB_ERR_SYMLINK_LOOP, + N_("too deep nesting of symlinks")); - symlink = read_symlink (ctx->currnode); - free_node (ctx->currnode, ctx); - ctx->currnode = 0; + symlink = read_symlink (ctx->currnode->node); if (!symlink) - { - free_node (ctx->oldnode, ctx); - ctx->oldnode = 0; - return grub_errno; - } + return grub_errno; /* The symlink is an absolute path, go back to the root inode. */ if (symlink[0] == '/') { - free_node (ctx->oldnode, ctx); - ctx->oldnode = ctx->rootnode; + err = go_to_root (ctx); + if (err) + return err; + } + else + { + /* Get from symlink to containing directory. */ + go_up_a_level (ctx); } + /* Lookup the node the symlink points to. */ - next = ctx->next; - find_file (symlink, ctx->oldnode, &ctx->currnode, - iterate_dir, read_symlink, ctx); - ctx->next = next; - ctx->type = ctx->foundtype; + find_file (symlink, iterate_dir, lookup_file, read_symlink, ctx); grub_free (symlink); if (grub_errno) - { - free_node (ctx->oldnode, ctx); - ctx->oldnode = 0; - return grub_errno; - } + return grub_errno; } - - if (ctx->oldnode != ctx->currnode) - { - free_node (ctx->oldnode, ctx); - ctx->oldnode = 0; - } - - ctx->name = ctx->next; } return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), ctx->path); } +static grub_err_t +grub_fshelp_find_file_real (const char *path, grub_fshelp_node_t rootnode, + grub_fshelp_node_t *foundnode, + iterate_dir_func iterate_dir, + lookup_file_func lookup_file, + read_symlink_func read_symlink, + enum grub_fshelp_filetype expecttype) +{ + struct grub_fshelp_find_file_ctx ctx = { + .path = path, + .rootnode = rootnode, + .symlinknest = 0, + .currnode = 0 + }; + grub_err_t err; + enum grub_fshelp_filetype foundtype; + char *duppath; + + if (!path || path[0] != '/') + { + return grub_error (GRUB_ERR_BAD_FILENAME, N_("invalid file name `%s'"), path); + } + + err = go_to_root (&ctx); + if (err) + return err; + + duppath = grub_strdup (path); + if (!duppath) + return grub_errno; + err = find_file (duppath, iterate_dir, lookup_file, read_symlink, &ctx); + grub_free (duppath); + if (err) + { + free_stack (&ctx); + return err; + } + + *foundnode = ctx.currnode->node; + foundtype = ctx.currnode->type; + /* Avoid the node being freed. */ + ctx.currnode->node = 0; + free_stack (&ctx); + + /* Check if the node that was found was of the expected type. */ + if (expecttype == GRUB_FSHELP_REG && foundtype != expecttype) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a regular file")); + else if (expecttype == GRUB_FSHELP_DIR && foundtype != expecttype) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); + + return 0; +} + /* Lookup the node PATH. The node ROOTNODE describes the root of the directory tree. The node found is returned in FOUNDNODE, which is either a ROOTNODE or a new malloc'ed node. ITERATE_DIR is used to @@ -207,31 +325,23 @@ grub_fshelp_find_file (const char *path, grub_fshelp_node_t rootnode, read_symlink_func read_symlink, enum grub_fshelp_filetype expecttype) { - struct grub_fshelp_find_file_ctx ctx = { - .path = path, - .rootnode = rootnode, - .foundtype = GRUB_FSHELP_DIR, - .symlinknest = 0 - }; - grub_err_t err; + return grub_fshelp_find_file_real (path, rootnode, foundnode, + iterate_dir, NULL, + read_symlink, expecttype); - if (!path || path[0] != '/') - { - grub_error (GRUB_ERR_BAD_FILENAME, N_("invalid file name `%s'"), path); - return grub_errno; - } +} - err = find_file (path, rootnode, foundnode, iterate_dir, read_symlink, &ctx); - if (err) - return err; +grub_err_t +grub_fshelp_find_file_lookup (const char *path, grub_fshelp_node_t rootnode, + grub_fshelp_node_t *foundnode, + lookup_file_func lookup_file, + read_symlink_func read_symlink, + enum grub_fshelp_filetype expecttype) +{ + return grub_fshelp_find_file_real (path, rootnode, foundnode, + NULL, lookup_file, + read_symlink, expecttype); - /* Check if the node that was found was of the expected type. */ - if (expecttype == GRUB_FSHELP_REG && ctx.foundtype != expecttype) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a regular file")); - else if (expecttype == GRUB_FSHELP_DIR && ctx.foundtype != expecttype) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); - - return 0; } /* Read LEN bytes from the file NODE on disk DISK into the buffer BUF, diff --git a/include/grub/fshelp.h b/include/grub/fshelp.h index 38923044c..eb1ba4f6c 100644 --- a/include/grub/fshelp.h +++ b/include/grub/fshelp.h @@ -62,6 +62,17 @@ EXPORT_FUNC(grub_fshelp_find_file) (const char *path, enum grub_fshelp_filetype expect); +grub_err_t +EXPORT_FUNC(grub_fshelp_find_file_lookup) (const char *path, + grub_fshelp_node_t rootnode, + grub_fshelp_node_t *foundnode, + grub_err_t (*lookup_file) (grub_fshelp_node_t dir, + const char *name, + grub_fshelp_node_t *foundnode, + enum grub_fshelp_filetype *foundtype), + char *(*read_symlink) (grub_fshelp_node_t node), + enum grub_fshelp_filetype expect); + /* Read LEN bytes from the file NODE on disk DISK into the buffer BUF, beginning with the block POS. READ_HOOK should be set before reading a block from the file. GET_BLOCK is used to translate file From d1d3a60b713f4075d7ed337a6cd942fad690f004 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Mon, 27 Jul 2015 12:48:38 +0200 Subject: [PATCH 102/106] BFS: Convert to fshelp. BFS doesn't handle ".." correctly, so convert it to fshelp to reuse the logic. --- grub-core/fs/bfs.c | 221 +++++++++++++++++++++------------------------ 1 file changed, 104 insertions(+), 117 deletions(-) diff --git a/grub-core/fs/bfs.c b/grub-core/fs/bfs.c index 145e77186..d2b490bce 100644 --- a/grub-core/fs/bfs.c +++ b/grub-core/fs/bfs.c @@ -29,6 +29,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -561,10 +562,10 @@ iterate_in_b_tree (grub_disk_t disk, } static int -bfs_strcmp (const char *a, const char *b, grub_size_t alen, grub_size_t blen) +bfs_strcmp (const char *a, const char *b, grub_size_t alen) { char ac, bc; - while (blen && alen) + while (*b && alen) { if (*a != *b) break; @@ -572,11 +573,10 @@ bfs_strcmp (const char *a, const char *b, grub_size_t alen, grub_size_t blen) a++; b++; alen--; - blen--; } ac = alen ? *a : 0; - bc = blen ? *b : 0; + bc = *b; #ifdef MODE_AFS return (int) (grub_int8_t) ac - (int) (grub_int8_t) bc; @@ -589,7 +589,6 @@ static grub_err_t find_in_b_tree (grub_disk_t disk, const struct grub_bfs_superblock *sb, const struct grub_bfs_inode *ino, const char *name, - grub_size_t name_len, grub_uint64_t * res) { struct grub_bfs_btree_header head; @@ -637,7 +636,7 @@ find_in_b_tree (grub_disk_t disk, end = grub_bfs_to_cpu16 (keylen_idx[(i | (1 << j))]); if (grub_bfs_to_cpu_treehead (node->total_key_len) <= end) end = grub_bfs_to_cpu_treehead (node->total_key_len); - cmp = bfs_strcmp (key_data + start, name, end - start, name_len); + cmp = bfs_strcmp (key_data + start, name, end - start); if (cmp == 0 && level == 0) { *res = grub_bfs_to_cpu64 (key_values[i | (1 << j)].val); @@ -658,7 +657,7 @@ find_in_b_tree (grub_disk_t disk, end = grub_bfs_to_cpu16 (keylen_idx[0]); if (grub_bfs_to_cpu_treehead (node->total_key_len) <= end) end = grub_bfs_to_cpu_treehead (node->total_key_len); - cmp = bfs_strcmp (key_data, name, end, name_len); + cmp = bfs_strcmp (key_data, name, end); if (cmp == 0 && level == 0) { *res = grub_bfs_to_cpu64 (key_values[0].val); @@ -707,127 +706,119 @@ find_in_b_tree (grub_disk_t disk, } } +struct grub_fshelp_node +{ + grub_disk_t disk; + const struct grub_bfs_superblock *sb; + struct grub_bfs_inode ino; +}; + static grub_err_t -hop_level (grub_disk_t disk, - const struct grub_bfs_superblock *sb, - struct grub_bfs_inode *ino, const char *name, - const char *name_end) +lookup_file (grub_fshelp_node_t dir, + const char *name, + grub_fshelp_node_t *foundnode, + enum grub_fshelp_filetype *foundtype) { grub_err_t err; + struct grub_bfs_inode *new_ino; grub_uint64_t res = 0; - if (((grub_bfs_to_cpu32 (ino->mode) & ATTR_TYPE) != ATTR_DIR)) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); - - err = find_in_b_tree (disk, sb, ino, name, name_end - name, &res); + err = find_in_b_tree (dir->disk, dir->sb, &dir->ino, name, &res); if (err) return err; - return grub_disk_read (disk, res - << (grub_bfs_to_cpu32 (sb->log2_bsize) - - GRUB_DISK_SECTOR_BITS), 0, - sizeof (*ino), (char *) ino); + *foundnode = grub_malloc (sizeof (struct grub_fshelp_node)); + if (!*foundnode) + return grub_errno; + + (*foundnode)->disk = dir->disk; + (*foundnode)->sb = dir->sb; + new_ino = &(*foundnode)->ino; + + if (grub_disk_read (dir->disk, res + << (grub_bfs_to_cpu32 (dir->sb->log2_bsize) + - GRUB_DISK_SECTOR_BITS), 0, + sizeof (*new_ino), (char *) new_ino)) + { + grub_free (*foundnode); + return grub_errno; + } + switch (grub_bfs_to_cpu32 (new_ino->mode) & ATTR_TYPE) + { + default: + case ATTR_REG: + *foundtype = GRUB_FSHELP_REG; + break; + case ATTR_DIR: + *foundtype = GRUB_FSHELP_DIR; + break; + case ATTR_LNK: + *foundtype = GRUB_FSHELP_SYMLINK; + break; + } + return GRUB_ERR_NONE; +} + +static char * +read_symlink (grub_fshelp_node_t node) +{ + char *alloc = NULL; + grub_err_t err; + +#ifndef MODE_AFS + if (!(grub_bfs_to_cpu32 (node->ino.flags) & LONG_SYMLINK)) + { + alloc = grub_malloc (sizeof (node->ino.inplace_link) + 1); + if (!alloc) + { + return NULL; + } + grub_memcpy (alloc, node->ino.inplace_link, + sizeof (node->ino.inplace_link)); + alloc[sizeof (node->ino.inplace_link)] = 0; + } + else +#endif + { + grub_size_t symsize = grub_bfs_to_cpu64 (node->ino.size); + alloc = grub_malloc (symsize + 1); + if (!alloc) + return NULL; + err = read_bfs_file (node->disk, node->sb, &node->ino, 0, alloc, symsize, 0, 0); + if (err) + { + grub_free (alloc); + return NULL; + } + alloc[symsize] = 0; + } + + return alloc; } static grub_err_t find_file (const char *path, grub_disk_t disk, - const struct grub_bfs_superblock *sb, struct grub_bfs_inode *ino) + const struct grub_bfs_superblock *sb, struct grub_bfs_inode *ino, + enum grub_fshelp_filetype exptype) { - const char *ptr, *next = path; - char *alloc = NULL; - char *wptr; grub_err_t err; - struct grub_bfs_inode old_ino; - unsigned symlinks_max = 32; + struct grub_fshelp_node root = { + .disk = disk, + .sb = sb, + }; + struct grub_fshelp_node *found; - err = read_extent (disk, sb, &sb->root_dir, 0, 0, ino, - sizeof (*ino)); + err = read_extent (disk, sb, &sb->root_dir, 0, 0, &root.ino, + sizeof (root.ino)); if (err) return err; + err = grub_fshelp_find_file_lookup (path, &root, &found, lookup_file, read_symlink, exptype); + if (!err) + grub_memcpy (ino, &found->ino, sizeof (*ino)); - while (1) - { - ptr = next; - while (*ptr == '/') - ptr++; - if (*ptr == 0) - { - grub_free (alloc); - return GRUB_ERR_NONE; - } - for (next = ptr; *next && *next != '/'; next++); - grub_memcpy (&old_ino, ino, sizeof (old_ino)); - err = hop_level (disk, sb, ino, ptr, next); - if (err) - return err; - - if (((grub_bfs_to_cpu32 (ino->mode) & ATTR_TYPE) == ATTR_LNK)) - { - char *old_alloc = alloc; - if (--symlinks_max == 0) - { - grub_free (alloc); - return grub_error (GRUB_ERR_SYMLINK_LOOP, - N_("too deep nesting of symlinks")); - } - -#ifndef MODE_AFS - if (grub_bfs_to_cpu32 (ino->flags) & LONG_SYMLINK) -#endif - { - grub_size_t symsize = grub_bfs_to_cpu64 (ino->size); - alloc = grub_malloc (grub_strlen (next) - + symsize + 1); - if (!alloc) - { - grub_free (alloc); - return grub_errno; - } - grub_free (old_alloc); - err = read_bfs_file (disk, sb, ino, 0, alloc, symsize, 0, 0); - if (err) - { - grub_free (alloc); - return err; - } - alloc[symsize] = 0; - } -#ifndef MODE_AFS - else - { - alloc = grub_malloc (grub_strlen (next) - + sizeof (ino->inplace_link) + 1); - if (!alloc) - { - grub_free (alloc); - return grub_errno; - } - grub_free (old_alloc); - grub_memcpy (alloc, ino->inplace_link, - sizeof (ino->inplace_link)); - alloc[sizeof (ino->inplace_link)] = 0; - } -#endif - if (alloc[0] == '/') - { - err = read_extent (disk, sb, &sb->root_dir, 0, 0, ino, - sizeof (*ino)); - if (err) - { - grub_free (alloc); - return err; - } - } - else - grub_memcpy (ino, &old_ino, sizeof (old_ino)); - wptr = alloc + grub_strlen (alloc); - if (next) - wptr = grub_stpcpy (wptr, next); - *wptr = 0; - next = alloc; - continue; - } - } + if (&root != found) + grub_free (found); + return err; } static grub_err_t @@ -909,11 +900,9 @@ grub_bfs_dir (grub_device_t device, const char *path, { struct grub_bfs_inode ino; - err = find_file (path, device->disk, &ctx.sb, &ino); + err = find_file (path, device->disk, &ctx.sb, &ino, GRUB_FSHELP_DIR); if (err) return err; - if (((grub_bfs_to_cpu32 (ino.mode) & ATTR_TYPE) != ATTR_DIR)) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); iterate_in_b_tree (device->disk, &ctx.sb, &ino, grub_bfs_dir_iter, &ctx); } @@ -934,11 +923,9 @@ grub_bfs_open (struct grub_file *file, const char *name) { struct grub_bfs_inode ino; struct grub_bfs_data *data; - err = find_file (name, file->device->disk, &sb, &ino); + err = find_file (name, file->device->disk, &sb, &ino, GRUB_FSHELP_REG); if (err) return err; - if (((grub_bfs_to_cpu32 (ino.mode) & ATTR_TYPE) != ATTR_REG)) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a regular file")); data = grub_zalloc (sizeof (struct grub_bfs_data)); if (!data) @@ -1034,7 +1021,7 @@ read_bfs_attr (grub_disk_t disk, if (err) return -1; - err = find_in_b_tree (disk, sb, ino, name, grub_strlen (name), &res); + err = find_in_b_tree (disk, sb, ino, name, &res); if (err) return -1; grub_disk_read (disk, res From bfb5b33e968f4bc4bb45d4f4c6724967b8abefdb Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Mon, 27 Jul 2015 12:49:26 +0200 Subject: [PATCH 103/106] FAT: Convert to fshelp. exFAT doesn't handle "." and ".." correctly, convert it to fshelp to reuse the same logic. --- grub-core/fs/fat.c | 363 +++++++++++++++++++++------------------------ 1 file changed, 170 insertions(+), 193 deletions(-) diff --git a/grub-core/fs/fat.c b/grub-core/fs/fat.c index 827708c18..aa2145cf2 100644 --- a/grub-core/fs/fat.c +++ b/grub-core/fs/fat.c @@ -31,6 +31,7 @@ #else #include #endif +#include #include GRUB_MOD_LICENSE ("GPLv3+"); @@ -173,8 +174,6 @@ struct grub_fat_data #ifndef MODE_EXFAT grub_uint32_t root_sector; grub_uint32_t num_root_sectors; -#else - int is_contiguous; #endif int cluster_bits; @@ -182,13 +181,22 @@ struct grub_fat_data grub_uint32_t cluster_sector; grub_uint32_t num_clusters; + grub_uint32_t uuid; +}; + +struct grub_fshelp_node { + grub_disk_t disk; + struct grub_fat_data *data; + grub_uint8_t attr; grub_ssize_t file_size; grub_uint32_t file_cluster; grub_uint32_t cur_cluster_num; grub_uint32_t cur_cluster; - grub_uint32_t uuid; +#ifdef MODE_EXFAT + int is_contiguous; +#endif }; static grub_dl_t my_mod; @@ -427,13 +435,6 @@ grub_fat_mount (grub_disk_t disk) (void) magic; #endif - /* Start from the root directory. */ - data->file_cluster = data->root_cluster; - data->cur_cluster_num = ~0U; - data->attr = GRUB_FAT_ATTR_DIRECTORY; -#ifdef MODE_EXFAT - data->is_contiguous = 0; -#endif return data; fail: @@ -444,7 +445,7 @@ grub_fat_mount (grub_disk_t disk) } static grub_ssize_t -grub_fat_read_data (grub_disk_t disk, struct grub_fat_data *data, +grub_fat_read_data (grub_disk_t disk, grub_fshelp_node_t node, grub_disk_read_hook_t read_hook, void *read_hook_data, grub_off_t offset, grub_size_t len, char *buf) { @@ -457,13 +458,13 @@ grub_fat_read_data (grub_disk_t disk, struct grub_fat_data *data, #ifndef MODE_EXFAT /* This is a special case. FAT12 and FAT16 doesn't have the root directory in clusters. */ - if (data->file_cluster == ~0U) + if (node->file_cluster == ~0U) { - size = (data->num_root_sectors << GRUB_DISK_SECTOR_BITS) - offset; + size = (node->data->num_root_sectors << GRUB_DISK_SECTOR_BITS) - offset; if (size > len) size = len; - if (grub_disk_read (disk, data->root_sector, offset, size, buf)) + if (grub_disk_read (disk, node->data->root_sector, offset, size, buf)) return -1; return size; @@ -471,12 +472,12 @@ grub_fat_read_data (grub_disk_t disk, struct grub_fat_data *data, #endif #ifdef MODE_EXFAT - if (data->is_contiguous) + if (node->is_contiguous) { /* Read the data here. */ - sector = (data->cluster_sector - + ((data->file_cluster - 2) - << data->cluster_bits)); + sector = (node->data->cluster_sector + + ((node->file_cluster - 2) + << node->data->cluster_bits)); disk->read_hook = read_hook; disk->read_hook_data = read_hook_data; @@ -491,53 +492,53 @@ grub_fat_read_data (grub_disk_t disk, struct grub_fat_data *data, #endif /* Calculate the logical cluster number and offset. */ - logical_cluster_bits = (data->cluster_bits + logical_cluster_bits = (node->data->cluster_bits + GRUB_DISK_SECTOR_BITS); logical_cluster = offset >> logical_cluster_bits; offset &= (1ULL << logical_cluster_bits) - 1; - if (logical_cluster < data->cur_cluster_num) + if (logical_cluster < node->cur_cluster_num) { - data->cur_cluster_num = 0; - data->cur_cluster = data->file_cluster; + node->cur_cluster_num = 0; + node->cur_cluster = node->file_cluster; } while (len) { - while (logical_cluster > data->cur_cluster_num) + while (logical_cluster > node->cur_cluster_num) { /* Find next cluster. */ grub_uint32_t next_cluster; grub_uint32_t fat_offset; - switch (data->fat_size) + switch (node->data->fat_size) { case 32: - fat_offset = data->cur_cluster << 2; + fat_offset = node->cur_cluster << 2; break; case 16: - fat_offset = data->cur_cluster << 1; + fat_offset = node->cur_cluster << 1; break; default: /* case 12: */ - fat_offset = data->cur_cluster + (data->cur_cluster >> 1); + fat_offset = node->cur_cluster + (node->cur_cluster >> 1); break; } /* Read the FAT. */ - if (grub_disk_read (disk, data->fat_sector, fat_offset, - (data->fat_size + 7) >> 3, + if (grub_disk_read (disk, node->data->fat_sector, fat_offset, + (node->data->fat_size + 7) >> 3, (char *) &next_cluster)) return -1; next_cluster = grub_le_to_cpu32 (next_cluster); - switch (data->fat_size) + switch (node->data->fat_size) { case 16: next_cluster &= 0xFFFF; break; case 12: - if (data->cur_cluster & 1) + if (node->cur_cluster & 1) next_cluster >>= 4; next_cluster &= 0x0FFF; @@ -545,27 +546,27 @@ grub_fat_read_data (grub_disk_t disk, struct grub_fat_data *data, } grub_dprintf ("fat", "fat_size=%d, next_cluster=%u\n", - data->fat_size, next_cluster); + node->data->fat_size, next_cluster); /* Check the end. */ - if (next_cluster >= data->cluster_eof_mark) + if (next_cluster >= node->data->cluster_eof_mark) return ret; - if (next_cluster < 2 || next_cluster >= data->num_clusters) + if (next_cluster < 2 || next_cluster >= node->data->num_clusters) { grub_error (GRUB_ERR_BAD_FS, "invalid cluster %u", next_cluster); return -1; } - data->cur_cluster = next_cluster; - data->cur_cluster_num++; + node->cur_cluster = next_cluster; + node->cur_cluster_num++; } /* Read the data here. */ - sector = (data->cluster_sector - + ((data->cur_cluster - 2) - << data->cluster_bits)); + sector = (node->data->cluster_sector + + ((node->cur_cluster - 2) + << node->data->cluster_bits)); size = (1 << logical_cluster_bits) - offset; if (size > len) size = len; @@ -631,7 +632,7 @@ grub_fat_iterate_fini (struct grub_fat_iterate_context *ctxt) #ifdef MODE_EXFAT static grub_err_t -grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data, +grub_fat_iterate_dir_next (grub_fshelp_node_t node, struct grub_fat_iterate_context *ctxt) { grub_memset (&ctxt->dir, 0, sizeof (ctxt->dir)); @@ -641,7 +642,7 @@ grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data, ctxt->offset += sizeof (dir); - if (grub_fat_read_data (disk, data, 0, 0, ctxt->offset, sizeof (dir), + if (grub_fat_read_data (node->disk, node, 0, 0, ctxt->offset, sizeof (dir), (char *) &dir) != sizeof (dir)) break; @@ -663,7 +664,7 @@ grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data, { struct grub_fat_dir_entry sec; ctxt->offset += sizeof (sec); - if (grub_fat_read_data (disk, data, 0, 0, + if (grub_fat_read_data (node->disk, node, 0, 0, ctxt->offset, sizeof (sec), (char *) &sec) != sizeof (sec)) break; @@ -727,7 +728,7 @@ grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data, #else static grub_err_t -grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data, +grub_fat_iterate_dir_next (grub_fshelp_node_t node, struct grub_fat_iterate_context *ctxt) { char *filep = 0; @@ -742,7 +743,7 @@ grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data, ctxt->offset += sizeof (ctxt->dir); /* Read a directory entry. */ - if (grub_fat_read_data (disk, data, 0, 0, + if (grub_fat_read_data (node->disk, node, 0, 0, ctxt->offset, sizeof (ctxt->dir), (char *) &ctxt->dir) != sizeof (ctxt->dir) || ctxt->dir.name[0] == 0) @@ -853,84 +854,20 @@ grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data, #endif -/* Find the underlying directory or file in PATH and return the - next path. If there is no next path or an error occurs, return NULL. - If HOOK is specified, call it with each file name. */ -static char * -grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data, - const char *path, const char *origpath, - grub_fs_dir_hook_t hook, void *hook_data) +static grub_err_t lookup_file (grub_fshelp_node_t node, + const char *name, + grub_fshelp_node_t *foundnode, + enum grub_fshelp_filetype *foundtype) { - char *dirname, *dirp; - int call_hook; - int found = 0; - struct grub_fat_iterate_context ctxt; grub_err_t err; - - if (! (data->attr & GRUB_FAT_ATTR_DIRECTORY)) - { - grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); - return 0; - } - - do - { - /* Extract a directory name. */ - while (*path == '/') - path++; - - /* Emulate special "." and ".." entries in root directory */ - if (data->file_cluster == data->root_cluster) - { - if (*path != '.') - break; - if (!path[1] || path[1] == '/') - { - path++; - continue; - } - if (path[1] == '.' && (!path[2] || path[2] == '/')) - { - path += 2; - continue; - } - } - break; - } - while (1); - - dirp = grub_strchr (path, '/'); - if (dirp) - { - unsigned len = dirp - path; - - dirname = grub_malloc (len + 1); - if (! dirname) - goto fail; - - grub_memcpy (dirname, path, len); - dirname[len] = '\0'; - } - else - /* This is actually a file. */ - dirname = grub_strdup (path); - - call_hook = (! dirp && hook); + struct grub_fat_iterate_context ctxt; err = grub_fat_iterate_init (&ctxt); if (err) - { - grub_free (dirname); - return 0; - } + return err; - while (!(err = grub_fat_iterate_dir_next (disk, data, &ctxt))) + while (!(err = grub_fat_iterate_dir_next (node, &ctxt))) { - struct grub_dirhook_info info; - grub_memset (&info, 0, sizeof (info)); - - info.dir = !! (ctxt.dir.attr & GRUB_FAT_ATTR_DIRECTORY); - info.case_insensitive = 1; #ifdef MODE_EXFAT if (!ctxt.dir.have_stream) @@ -939,36 +876,33 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data, if (ctxt.dir.attr & GRUB_FAT_ATTR_VOLUME_ID) continue; #endif - if (*dirname == '\0' && call_hook) - { - if (hook (ctxt.filename, &info, hook_data)) - break; - else - continue; - } - if (grub_strcasecmp (dirname, ctxt.filename) == 0) + if (grub_strcasecmp (name, ctxt.filename) == 0) { - found = 1; - data->attr = ctxt.dir.attr; + *foundnode = grub_malloc (sizeof (struct grub_fshelp_node)); + if (!*foundnode) + return grub_errno; + (*foundnode)->attr = ctxt.dir.attr; #ifdef MODE_EXFAT - data->file_size = ctxt.dir.file_size; - data->file_cluster = ctxt.dir.first_cluster; - data->is_contiguous = ctxt.dir.is_contiguous; + (*foundnode)->file_size = ctxt.dir.file_size; + (*foundnode)->file_cluster = ctxt.dir.first_cluster; + (*foundnode)->is_contiguous = ctxt.dir.is_contiguous; #else - data->file_size = grub_le_to_cpu32 (ctxt.dir.file_size); - data->file_cluster = ((grub_le_to_cpu16 (ctxt.dir.first_cluster_high) << 16) + (*foundnode)->file_size = grub_le_to_cpu32 (ctxt.dir.file_size); + (*foundnode)->file_cluster = ((grub_le_to_cpu16 (ctxt.dir.first_cluster_high) << 16) | grub_le_to_cpu16 (ctxt.dir.first_cluster_low)); /* If directory points to root, starting cluster is 0 */ - if (!data->file_cluster) - data->file_cluster = data->root_cluster; + if (!(*foundnode)->file_cluster) + (*foundnode)->file_cluster = node->data->root_cluster; #endif - data->cur_cluster_num = ~0U; + (*foundnode)->cur_cluster_num = ~0U; + (*foundnode)->data = node->data; + (*foundnode)->disk = node->disk; - if (call_hook) - hook (ctxt.filename, &info, hook_data); + *foundtype = ((*foundnode)->attr & GRUB_FAT_ATTR_DIRECTORY) ? GRUB_FSHELP_DIR : GRUB_FSHELP_REG; - break; + grub_fat_iterate_fini (&ctxt); + return GRUB_ERR_NONE; } } @@ -976,13 +910,8 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data, if (err == GRUB_ERR_EOF) err = 0; - if (grub_errno == GRUB_ERR_NONE && ! found && !call_hook) - grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), origpath); + return err; - fail: - grub_free (dirname); - - return found ? dirp : 0; } static grub_err_t @@ -991,9 +920,9 @@ grub_fat_dir (grub_device_t device, const char *path, grub_fs_dir_hook_t hook, { struct grub_fat_data *data = 0; grub_disk_t disk = device->disk; - grub_size_t len; - char *dirname = 0; - char *p; + grub_fshelp_node_t found = NULL; + grub_err_t err; + struct grub_fat_iterate_context ctxt; grub_dl_ref (my_mod); @@ -1001,27 +930,53 @@ grub_fat_dir (grub_device_t device, const char *path, grub_fs_dir_hook_t hook, if (! data) goto fail; - /* Make sure that DIRNAME terminates with '/'. */ - len = grub_strlen (path); - dirname = grub_malloc (len + 1 + 1); - if (! dirname) - goto fail; - grub_memcpy (dirname, path, len); - p = dirname + len; - if (path[len - 1] != '/') - *p++ = '/'; - *p = '\0'; - p = dirname; + struct grub_fshelp_node root = { + .data = data, + .disk = disk, + .attr = GRUB_FAT_ATTR_DIRECTORY, + .file_size = 0, + .file_cluster = data->root_cluster, + .cur_cluster_num = ~0U, + .cur_cluster = 0, +#ifdef MODE_EXFAT + .is_contiguous = 0, +#endif + }; - do + err = grub_fshelp_find_file_lookup (path, &root, &found, lookup_file, NULL, GRUB_FSHELP_DIR); + if (err) + goto fail; + + err = grub_fat_iterate_init (&ctxt); + if (err) + goto fail; + + while (!(err = grub_fat_iterate_dir_next (found, &ctxt))) { - p = grub_fat_find_dir (disk, data, p, path, hook, hook_data); + struct grub_dirhook_info info; + grub_memset (&info, 0, sizeof (info)); + + info.dir = !! (ctxt.dir.attr & GRUB_FAT_ATTR_DIRECTORY); + info.case_insensitive = 1; +#ifdef MODE_EXFAT + if (!ctxt.dir.have_stream) + continue; +#else + if (ctxt.dir.attr & GRUB_FAT_ATTR_VOLUME_ID) + continue; +#endif + + if (hook (ctxt.filename, &info, hook_data)) + break; } - while (p && grub_errno == GRUB_ERR_NONE); + grub_fat_iterate_fini (&ctxt); + if (err == GRUB_ERR_EOF) + err = 0; fail: + if (found != &root) + grub_free (found); - grub_free (dirname); grub_free (data); grub_dl_unref (my_mod); @@ -1033,35 +988,43 @@ static grub_err_t grub_fat_open (grub_file_t file, const char *name) { struct grub_fat_data *data = 0; - char *p = (char *) name; + grub_fshelp_node_t found = NULL; + grub_err_t err; + grub_disk_t disk = file->device->disk; grub_dl_ref (my_mod); - data = grub_fat_mount (file->device->disk); + data = grub_fat_mount (disk); if (! data) goto fail; - do - { - p = grub_fat_find_dir (file->device->disk, data, p, name, 0, 0); - if (grub_errno != GRUB_ERR_NONE) - goto fail; - } - while (p); + struct grub_fshelp_node root = { + .data = data, + .disk = disk, + .attr = GRUB_FAT_ATTR_DIRECTORY, + .file_size = 0, + .file_cluster = data->root_cluster, + .cur_cluster_num = ~0U, + .cur_cluster = 0, +#ifdef MODE_EXFAT + .is_contiguous = 0, +#endif + }; - if (data->attr & GRUB_FAT_ATTR_DIRECTORY) - { - grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a regular file")); - goto fail; - } + err = grub_fshelp_find_file_lookup (name, &root, &found, lookup_file, NULL, GRUB_FSHELP_REG); + if (err) + goto fail; - file->data = data; - file->size = data->file_size; + file->data = found; + file->size = found->file_size; return GRUB_ERR_NONE; fail: + if (found != &root) + grub_free (found); + grub_free (data); grub_dl_unref (my_mod); @@ -1080,7 +1043,10 @@ grub_fat_read (grub_file_t file, char *buf, grub_size_t len) static grub_err_t grub_fat_close (grub_file_t file) { - grub_free (file->data); + grub_fshelp_node_t node = file->data; + + grub_free (node->data); + grub_free (node); grub_dl_unref (my_mod); @@ -1093,20 +1059,29 @@ grub_fat_label (grub_device_t device, char **label) { struct grub_fat_dir_entry dir; grub_ssize_t offset = -sizeof(dir); - struct grub_fat_data *data; grub_disk_t disk = device->disk; + struct grub_fshelp_node root = { + .disk = disk, + .attr = GRUB_FAT_ATTR_DIRECTORY, + .file_size = 0, + .cur_cluster_num = ~0U, + .cur_cluster = 0, + .is_contiguous = 0, + }; - data = grub_fat_mount (disk); - if (! data) + root.data = grub_fat_mount (disk); + if (! root.data) return grub_errno; + root.file_cluster = root.data->root_cluster; + *label = NULL; while (1) { offset += sizeof (dir); - if (grub_fat_read_data (disk, data, 0, 0, + if (grub_fat_read_data (disk, &root, 0, 0, offset, sizeof (dir), (char *) &dir) != sizeof (dir)) break; @@ -1126,7 +1101,7 @@ grub_fat_label (grub_device_t device, char **label) * GRUB_MAX_UTF8_PER_UTF16 + 1); if (!*label) { - grub_free (data); + grub_free (root.data); return grub_errno; } chc = dir.type_specific.volume_label.character_count; @@ -1138,7 +1113,7 @@ grub_fat_label (grub_device_t device, char **label) } } - grub_free (data); + grub_free (root.data); return grub_errno; } @@ -1147,30 +1122,32 @@ grub_fat_label (grub_device_t device, char **label) static grub_err_t grub_fat_label (grub_device_t device, char **label) { - struct grub_fat_data *data; grub_disk_t disk = device->disk; grub_err_t err; struct grub_fat_iterate_context ctxt; + struct grub_fshelp_node root = { + .disk = disk, + .attr = GRUB_FAT_ATTR_DIRECTORY, + .file_size = 0, + .cur_cluster_num = ~0U, + .cur_cluster = 0, + }; *label = 0; grub_dl_ref (my_mod); - data = grub_fat_mount (disk); - if (! data) + root.data = grub_fat_mount (disk); + if (! root.data) goto fail; - if (! (data->attr & GRUB_FAT_ATTR_DIRECTORY)) - { - grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); - goto fail; - } + root.file_cluster = root.data->root_cluster; err = grub_fat_iterate_init (&ctxt); if (err) goto fail; - while (!(err = grub_fat_iterate_dir_next (disk, data, &ctxt))) + while (!(err = grub_fat_iterate_dir_next (&root, &ctxt))) if ((ctxt.dir.attr & ~GRUB_FAT_ATTR_ARCHIVE) == GRUB_FAT_ATTR_VOLUME_ID) { *label = grub_strdup (ctxt.filename); @@ -1183,7 +1160,7 @@ grub_fat_label (grub_device_t device, char **label) grub_dl_unref (my_mod); - grub_free (data); + grub_free (root.data); return grub_errno; } From 5fb1e859f71c33bec25d7a7f5926e80e0019b37c Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Mon, 27 Jul 2015 12:50:22 +0200 Subject: [PATCH 104/106] HFS: Convert to fshelp. HFS doesn't handle "." and ".." properly. Convert it to fshelp to reuse the logic. --- grub-core/fs/hfs.c | 177 ++++++++++++++++++++------------------------- 1 file changed, 78 insertions(+), 99 deletions(-) diff --git a/grub-core/fs/hfs.c b/grub-core/fs/hfs.c index 06cf0c7ab..0ebc71b62 100644 --- a/grub-core/fs/hfs.c +++ b/grub-core/fs/hfs.c @@ -29,6 +29,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -1125,90 +1126,81 @@ utf8_to_macroman (grub_uint8_t *to, const char *from) return optr - to; } +union grub_hfs_anyrec { + struct grub_hfs_filerec frec; + struct grub_hfs_dirrec dir; +}; + +struct grub_fshelp_node +{ + struct grub_hfs_data *data; + union grub_hfs_anyrec fdrec; + grub_uint32_t inode; +}; + +static grub_err_t +lookup_file (grub_fshelp_node_t dir, + const char *name, + grub_fshelp_node_t *foundnode, + enum grub_fshelp_filetype *foundtype) +{ + struct grub_hfs_catalog_key key; + grub_ssize_t slen; + union grub_hfs_anyrec fdrec; + + key.parent_dir = grub_cpu_to_be32 (dir->inode); + slen = utf8_to_macroman (key.str, name); + if (slen < 0) + /* Not found */ + return GRUB_ERR_NONE; + key.strlen = slen; + + /* Lookup this node. */ + if (! grub_hfs_find_node (dir->data, (char *) &key, dir->data->cat_root, + 0, (char *) &fdrec.frec, sizeof (fdrec.frec))) + /* Not found */ + return GRUB_ERR_NONE; + + *foundnode = grub_malloc (sizeof (struct grub_fshelp_node)); + if (!*foundnode) + return grub_errno; + + (*foundnode)->inode = grub_be_to_cpu32 (fdrec.dir.dirid); + (*foundnode)->fdrec = fdrec; + (*foundnode)->data = dir->data; + *foundtype = (fdrec.frec.type == GRUB_HFS_FILETYPE_DIR) ? GRUB_FSHELP_DIR : GRUB_FSHELP_REG; + return GRUB_ERR_NONE; +} /* Find a file or directory with the pathname PATH in the filesystem DATA. Return the file record in RETDATA when it is non-zero. Return the directory number in RETINODE when it is non-zero. */ static grub_err_t grub_hfs_find_dir (struct grub_hfs_data *data, const char *path, - struct grub_hfs_filerec *retdata, int *retinode) + grub_fshelp_node_t *found, + enum grub_fshelp_filetype exptype) { - int inode = data->rootdir; - char *next; - char *origpath; - union { - struct grub_hfs_filerec frec; - struct grub_hfs_dirrec dir; - } fdrec; - - fdrec.frec.type = GRUB_HFS_FILETYPE_DIR; - - if (path[0] != '/') - { - grub_error (GRUB_ERR_BAD_FILENAME, N_("invalid file name `%s'"), path); - return 0; + struct grub_fshelp_node root = { + .data = data, + .inode = data->rootdir, + .fdrec = { + .frec = { + .type = GRUB_HFS_FILETYPE_DIR + } } + }; + grub_err_t err; - origpath = grub_strdup (path); - if (!origpath) - return grub_errno; + err = grub_fshelp_find_file_lookup (path, &root, found, lookup_file, NULL, exptype); - path = origpath; - while (*path == '/') - path++; - - while (path && grub_strlen (path)) + if (&root == *found) { - grub_ssize_t slen; - if (fdrec.frec.type != GRUB_HFS_FILETYPE_DIR) - { - grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); - goto fail; - } - - /* Isolate a part of the path. */ - next = grub_strchr (path, '/'); - if (next) - { - while (*next == '/') - *(next++) = '\0'; - } - - struct grub_hfs_catalog_key key; - - key.parent_dir = grub_cpu_to_be32 (inode); - slen = utf8_to_macroman (key.str, path); - if (slen < 0) - { - grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), path); - goto fail; - } - key.strlen = slen; - - /* Lookup this node. */ - if (! grub_hfs_find_node (data, (char *) &key, data->cat_root, - 0, (char *) &fdrec.frec, sizeof (fdrec.frec))) - { - grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), origpath); - goto fail; - } - - if (grub_errno) - goto fail; - - inode = grub_be_to_cpu32 (fdrec.dir.dirid); - path = next; + *found = grub_malloc (sizeof (root)); + if (!*found) + return grub_errno; + grub_memcpy (*found, &root, sizeof (root)); } - - if (retdata) - grub_memcpy (retdata, &fdrec.frec, sizeof (fdrec.frec)); - - if (retinode) - *retinode = inode; - - fail: - grub_free (origpath); - return grub_errno; + return err; } struct grub_hfs_dir_hook_ctx @@ -1266,16 +1258,14 @@ static grub_err_t grub_hfs_dir (grub_device_t device, const char *path, grub_fs_dir_hook_t hook, void *hook_data) { - int inode; - struct grub_hfs_data *data; - struct grub_hfs_filerec frec; struct grub_hfs_dir_hook_ctx ctx = { .hook = hook, .hook_data = hook_data }; - + grub_fshelp_node_t found = NULL; + grub_dl_ref (my_mod); data = grub_hfs_mount (device->disk); @@ -1283,18 +1273,13 @@ grub_hfs_dir (grub_device_t device, const char *path, grub_fs_dir_hook_t hook, goto fail; /* First the directory ID for the directory. */ - if (grub_hfs_find_dir (data, path, &frec, &inode)) + if (grub_hfs_find_dir (data, path, &found, GRUB_FSHELP_DIR)) goto fail; - if (frec.type != GRUB_HFS_FILETYPE_DIR) - { - grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); - goto fail; - } - - grub_hfs_iterate_dir (data, data->cat_root, inode, grub_hfs_dir_hook, &ctx); + grub_hfs_iterate_dir (data, data->cat_root, found->inode, grub_hfs_dir_hook, &ctx); fail: + grub_free (found); grub_free (data); grub_dl_unref (my_mod); @@ -1308,8 +1293,8 @@ static grub_err_t grub_hfs_open (struct grub_file *file, const char *name) { struct grub_hfs_data *data; - struct grub_hfs_filerec frec; - + grub_fshelp_node_t found = NULL; + grub_dl_ref (my_mod); data = grub_hfs_mount (file->device->disk); @@ -1320,29 +1305,23 @@ grub_hfs_open (struct grub_file *file, const char *name) return grub_errno; } - if (grub_hfs_find_dir (data, name, &frec, 0)) + if (grub_hfs_find_dir (data, name, &found, GRUB_FSHELP_REG)) { grub_free (data); grub_dl_unref (my_mod); return grub_errno; } - if (frec.type != GRUB_HFS_FILETYPE_FILE) - { - grub_free (data); - grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a regular file")); - grub_dl_unref (my_mod); - return grub_errno; - } - - grub_memcpy (data->extents, frec.extents, sizeof (grub_hfs_datarecord_t)); - file->size = grub_be_to_cpu32 (frec.size); - data->size = grub_be_to_cpu32 (frec.size); - data->fileid = grub_be_to_cpu32 (frec.fileid); + grub_memcpy (data->extents, found->fdrec.frec.extents, sizeof (grub_hfs_datarecord_t)); + file->size = grub_be_to_cpu32 (found->fdrec.frec.size); + data->size = grub_be_to_cpu32 (found->fdrec.frec.size); + data->fileid = grub_be_to_cpu32 (found->fdrec.frec.fileid); file->offset = 0; file->data = data; + grub_free (found); + return 0; } From d3b464a7c0a9acb7d0f7202a7fa45ac29a014692 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Mon, 27 Jul 2015 13:19:02 +0200 Subject: [PATCH 105/106] archelp: Never pass NULL as mtime. Moves complexity from fs code (NULL check) to common code (passing non-NULL). --- grub-core/fs/archelp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/grub-core/fs/archelp.c b/grub-core/fs/archelp.c index 707f9a658..0cf544f6f 100644 --- a/grub-core/fs/archelp.c +++ b/grub-core/fs/archelp.c @@ -249,9 +249,10 @@ grub_archelp_open (struct grub_archelp_data *data, while (1) { grub_uint32_t mode; + grub_int32_t mtime; int restart; - if (arcops->find_file (data, &fn, NULL, &mode)) + if (arcops->find_file (data, &fn, &mtime, &mode)) goto fail; if (mode == GRUB_ARCHELP_ATTR_END) From 72fc110d95129410443b898e931ff7a1db75312e Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Tue, 28 Jul 2015 01:51:14 +0200 Subject: [PATCH 106/106] ahci: Ensure that bus mastering is set. Fixes ahci_test failing on several platforms. --- grub-core/disk/ahci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c index f4725e8c1..fc640d5d4 100644 --- a/grub-core/disk/ahci.c +++ b/grub-core/disk/ahci.c @@ -195,7 +195,7 @@ grub_ahci_pciinit (grub_pci_device_t dev, addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); grub_pci_write_word (addr, grub_pci_read_word (addr) - | GRUB_PCI_COMMAND_MEM_ENABLED); + | GRUB_PCI_COMMAND_MEM_ENABLED | GRUB_PCI_COMMAND_BUS_MASTER); hba = grub_pci_device_map_range (dev, bar & GRUB_PCI_ADDR_MEM_MASK, sizeof (*hba));