From 00c108a446ca71908db330427c8257208d86fe83 Mon Sep 17 00:00:00 2001 From: robertmh Date: Sun, 1 Jun 2008 13:30:00 +0000 Subject: [PATCH] 2008-06-01 Robert Millan * util/biosdisk.c (get_drive): Verify that `map[i].drive' is non-NULL before dereferencing it. * fs/fat.c (struct grub_fat_bpb): Move fat32-specific fields into a union with fat12/fat16-specific ones. Add some new fields, including `num_serial' for both versions. (struct grub_fat_data): Add `uuid' member. (grub_fat_mount): Refer to fat32-specific fields in `bpb' by their new names. Initialize `data->uuid' using `num_serial'. (grub_fat_uuid): New function. (grub_fat_fs): Reference grub_fat_uuid() in `uuid' struct member. * fs/reiserfs.c (grub_reiserfs_superblock): Add `uuid' field. (grub_reiserfs_uuid): New function. (grub_reiserfs_fs): Reference grub_reiserfs_uuid() in `uuid' struct member. * fs/xfs.c (grub_xfs_sblock): Add `uuid' field. (grub_xfs_uuid): New function. (grub_xfs_fs): Reference grub_reiserfs_uuid() in `uuid' struct member. --- ChangeLog | 23 ++++++++++++++ fs/fat.c | 83 +++++++++++++++++++++++++++++++++++++++++-------- fs/reiserfs.c | 35 +++++++++++++++++++++ fs/xfs.c | 45 ++++++++++++++++++++++++--- util/biosdisk.c | 2 +- 5 files changed, 169 insertions(+), 19 deletions(-) diff --git a/ChangeLog b/ChangeLog index e5ddeda69..f2513e07e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2008-06-01 Robert Millan + + * util/biosdisk.c (get_drive): Verify that `map[i].drive' is non-NULL + before dereferencing it. + + * fs/fat.c (struct grub_fat_bpb): Move fat32-specific fields into a + union with fat12/fat16-specific ones. Add some new fields, including + `num_serial' for both versions. + (struct grub_fat_data): Add `uuid' member. + (grub_fat_mount): Refer to fat32-specific fields in `bpb' by their new + names. Initialize `data->uuid' using `num_serial'. + (grub_fat_uuid): New function. + (grub_fat_fs): Reference grub_fat_uuid() in `uuid' struct member. + + * fs/reiserfs.c (grub_reiserfs_superblock): Add `uuid' field. + (grub_reiserfs_uuid): New function. + (grub_reiserfs_fs): Reference grub_reiserfs_uuid() in `uuid' struct + member. + + * fs/xfs.c (grub_xfs_sblock): Add `uuid' field. + (grub_xfs_uuid): New function. + (grub_xfs_fs): Reference grub_reiserfs_uuid() in `uuid' struct member. + 2008-06-01 Robert Millan * util/update-grub_lib.in (prepare_grub_to_access_device): Generate diff --git a/fs/fat.c b/fs/fat.c index 7f4107735..4d04aeca3 100644 --- a/fs/fat.c +++ b/fs/fat.c @@ -1,7 +1,7 @@ /* fat.c - FAT filesystem */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2000,2001,2002,2003,2004,2005,2007 Free Software Foundation, Inc. + * Copyright (C) 2000,2001,2002,2003,2004,2005,2007,2008 Free Software Foundation, Inc. * * GRUB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -61,14 +61,34 @@ struct grub_fat_bpb grub_uint16_t num_heads; grub_uint32_t num_hidden_sectors; grub_uint32_t num_total_sectors_32; - - /* The following fields are only used by FAT32. */ - grub_uint32_t sectors_per_fat_32; - grub_uint16_t extended_flags; - grub_uint16_t fs_version; - grub_uint32_t root_cluster; - grub_uint16_t fs_info; - grub_uint16_t backup_boot_sector; + union + { + struct + { + grub_uint8_t num_ph_drive; + grub_uint8_t reserved; + grub_uint8_t boot_sig; + grub_uint32_t num_serial; + grub_uint8_t label[11]; + grub_uint8_t fstype[8]; + } __attribute__ ((packed)) fat12_or_fat16; + struct + { + grub_uint32_t sectors_per_fat_32; + grub_uint16_t extended_flags; + grub_uint16_t fs_version; + grub_uint32_t root_cluster; + grub_uint16_t fs_info; + grub_uint16_t backup_boot_sector; + grub_uint8_t reserved[12]; + grub_uint8_t num_ph_drive; + grub_uint8_t reserved1; + grub_uint8_t boot_sig; + grub_uint32_t num_serial; + grub_uint8_t label[11]; + grub_uint8_t fstype[8]; + } __attribute__ ((packed)) fat32; + } __attribute__ ((packed)) version_specific; } __attribute__ ((packed)); struct grub_fat_dir_entry @@ -122,6 +142,8 @@ struct grub_fat_data grub_uint32_t file_cluster; grub_uint32_t cur_cluster_num; grub_uint32_t cur_cluster; + + grub_uint16_t uuid[2]; }; #ifndef GRUB_UTIL @@ -183,7 +205,7 @@ grub_fat_mount (grub_disk_t disk) data->sectors_per_fat = ((bpb.sectors_per_fat_16 ? grub_le_to_cpu16 (bpb.sectors_per_fat_16) - : grub_le_to_cpu32 (bpb.sectors_per_fat_32)) + : grub_le_to_cpu32 (bpb.version_specific.fat32.sectors_per_fat_32)) << data->logical_sector_bits); if (data->sectors_per_fat == 0) goto fail; @@ -219,9 +241,9 @@ grub_fat_mount (grub_disk_t disk) if (! bpb.sectors_per_fat_16) { /* FAT32. */ - grub_uint16_t flags = grub_le_to_cpu16 (bpb.extended_flags); + grub_uint16_t flags = grub_le_to_cpu16 (bpb.version_specific.fat32.extended_flags); - data->root_cluster = grub_le_to_cpu32 (bpb.root_cluster); + data->root_cluster = grub_le_to_cpu32 (bpb.version_specific.fat32.root_cluster); data->fat_size = 32; data->cluster_eof_mark = 0x0ffffff8; @@ -236,7 +258,7 @@ grub_fat_mount (grub_disk_t disk) data->fat_sector += active_fat * data->sectors_per_fat; } - if (bpb.num_root_entries != 0 || bpb.fs_version != 0) + if (bpb.num_root_entries != 0 || bpb.version_specific.fat32.fs_version != 0) goto fail; } else @@ -286,6 +308,12 @@ grub_fat_mount (grub_disk_t disk) first_fat &= 0x00000fff; magic = 0x0f00; } + + /* Serial number. */ + if (bpb.sectors_per_fat_16) + *((grub_uint32_t *) &data->uuid) = grub_le_to_cpu32 (bpb.version_specific.fat12_or_fat16.num_serial); + else + *((grub_uint32_t *) &data->uuid) = grub_le_to_cpu32 (bpb.version_specific.fat32.num_serial); /* Ignore the 3rd bit, because some BIOSes assigns 0xF0 to the media descriptor, even if it is a so-called superfloppy (e.g. an USB key). @@ -797,6 +825,34 @@ grub_fat_label (grub_device_t device, char **label) return grub_errno; } +static grub_err_t +grub_fat_uuid (grub_device_t device, char **uuid) +{ + struct grub_fat_data *data; + grub_disk_t disk = device->disk; + +#ifndef GRUB_UTIL + grub_dl_ref (my_mod); +#endif + + data = grub_fat_mount (disk); + if (data) + { + *uuid = grub_malloc (sizeof ("xxxx-xxxx")); + grub_sprintf (*uuid, "%04x-%04x", data->uuid[1], data->uuid[0]); + } + else + *uuid = NULL; + +#ifndef GRUB_UTIL + grub_dl_unref (my_mod); +#endif + + grub_free (data); + + return grub_errno; +} + static struct grub_fs grub_fat_fs = { .name = "fat", @@ -805,6 +861,7 @@ static struct grub_fs grub_fat_fs = .read = grub_fat_read, .close = grub_fat_close, .label = grub_fat_label, + .uuid = grub_fat_uuid, .next = 0 }; diff --git a/fs/reiserfs.c b/fs/reiserfs.c index 554d10453..9a059e3ca 100644 --- a/fs/reiserfs.c +++ b/fs/reiserfs.c @@ -108,6 +108,8 @@ struct grub_reiserfs_superblock grub_uint16_t version; grub_uint16_t reserved; grub_uint32_t inode_generation; + grub_uint8_t unused[4]; + grub_uint16_t uuid[8]; } __attribute__ ((packed)); struct grub_reiserfs_journal_header @@ -1468,6 +1470,38 @@ grub_reiserfs_label (grub_device_t device, char **label) return grub_errno; } +static grub_err_t +grub_reiserfs_uuid (grub_device_t device, char **uuid) +{ + struct grub_reiserfs_data *data; + grub_disk_t disk = device->disk; + +#ifndef GRUB_UTIL + grub_dl_ref (my_mod); +#endif + + data = grub_reiserfs_mount (disk); + if (data) + { + *uuid = grub_malloc (sizeof ("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")); + grub_sprintf (*uuid, "%04x%04x-%04x-%04x-%04x-%04x%04x%04x", + grub_be_to_cpu16 (data->superblock.uuid[0]), grub_be_to_cpu16 (data->superblock.uuid[1]), + grub_be_to_cpu16 (data->superblock.uuid[2]), grub_be_to_cpu16 (data->superblock.uuid[3]), + grub_be_to_cpu16 (data->superblock.uuid[4]), grub_be_to_cpu16 (data->superblock.uuid[5]), + grub_be_to_cpu16 (data->superblock.uuid[6]), grub_be_to_cpu16 (data->superblock.uuid[7])); + } + else + *uuid = NULL; + +#ifndef GRUB_UTIL + grub_dl_unref (my_mod); +#endif + + grub_free (data); + + return grub_errno; +} + static struct grub_fs grub_reiserfs_fs = { .name = "reiserfs", @@ -1476,6 +1510,7 @@ static struct grub_fs grub_reiserfs_fs = .read = grub_reiserfs_read, .close = grub_reiserfs_close, .label = grub_reiserfs_label, + .uuid = grub_reiserfs_uuid, .next = 0 }; diff --git a/fs/xfs.c b/fs/xfs.c index a778e9905..5437678ad 100644 --- a/fs/xfs.c +++ b/fs/xfs.c @@ -37,17 +37,19 @@ struct grub_xfs_sblock { grub_uint8_t magic[4]; grub_uint32_t bsize; - grub_uint8_t unused1[48]; + grub_uint8_t unused1[24]; + grub_uint16_t uuid[8]; + grub_uint8_t unused2[8]; grub_uint64_t rootino; - grub_uint8_t unused2[20]; - grub_uint32_t agsize; grub_uint8_t unused3[20]; + grub_uint32_t agsize; + grub_uint8_t unused4[20]; grub_uint8_t label[12]; grub_uint8_t log2_bsize; - grub_uint8_t unused4[2]; + grub_uint8_t unused5[2]; grub_uint8_t log2_inop; grub_uint8_t log2_agblk; - grub_uint8_t unused5[67]; + grub_uint8_t unused6[67]; grub_uint8_t log2_dirblk; } __attribute__ ((packed)); @@ -763,6 +765,38 @@ grub_xfs_label (grub_device_t device, char **label) return grub_errno; } +static grub_err_t +grub_xfs_uuid (grub_device_t device, char **uuid) +{ + struct grub_xfs_data *data; + grub_disk_t disk = device->disk; + +#ifndef GRUB_UTIL + grub_dl_ref (my_mod); +#endif + + data = grub_xfs_mount (disk); + if (data) + { + *uuid = grub_malloc (sizeof ("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")); + grub_sprintf (*uuid, "%04x%04x-%04x-%04x-%04x-%04x%04x%04x", + grub_be_to_cpu16 (data->sblock.uuid[0]), grub_be_to_cpu16 (data->sblock.uuid[1]), + grub_be_to_cpu16 (data->sblock.uuid[2]), grub_be_to_cpu16 (data->sblock.uuid[3]), + grub_be_to_cpu16 (data->sblock.uuid[4]), grub_be_to_cpu16 (data->sblock.uuid[5]), + grub_be_to_cpu16 (data->sblock.uuid[6]), grub_be_to_cpu16 (data->sblock.uuid[7])); + } + else + *uuid = NULL; + +#ifndef GRUB_UTIL + grub_dl_unref (my_mod); +#endif + + grub_free (data); + + return grub_errno; +} + static struct grub_fs grub_xfs_fs = @@ -773,6 +807,7 @@ static struct grub_fs grub_xfs_fs = .read = grub_xfs_read, .close = grub_xfs_close, .label = grub_xfs_label, + .uuid = grub_xfs_uuid, .next = 0 }; diff --git a/util/biosdisk.c b/util/biosdisk.c index 3a81e5fde..b42c06df8 100644 --- a/util/biosdisk.c +++ b/util/biosdisk.c @@ -117,7 +117,7 @@ get_drive (const char *name) if (name) { for (i = 0; i < sizeof (map) / sizeof (map[0]); i++) - if (! strcmp (map[i].drive, name)) + if (map[i].drive && ! strcmp (map[i].drive, name)) return i; } else