diff options
author | BlackNoxis <steven.darklight@gmail.com> | 2014-02-15 23:24:26 +0200 |
---|---|---|
committer | BlackNoxis <steven.darklight@gmail.com> | 2014-02-15 23:24:26 +0200 |
commit | 7224c1253228e5c29c78cb3f0f26ce34770f2356 (patch) | |
tree | 1684924656132935256e034f35f92abee6623265 /sys-boot/grub/files/grub-0.97-uuid.patch |
Added ebuilds for kogaion desktop
Diffstat (limited to 'sys-boot/grub/files/grub-0.97-uuid.patch')
-rw-r--r-- | sys-boot/grub/files/grub-0.97-uuid.patch | 5406 |
1 files changed, 5406 insertions, 0 deletions
diff --git a/sys-boot/grub/files/grub-0.97-uuid.patch b/sys-boot/grub/files/grub-0.97-uuid.patch new file mode 100644 index 00000000..f99670a8 --- /dev/null +++ b/sys-boot/grub/files/grub-0.97-uuid.patch @@ -0,0 +1,5406 @@ +=== modified file 'Makefile.am' +--- grub-0.97.orig/Makefile.am 2004-04-23 13:39:01 +0000 ++++ grub-0.97/Makefile.am 2008-07-09 17:23:44 +0000 +@@ -1,4 +1,9 @@ + # Do not change this order if you don't know what you are doing. + AUTOMAKE_OPTIONS = 1.7 gnu +-SUBDIRS = netboot stage2 stage1 lib grub util docs ++if UUID_SUPPORT ++SUBDIRS = libvolume_id netboot stage2 stage1 lib grub util docs ++else ++SUBDIRS = netboot stage2 stage1 lib grub util docs ++endif ++ + EXTRA_DIST = BUGS MAINTENANCE + +=== modified file 'configure.ac' +--- grub-0.97.orig/configure.ac 2008-01-28 18:41:45 +0000 ++++ grub-0.97/configure.ac 2008-07-09 17:23:44 +0000 +@@ -605,6 +606,11 @@ + [ --disable-serial disable serial terminal support]) + AM_CONDITIONAL(SERIAL_SUPPORT, test "x$enable_serial" != xno) + ++dnl UUID scanning ++AC_ARG_ENABLE(uuid, ++ [ --disable-uuid disable uuid scanning support]) ++AM_CONDITIONAL(UUID_SUPPORT, test "x$enable_uuid" != xno) ++ + dnl Simulation of the slowness of a serial device. + AC_ARG_ENABLE(serial-speed-simulation, + [ --enable-serial-speed-simulation +@@ -666,5 +672,6 @@ + docs/Makefile lib/Makefile util/Makefile \ + grub/Makefile netboot/Makefile util/grub-image \ + util/grub-install util/grub-md5-crypt \ +- util/grub-terminfo util/grub-set-default]) ++ util/grub-terminfo util/grub-set-default \ ++ libvolume_id/Makefile]) + AC_OUTPUT + +=== modified file 'grub/Makefile.am' +--- grub-0.97.orig/grub/Makefile.am 2005-02-02 20:40:05 +0000 ++++ grub-0.97/grub/Makefile.am 2008-07-09 17:23:44 +0000 +@@ -16,4 +16,9 @@ + AM_CFLAGS = $(GRUB_CFLAGS) + + grub_SOURCES = main.c asmstub.c +-grub_LDADD = ../stage2/libgrub.a ../lib/libcommon.a $(GRUB_LIBS) ++ ++if UUID_SUPPORT ++grub_LDADD = ../stage2/libgrub.a ../lib/libcommon.a ../libvolume_id/libvolume_id.a $(GRUB_LIBS) ++else ++grub_LDADD = ../stage2/libgrub.a ../lib/libcommon.a $(GRUB_LIBS) ++endif + +=== added directory 'libvolume_id' +=== added file 'libvolume_id/Makefile.am' +--- grub-0.97.orig/libvolume_id/Makefile.am 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/Makefile.am 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,27 @@ ++noinst_LIBRARIES = libvolume_id.a ++ ++AM_CFLAGS = $(STAGE2_CFLAGS) -I$(top_srcdir)/stage2 -I$(top_srcdir)/stage1 ++ ++LIBVOLUME_ID_FS_SUPPORTED = ext.c fat.c hfs.c jfs.c \ ++ luks.c ntfs.c ocfs.c reiserfs.c \ ++ xfs.c ++ ++LIBVOLUME_ID_FS_UNSUPPORTED = cramfs.c gfs.c hpfs.c iso9660.c \ ++ lvm.c minix.c romfs.c squashfs.c \ ++ sysv.c udf.c ufs.c vxfs.c ++ ++LIBVOLUME_ID_RAID_SUPPORTED = ddf_raid.c ++ ++LIBVOLUME_ID_RAID_UNSUPPORTED = adaptec_raid.c highpoint.c isw_raid.c \ ++ jmicron_raid.c linux_raid.c lsi_raid.c \ ++ nvidia_raid.c promise_raid.c silicon_raid.c \ ++ via_raid.c ++ ++LIBVOLUME_ID_MISC_UNSUPPORTED = linux_swap.c netware.c ++ ++libvolume_id_a_SOURCES = $(LIBVOLUME_ID_FS_SUPPORTED) \ ++ $(LIBVOLUME_ID_RAID_SUPPORTED) \ ++ $(LIBVOLUME_ID_FS_UNSUPPORTED) \ ++ $(LIBVOLUME_ID_RAID_UNSUPPORTED) \ ++ volume_id.h volume_id.c util.c util.h misc.c ++ + +=== added file 'libvolume_id/adaptec_raid.c' +--- grub-0.97.orig/libvolume_id/adaptec_raid.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/adaptec_raid.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,107 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2006 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++struct adaptec_meta { ++ uint32_t b0idcode; ++ uint8_t lunsave[8]; ++ uint16_t sdtype; ++ uint16_t ssavecyl; ++ uint8_t ssavehed; ++ uint8_t ssavesec; ++ uint8_t sb0flags; ++ uint8_t jbodEnable; ++ uint8_t lundsave; ++ uint8_t svpdirty; ++ uint16_t biosInfo; ++ uint16_t svwbskip; ++ uint16_t svwbcln; ++ uint16_t svwbmax; ++ uint16_t res3; ++ uint16_t svwbmin; ++ uint16_t res4; ++ uint16_t svrcacth; ++ uint16_t svwcacth; ++ uint16_t svwbdly; ++ uint8_t svsdtime; ++ uint8_t res5; ++ uint16_t firmval; ++ uint16_t firmbln; ++ uint32_t firmblk; ++ uint32_t fstrsvrb; ++ uint16_t svBlockStorageTid; ++ uint16_t svtid; ++ uint8_t svseccfl; ++ uint8_t res6; ++ uint8_t svhbanum; ++ uint8_t resver; ++ uint32_t drivemagic; ++ uint8_t reserved[20]; ++ uint8_t testnum; ++ uint8_t testflags; ++ uint16_t maxErrorCount; ++ uint32_t count; ++ uint32_t startTime; ++ uint32_t interval; ++ uint8_t tstxt0; ++ uint8_t tstxt1; ++ uint8_t serNum[32]; ++ uint8_t res8[102]; ++ uint32_t fwTestMagic; ++ uint32_t fwTestSeqNum; ++ uint8_t fwTestRes[8]; ++ uint8_t smagic[4]; ++ uint32_t raidtbl; ++ uint16_t raidline; ++ uint8_t res9[0xF6]; ++} PACKED; ++ ++int volume_id_probe_adaptec_raid(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ const uint8_t *buf; ++ uint64_t meta_off; ++ struct adaptec_meta *ad; ++ ++ info("probing at offset 0x%llx, size 0x%llx", ++ (unsigned long long) off, (unsigned long long) size); ++ ++ if (size < 0x10000) ++ return -1; ++ ++ meta_off = ((size / 0x200)-1) * 0x200; ++ buf = volume_id_get_buffer(id, off + meta_off, 0x200); ++ if (buf == NULL) ++ return -1; ++ ++ ad = (struct adaptec_meta *) buf; ++ if (memcmp((char*)ad->smagic, "DPTM", 4) != 0) ++ return -1; ++ ++ if (ad->b0idcode != be32_to_cpu(0x37FC4D1E)) ++ return -1; ++ ++ volume_id_set_usage(id, VOLUME_ID_RAID); ++ sprintf(id->type_version, "%u", ad->resver); ++ id->type = "adaptec_raid_member"; ++ ++ return 0; ++} + +=== added file 'libvolume_id/cramfs.c' +--- grub-0.97.orig/libvolume_id/cramfs.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/cramfs.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,60 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++struct cramfs_super { ++ uint8_t magic[4]; ++ uint32_t size; ++ uint32_t flags; ++ uint32_t future; ++ uint8_t signature[16]; ++ struct cramfs_info { ++ uint32_t crc; ++ uint32_t edition; ++ uint32_t blocks; ++ uint32_t files; ++ } PACKED info; ++ uint8_t name[16]; ++} PACKED; ++ ++int volume_id_probe_cramfs(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ struct cramfs_super *cs; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ cs = (struct cramfs_super *) volume_id_get_buffer(id, off, 0x200); ++ if (cs == NULL) ++ return -1; ++ ++ if (memcmp((char*)cs->magic, "\x45\x3d\xcd\x28", 4) == 0 || memcmp((char*)cs->magic, "\x28\xcd\x3d\x45", 4) == 0) { ++ volume_id_set_label_raw(id, cs->name, 16); ++ volume_id_set_label_string(id, cs->name, 16); ++ ++ volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); ++ id->type = "cramfs"; ++ return 0; ++ } ++ ++ return -1; ++} + +=== added file 'libvolume_id/ddf_raid.c' +--- grub-0.97.orig/libvolume_id/ddf_raid.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/ddf_raid.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,60 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2007 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++/* http://www.snia.org/standards/home */ ++ ++#define DDF_HEADER 0xDE11DE11 ++#define DDF_GUID_LENGTH 24 ++#define DDF_REV_LENGTH 8 ++ ++static struct ddf_header { ++ uint32_t signature; ++ uint32_t crc; ++ uint8_t guid[DDF_GUID_LENGTH]; ++ uint8_t ddf_rev[DDF_REV_LENGTH]; ++} PACKED *ddf; ++ ++int volume_id_probe_ddf_raid(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ uint64_t ddf_off = ((size / 0x200)-1) * 0x200; ++ const uint8_t *buf; ++ ++ info("probing at offset 0x%llx, size 0x%llx", ++ (unsigned long long) off, (unsigned long long) size); ++ if (size < 0x10000) ++ return -1; ++ ++ buf = volume_id_get_buffer(id, off + ddf_off, 0x200); ++ if (buf == NULL) ++ return -1; ++ ddf = (struct ddf_header *) buf; ++ ++ if (ddf->signature != cpu_to_be32(DDF_HEADER)) ++ return -1; ++ ++ volume_id_set_uuid(id, ddf->guid, DDF_GUID_LENGTH, UUID_STRING); ++ strcpy(id->type_version, (char*) ddf->ddf_rev); ++ volume_id_set_usage(id, VOLUME_ID_RAID); ++ id->type = "ddf_raid_member"; ++ return 0; ++} + +=== added file 'libvolume_id/ext.c' +--- grub-0.97.orig/libvolume_id/ext.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/ext.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,129 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++struct ext2_super_block { ++ uint32_t s_inodes_count; ++ uint32_t s_blocks_count; ++ uint32_t s_r_blocks_count; ++ uint32_t s_free_blocks_count; ++ uint32_t s_free_inodes_count; ++ uint32_t s_first_data_block; ++ uint32_t s_log_block_size; ++ uint32_t s_log_frag_size; ++ uint32_t s_blocks_per_group; ++ uint32_t s_frags_per_group; ++ uint32_t s_inodes_per_group; ++ uint32_t s_mtime; ++ uint32_t s_wtime; ++ uint16_t s_mnt_count; ++ uint16_t s_max_mnt_count; ++ uint16_t s_magic; ++ uint16_t s_state; ++ uint16_t s_errors; ++ uint16_t s_minor_rev_level; ++ uint32_t s_lastcheck; ++ uint32_t s_checkinterval; ++ uint32_t s_creator_os; ++ uint32_t s_rev_level; ++ uint16_t s_def_resuid; ++ uint16_t s_def_resgid; ++ uint32_t s_first_ino; ++ uint16_t s_inode_size; ++ uint16_t s_block_group_nr; ++ uint32_t s_feature_compat; ++ uint32_t s_feature_incompat; ++ uint32_t s_feature_ro_compat; ++ uint8_t s_uuid[16]; ++ uint8_t s_volume_name[16]; ++} PACKED; ++ ++#define EXT_SUPER_MAGIC 0xEF53 ++#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004 ++#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 ++#define EXT3_FEATURE_INCOMPAT_EXTENTS 0x0040 ++#define EXT4_FEATURE_INCOMPAT_64BIT 0x0080 ++#define EXT4_FEATURE_INCOMPAT_MMP 0x0100 ++ ++#define EXT_SUPERBLOCK_OFFSET 0x400 ++ ++#define EXT3_MIN_BLOCK_SIZE 0x400 ++#define EXT3_MAX_BLOCK_SIZE 0x1000 ++ ++int volume_id_probe_ext(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ struct ext2_super_block *es; ++ size_t bsize; ++ uint32_t feature_compat; ++ uint32_t feature_incompat; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ es = (struct ext2_super_block *) volume_id_get_buffer(id, off + EXT_SUPERBLOCK_OFFSET, 0x200); ++ if (es == NULL) ++ return -1; ++ ++ if (es->s_magic != cpu_to_le16(EXT_SUPER_MAGIC)) ++ return -1; ++ ++ bsize = 0x400 << le32_to_cpu(es->s_log_block_size); ++ dbg("ext blocksize 0x%zx", bsize); ++ if (bsize < EXT3_MIN_BLOCK_SIZE || bsize > EXT3_MAX_BLOCK_SIZE) { ++ dbg("invalid ext blocksize"); ++ return -1; ++ } ++ ++ volume_id_set_label_raw(id, es->s_volume_name, 16); ++ volume_id_set_label_string(id, es->s_volume_name, 16); ++ volume_id_set_uuid(id, es->s_uuid, 0, UUID_DCE); ++ sprintf(id->type_version, "%u.%u", ++ le32_to_cpu(es->s_rev_level), le16_to_cpu(es->s_minor_rev_level)); ++ ++ feature_compat = le32_to_cpu(es->s_feature_compat); ++ feature_incompat = le32_to_cpu(es->s_feature_incompat); ++ ++ /* check for external journal device */ ++ if ((feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) != 0) { ++ volume_id_set_usage(id, VOLUME_ID_OTHER); ++ id->type = "jbd"; ++ goto out; ++ } ++ ++ volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); ++ ++ if ((feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS) != 0 || ++ (feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) != 0 || ++ (feature_incompat & EXT4_FEATURE_INCOMPAT_MMP) != 0) { ++ id->type = "ext4"; ++ goto out; ++ } ++ ++ if ((feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) != 0) { ++ id->type = "ext3"; ++ goto out; ++ } ++ ++ id->type = "ext2"; ++ ++out: ++ return 0; ++} + +=== added file 'libvolume_id/fat.c' +--- grub-0.97.orig/libvolume_id/fat.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/fat.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,482 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2004-2007 Kay Sievers <kay.sievers@vrfy.org> ++ * Copyright (C) 2007 Ryan Lortie <desrt@desrt.ca> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++#define FAT12_MAX 0xff5 ++#define FAT16_MAX 0xfff5 ++#define FAT_ATTR_VOLUME_ID 0x08 ++#define FAT_ATTR_DIR 0x10 ++#define FAT_ATTR_LONG_NAME 0x0f ++#define FAT_ATTR_MASK 0x3f ++#define FAT_ENTRY_FREE 0xe5 ++ ++#define VFAT_LFN_SEQ_MASK 0x3f ++#define VFAT_LFN_SEQ_LAST 0x40 ++#define VFAT_LFN_SEQ_MAX 20 ++#define VFAT_LFN_CHARS_PER_ENTRY (5 + 6 + 2) ++#define VFAT_LOWERCASE_NAME 0x10 ++#define VFAT_LOWERCASE_EXT 0x08 ++ ++struct vfat_super_block { ++ uint8_t boot_jump[3]; ++ uint8_t sysid[8]; ++ uint16_t sector_size; ++ uint8_t sectors_per_cluster; ++ uint16_t reserved; ++ uint8_t fats; ++ uint16_t dir_entries; ++ uint16_t sectors; ++ uint8_t media; ++ uint16_t fat_length; ++ uint16_t secs_track; ++ uint16_t heads; ++ uint32_t hidden; ++ uint32_t total_sect; ++ union { ++ struct fat_super_block { ++ uint8_t unknown[3]; ++ uint8_t serno[4]; ++ uint8_t label[11]; ++ uint8_t magic[8]; ++ uint8_t dummy2[192]; ++ uint8_t pmagic[2]; ++ } PACKED fat; ++ struct fat32_super_block { ++ uint32_t fat32_length; ++ uint16_t flags; ++ uint8_t version[2]; ++ uint32_t root_cluster; ++ uint16_t fsinfo_sector; ++ uint16_t backup_boot; ++ uint16_t reserved2[6]; ++ uint8_t unknown[3]; ++ uint8_t serno[4]; ++ uint8_t label[11]; ++ uint8_t magic[8]; ++ uint8_t dummy2[164]; ++ uint8_t pmagic[2]; ++ } PACKED fat32; ++ } PACKED type; ++} PACKED; ++ ++struct fat32_fsinfo { ++ uint8_t signature1[4]; ++ uint32_t reserved1[120]; ++ uint8_t signature2[4]; ++ uint32_t free_clusters; ++ uint32_t next_cluster; ++ uint32_t reserved2[4]; ++} PACKED; ++ ++struct vfat_dir_entry { ++ uint8_t name[11]; ++ uint8_t attr; ++ uint8_t lowercase; ++ uint8_t fine_time_creat; ++ uint16_t time_creat; ++ uint16_t date_creat; ++ uint16_t date_acc; ++ uint16_t cluster_high; ++ uint16_t time_write; ++ uint16_t date_write; ++ uint16_t cluster_low; ++ uint32_t size; ++} PACKED; ++ ++ ++struct vfat_lfn_entry { ++ uint8_t seq; ++ uint16_t name0[5]; ++ uint8_t attr; ++ uint8_t reserved; ++ uint8_t cksum; ++ uint16_t name1[6]; ++ uint16_t cluster; ++ uint16_t name2[2]; ++} PACKED; ++ ++static uint8_t fat_lfn_checksum(const uint8_t name[11]) ++{ ++ uint8_t cksum = 0; ++ int i; ++ ++ /* http://en.wikipedia.org/wiki/File_Allocation_Table */ ++ for (i = 0; i < 11; i++) ++ cksum = ((cksum & 1) ? 0x80 : 0) + (cksum >> 1) + name[i]; ++ ++ return cksum; ++} ++ ++static size_t fat_read_lfn(uint8_t *filename, size_t fnsize, ++ struct vfat_dir_entry *direntry, ++ struct vfat_dir_entry *entry) ++{ ++ uint8_t buffer[VFAT_LFN_SEQ_MAX * VFAT_LFN_CHARS_PER_ENTRY * 2]; ++ uint8_t expected_seq = 1; ++ uint8_t cksum; ++ size_t len = 0; ++ size_t fnlen = 0; ++ ++ cksum = fat_lfn_checksum(entry->name); ++ ++ while (--entry >= direntry) { ++ struct vfat_lfn_entry *lfn = (struct vfat_lfn_entry *) entry; ++ ++ if (expected_seq > VFAT_LFN_SEQ_MAX) ++ break; ++ ++ if ((lfn->attr & FAT_ATTR_MASK) != FAT_ATTR_LONG_NAME) ++ break; ++ ++ if (lfn->cksum != cksum) ++ break; ++ ++ if ((lfn->seq & VFAT_LFN_SEQ_MASK) != expected_seq++) ++ break; ++ ++ if (lfn->cluster != 0) ++ break; ++ ++ /* extra paranoia -- should never happen */ ++ if (len + sizeof(lfn->name0) + sizeof(lfn->name1) + ++ sizeof(lfn->name2) > sizeof(buffer)) ++ break; ++ ++ memcpy (&buffer[len], lfn->name0, sizeof(lfn->name0)); ++ len += sizeof(lfn->name0); ++ memcpy (&buffer[len], lfn->name1, sizeof(lfn->name1)); ++ len += sizeof(lfn->name1); ++ memcpy (&buffer[len], lfn->name2, sizeof(lfn->name2)); ++ len += sizeof(lfn->name2); ++ ++ if (lfn->seq & VFAT_LFN_SEQ_LAST) { ++ fnlen = volume_id_set_unicode16(filename, fnsize, buffer, LE, len); ++ break; ++ } ++ } ++ ++ return fnlen; ++} ++ ++static size_t fat_read_filename(uint8_t *filename, size_t fnsize, ++ struct vfat_dir_entry *direntry, struct vfat_dir_entry *entry) ++{ ++ size_t len; ++ int i; ++ ++ /* check if maybe we have LFN entries */ ++ len = fat_read_lfn(filename, fnsize, direntry, entry); ++ if (len > 0) ++ goto out; ++ ++ /* else, read the normal 8.3 name */ ++ for (i = 0; i < 11; i++) { ++ if (entry->lowercase & ((i < 8) ? VFAT_LOWERCASE_NAME : VFAT_LOWERCASE_EXT)) ++ filename[i] = tolower(entry->name[i]); ++ else ++ filename[i] = entry->name[i]; ++ } ++ len = 11; ++ ++out: ++ filename[len] = '\0'; ++ return len; ++} ++ ++/* fills filename, returns string length */ ++static size_t get_fat_attr_volume_id(uint8_t *filename, size_t fnsize, ++ struct vfat_dir_entry *direntry, unsigned int count) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < count; i++) { ++ /* end marker */ ++ if (direntry[i].name[0] == 0x00) { ++ dbg("end of dir"); ++ break; ++ } ++ ++ /* empty entry */ ++ if (direntry[i].name[0] == FAT_ENTRY_FREE) ++ continue; ++ ++ /* long name */ ++ if ((direntry[i].attr & FAT_ATTR_MASK) == FAT_ATTR_LONG_NAME) ++ continue; ++ ++ if ((direntry[i].attr & (FAT_ATTR_VOLUME_ID | FAT_ATTR_DIR)) == FAT_ATTR_VOLUME_ID) { ++ /* labels do not have file data */ ++ if (direntry[i].cluster_high != 0 || direntry[i].cluster_low != 0) ++ continue; ++ ++ dbg("found ATTR_VOLUME_ID id in root dir"); ++ return fat_read_filename(filename, fnsize, direntry, &direntry[i]); ++ } ++ ++ dbg("skip dir entry"); ++ } ++ ++ return 0; ++} ++ ++int volume_id_probe_vfat(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ uint8_t filename[255 * 3]; ++ struct vfat_super_block *vs; ++ struct vfat_dir_entry *direntry; ++ struct fat32_fsinfo *fsinfo; ++ uint16_t sector_size; ++ uint16_t dir_entries; ++ uint32_t sect_count; ++ uint16_t reserved; ++ uint32_t fat_size; ++ uint32_t root_cluster; ++ uint32_t dir_size; ++ uint32_t cluster_count; ++ uint16_t fat_length; ++ uint32_t fat32_length; ++ uint64_t root_start; ++ uint32_t start_data_sect; ++ uint16_t root_dir_entries; ++ uint16_t fsinfo_sect; ++ uint8_t *buf; ++ uint32_t buf_size; ++ uint32_t next; ++ int maxloop; ++ size_t fnlen; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ buf = volume_id_get_buffer(id, off, 0x400); ++ if (buf == NULL) ++ return -1; ++ ++ /* check signature */ ++ if (buf[510] != 0x55 || buf[511] != 0xaa) ++ return -1; ++ ++ vs = (struct vfat_super_block *) buf; ++ if (memcmp((char*)vs->sysid, "NTFS", 4) == 0) ++ return -1; ++ ++ /* believe only that's fat, don't trust the version */ ++ if (memcmp((char*)vs->type.fat32.magic, "MSWIN", 5) == 0) ++ goto magic; ++ ++ if (memcmp((char*)vs->type.fat32.magic, "FAT32 ", 8) == 0) ++ goto magic; ++ ++ if (memcmp((char*)vs->type.fat.magic, "FAT16 ", 8) == 0) ++ goto magic; ++ ++ if (memcmp((char*)vs->type.fat.magic, "MSDOS", 5) == 0) ++ goto magic; ++ ++ if (memcmp((char*)vs->type.fat.magic, "FAT12 ", 8) == 0) ++ goto magic; ++ ++ /* some old floppies don't have a magic, expect the boot jump address to match */ ++ if ((vs->boot_jump[0] != 0xeb || vs->boot_jump[2] != 0x90) && ++ vs->boot_jump[0] != 0xe9) ++ return -1; ++ ++magic: ++ /* reserverd sector count */ ++ if (!vs->reserved) ++ return -1; ++ ++ /* fat count */ ++ if (!vs->fats) ++ return -1; ++ ++ /* media check */ ++ if (vs->media < 0xf8 && vs->media != 0xf0) ++ return -1; ++ ++ /* cluster size check */ ++ if (vs->sectors_per_cluster == 0 || ++ (vs->sectors_per_cluster & (vs->sectors_per_cluster-1))) ++ return -1; ++ ++ /* sector size check */ ++ sector_size = le16_to_cpu(vs->sector_size); ++ if (sector_size == 0 || ((sector_size & (sector_size-1)) != 0)) ++ return -1; ++ ++ dbg("sector_size 0x%x", sector_size); ++ dbg("sectors_per_cluster 0x%x", vs->sectors_per_cluster); ++ ++ dir_entries = le16_to_cpu(vs->dir_entries); ++ reserved = le16_to_cpu(vs->reserved); ++ dbg("reserved 0x%x", reserved); ++ ++ sect_count = le16_to_cpu(vs->sectors); ++ if (sect_count == 0) ++ sect_count = le32_to_cpu(vs->total_sect); ++ dbg("sect_count 0x%x", sect_count); ++ ++ fat_length = le16_to_cpu(vs->fat_length); ++ dbg("fat_length 0x%x", fat_length); ++ fat32_length = le32_to_cpu(vs->type.fat32.fat32_length); ++ dbg("fat32_length 0x%x", fat32_length); ++ ++ if (fat_length) ++ fat_size = fat_length * vs->fats; ++ else if (fat32_length) ++ fat_size = fat32_length * vs->fats; ++ else ++ return -1; ++ dbg("fat_size 0x%x", fat_size); ++ ++ dir_size = ((dir_entries * sizeof(struct vfat_dir_entry)) + ++ (sector_size-1)) / sector_size; ++ dbg("dir_size 0x%x", dir_size); ++ ++ cluster_count = sect_count - (reserved + fat_size + dir_size); ++ cluster_count /= vs->sectors_per_cluster; ++ dbg("cluster_count 0x%x", cluster_count); ++ ++ /* must be FAT32 */ ++ if (!fat_length && fat32_length) ++ goto fat32; ++ ++ /* cluster_count tells us the format */ ++ if (cluster_count < FAT12_MAX) ++ strcpy(id->type_version, "FAT12"); ++ else if (cluster_count < FAT16_MAX) ++ strcpy(id->type_version, "FAT16"); ++ else ++ goto fat32; ++ ++ /* the label may be an attribute in the root directory */ ++ root_start = (reserved + fat_size) * sector_size; ++ dbg("root dir start 0x%llx", (unsigned long long) root_start); ++ root_dir_entries = le16_to_cpu(vs->dir_entries); ++ dbg("expected entries 0x%x", root_dir_entries); ++ ++ buf_size = root_dir_entries * sizeof(struct vfat_dir_entry); ++ buf = volume_id_get_buffer(id, off + root_start, buf_size); ++ if (buf == NULL) ++ goto found; ++ ++ direntry = (struct vfat_dir_entry*) buf; ++ ++ fnlen = get_fat_attr_volume_id(filename, sizeof(filename), direntry, root_dir_entries); ++ ++ vs = (struct vfat_super_block *) volume_id_get_buffer(id, off, 0x200); ++ if (vs == NULL) ++ return -1; ++ ++ if (fnlen > 0 && memcmp((char*)filename, "NO NAME ", 11) != 0) { ++ volume_id_set_label_raw(id, filename, fnlen); ++ volume_id_set_label_string(id, filename, fnlen); ++ } else if (memcmp((char*)vs->type.fat.label, "NO NAME ", 11) != 0) { ++ volume_id_set_label_raw(id, vs->type.fat.label, 11); ++ volume_id_set_label_string(id, vs->type.fat.label, 11); ++ } ++ volume_id_set_uuid(id, vs->type.fat.serno, 0, UUID_DOS); ++ goto found; ++ ++fat32: ++ /* FAT32 should have a valid signature in the fsinfo block */ ++ fsinfo_sect = le16_to_cpu(vs->type.fat32.fsinfo_sector); ++ buf = volume_id_get_buffer(id, off + (fsinfo_sect * sector_size), 0x200); ++ if (buf == NULL) ++ return -1; ++ fsinfo = (struct fat32_fsinfo *) buf; ++ if (memcmp((char*)fsinfo->signature1, "\x52\x52\x61\x41", 4) != 0) ++ return -1; ++ if (memcmp((char*)fsinfo->signature2, "\x72\x72\x41\x61", 4) != 0) ++ return -1 ; ++ ++ vs = (struct vfat_super_block *) volume_id_get_buffer(id, off, 0x200); ++ if (vs == NULL) ++ return -1; ++ ++ strcpy(id->type_version, "FAT32"); ++ ++ /* FAT32 root dir is a cluster chain like any other directory */ ++ buf_size = vs->sectors_per_cluster * sector_size; ++ root_cluster = le32_to_cpu(vs->type.fat32.root_cluster); ++ dbg("root dir cluster %u", root_cluster); ++ start_data_sect = reserved + fat_size; ++ ++ next = root_cluster; ++ maxloop = 100; ++ while (--maxloop) { ++ uint32_t next_sect_off; ++ uint64_t next_off; ++ uint64_t fat_entry_off; ++ int count; ++ ++ dbg("next cluster %u", next); ++ next_sect_off = (next - 2) * vs->sectors_per_cluster; ++ next_off = (start_data_sect + next_sect_off) * sector_size; ++ dbg("cluster offset 0x%llx", (unsigned long long) next_off); ++ ++ /* get cluster */ ++ buf = volume_id_get_buffer(id, off + next_off, buf_size); ++ if (buf == NULL) ++ goto found; ++ ++ direntry = (struct vfat_dir_entry*) buf; ++ count = buf_size / sizeof(struct vfat_dir_entry); ++ dbg("expected entries 0x%x", count); ++ ++ fnlen = get_fat_attr_volume_id(filename, sizeof(filename), direntry, count); ++ if (fnlen > 0) ++ break; ++ ++ /* get FAT entry */ ++ fat_entry_off = (reserved * sector_size) + (next * sizeof(uint32_t)); ++ buf = volume_id_get_buffer(id, off + fat_entry_off, buf_size); ++ if (buf == NULL) ++ goto found; ++ ++ /* set next cluster */ ++ next = le32_to_cpu(*((uint32_t *) buf)) & 0x0fffffff; ++ if (next < 2 || next >= 0x0ffffff0) ++ break; ++ } ++ if (maxloop == 0) ++ dbg("reached maximum follow count of root cluster chain, give up"); ++ ++ vs = (struct vfat_super_block *) volume_id_get_buffer(id, off, 0x200); ++ if (vs == NULL) ++ return -1; ++ ++ if (fnlen > 0 && memcmp((char*)filename, "NO NAME ", 11) != 0) { ++ volume_id_set_label_raw(id, filename, fnlen); ++ volume_id_set_label_string(id, filename, fnlen); ++ } else if (memcmp((char*)vs->type.fat32.label, "NO NAME ", 11) != 0) { ++ volume_id_set_label_raw(id, vs->type.fat32.label, 11); ++ volume_id_set_label_string(id, vs->type.fat32.label, 11); ++ } ++ volume_id_set_uuid(id, vs->type.fat32.serno, 0, UUID_DOS); ++ ++found: ++ volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); ++ id->type = "vfat"; ++ ++ return 0; ++} + +=== added file 'libvolume_id/gfs.c' +--- grub-0.97.orig/libvolume_id/gfs.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/gfs.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,115 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2006 Red Hat, Inc. <redhat.com> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++/* Common gfs/gfs2 constants: */ ++#define GFS_MAGIC 0x01161970 ++#define GFS_DEFAULT_BSIZE 4096 ++#define GFS_SUPERBLOCK_OFFSET (0x10 * GFS_DEFAULT_BSIZE) ++#define GFS_METATYPE_SB 1 ++#define GFS_FORMAT_SB 100 ++#define GFS_LOCKNAME_LEN 64 ++ ++/* gfs1 constants: */ ++#define GFS_FORMAT_FS 1309 ++#define GFS_FORMAT_MULTI 1401 ++/* gfs2 constants: */ ++#define GFS2_FORMAT_FS 1801 ++#define GFS2_FORMAT_MULTI 1900 ++ ++struct gfs2_meta_header { ++ uint32_t mh_magic; ++ uint32_t mh_type; ++ uint64_t __pad0; /* Was generation number in gfs1 */ ++ uint32_t mh_format; ++ uint32_t __pad1; /* Was incarnation number in gfs1 */ ++}; ++ ++struct gfs2_inum { ++ uint64_t no_formal_ino; ++ uint64_t no_addr; ++}; ++ ++struct gfs2_sb { ++ struct gfs2_meta_header sb_header; ++ ++ uint32_t sb_fs_format; ++ uint32_t sb_multihost_format; ++ uint32_t __pad0; /* Was superblock flags in gfs1 */ ++ ++ uint32_t sb_bsize; ++ uint32_t sb_bsize_shift; ++ uint32_t __pad1; /* Was journal segment size in gfs1 */ ++ ++ struct gfs2_inum sb_master_dir; /* Was jindex dinode in gfs1 */ ++ struct gfs2_inum __pad2; /* Was rindex dinode in gfs1 */ ++ struct gfs2_inum sb_root_dir; ++ ++ char sb_lockproto[GFS_LOCKNAME_LEN]; ++ char sb_locktable[GFS_LOCKNAME_LEN]; ++ /* In gfs1, quota and license dinodes followed */ ++} PACKED; ++ ++static int volume_id_probe_gfs_generic(struct volume_id *id, uint64_t off, int vers) ++{ ++ struct gfs2_sb *sbd; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ sbd = (struct gfs2_sb *) ++ volume_id_get_buffer(id, off + GFS_SUPERBLOCK_OFFSET, sizeof(struct gfs2_sb)); ++ if (sbd == NULL) ++ return -1; ++ ++ if (be32_to_cpu(sbd->sb_header.mh_magic) == GFS_MAGIC && ++ be32_to_cpu(sbd->sb_header.mh_type) == GFS_METATYPE_SB && ++ be32_to_cpu(sbd->sb_header.mh_format) == GFS_FORMAT_SB) { ++ if (vers == 1) { ++ if (be32_to_cpu(sbd->sb_fs_format) != GFS_FORMAT_FS || ++ be32_to_cpu(sbd->sb_multihost_format) != GFS_FORMAT_MULTI) ++ return -1; /* not gfs1 */ ++ id->type = "gfs"; ++ } ++ else if (vers == 2) { ++ if (be32_to_cpu(sbd->sb_fs_format) != GFS2_FORMAT_FS || ++ be32_to_cpu(sbd->sb_multihost_format) != GFS2_FORMAT_MULTI) ++ return -1; /* not gfs2 */ ++ id->type = "gfs2"; ++ } ++ else ++ return -1; ++ strcpy(id->type_version, "1"); ++ volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); ++ return 0; ++ } ++ return -1; ++} ++ ++int volume_id_probe_gfs(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ return volume_id_probe_gfs_generic(id, off, 1); ++} ++ ++int volume_id_probe_gfs2(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ return volume_id_probe_gfs_generic(id, off, 2); ++} + +=== added file 'libvolume_id/hfs.c' +--- grub-0.97.orig/libvolume_id/hfs.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/hfs.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,318 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++struct hfs_finder_info{ ++ uint32_t boot_folder; ++ uint32_t start_app; ++ uint32_t open_folder; ++ uint32_t os9_folder; ++ uint32_t reserved; ++ uint32_t osx_folder; ++ uint8_t id[8]; ++} PACKED; ++ ++static struct hfs_mdb { ++ uint8_t signature[2]; ++ uint32_t cr_date; ++ uint32_t ls_Mod; ++ uint16_t atrb; ++ uint16_t nm_fls; ++ uint16_t vbm_st; ++ uint16_t alloc_ptr; ++ uint16_t nm_al_blks; ++ uint32_t al_blk_size; ++ uint32_t clp_size; ++ uint16_t al_bl_st; ++ uint32_t nxt_cnid; ++ uint16_t free_bks; ++ uint8_t label_len; ++ uint8_t label[27]; ++ uint32_t vol_bkup; ++ uint16_t vol_seq_num; ++ uint32_t wr_cnt; ++ uint32_t xt_clump_size; ++ uint32_t ct_clump_size; ++ uint16_t num_root_dirs; ++ uint32_t file_count; ++ uint32_t dir_count; ++ struct hfs_finder_info finder_info; ++ uint8_t embed_sig[2]; ++ uint16_t embed_startblock; ++ uint16_t embed_blockcount; ++} PACKED *hfs; ++ ++struct hfsplus_bnode_descriptor { ++ uint32_t next; ++ uint32_t prev; ++ uint8_t type; ++ uint8_t height; ++ uint16_t num_recs; ++ uint16_t reserved; ++} PACKED; ++ ++struct hfsplus_bheader_record { ++ uint16_t depth; ++ uint32_t root; ++ uint32_t leaf_count; ++ uint32_t leaf_head; ++ uint32_t leaf_tail; ++ uint16_t node_size; ++} PACKED; ++ ++struct hfsplus_catalog_key { ++ uint16_t key_len; ++ uint32_t parent_id; ++ uint16_t unicode_len; ++ uint8_t unicode[255 * 2]; ++} PACKED; ++ ++struct hfsplus_extent { ++ uint32_t start_block; ++ uint32_t block_count; ++} PACKED; ++ ++#define HFSPLUS_EXTENT_COUNT 8 ++struct hfsplus_fork { ++ uint64_t total_size; ++ uint32_t clump_size; ++ uint32_t total_blocks; ++ struct hfsplus_extent extents[HFSPLUS_EXTENT_COUNT]; ++} PACKED; ++ ++static struct hfsplus_vol_header { ++ uint8_t signature[2]; ++ uint16_t version; ++ uint32_t attributes; ++ uint32_t last_mount_vers; ++ uint32_t reserved; ++ uint32_t create_date; ++ uint32_t modify_date; ++ uint32_t backup_date; ++ uint32_t checked_date; ++ uint32_t file_count; ++ uint32_t folder_count; ++ uint32_t blocksize; ++ uint32_t total_blocks; ++ uint32_t free_blocks; ++ uint32_t next_alloc; ++ uint32_t rsrc_clump_sz; ++ uint32_t data_clump_sz; ++ uint32_t next_cnid; ++ uint32_t write_count; ++ uint64_t encodings_bmp; ++ struct hfs_finder_info finder_info; ++ struct hfsplus_fork alloc_file; ++ struct hfsplus_fork ext_file; ++ struct hfsplus_fork cat_file; ++ struct hfsplus_fork attr_file; ++ struct hfsplus_fork start_file; ++} PACKED *hfsplus; ++ ++#define HFS_SUPERBLOCK_OFFSET 0x400 ++#define HFS_NODE_LEAF 0xff ++#define HFSPLUS_POR_CNID 1 ++ ++static void hfsid_set_uuid(struct volume_id *id, const uint8_t *hfs_id) ++{ ++#if 0 ++ MD5_CTX md5c; ++ static const uint8_t hash_init[16] = { ++ 0xb3, 0xe2, 0x0f, 0x39, 0xf2, 0x92, 0x11, 0xd6, ++ 0x97, 0xa4, 0x00, 0x30, 0x65, 0x43, 0xec, 0xac ++ }; ++ uint8_t uuid[16]; ++ ++ if (*((uint64_t *)hfs_id) == 0) ++ return; ++ ++ MD5_Init(&md5c); ++ MD5_Update(&md5c, &hash_init, 16); ++ MD5_Update(&md5c, hfs_id, 8); ++ MD5_Final(uuid, &md5c); ++ ++ uuid[6] = 0x30 | (uuid[6] & 0x0f); ++ uuid[8] = 0x80 | (uuid[8] & 0x3f); ++ volume_id_set_uuid(id, uuid, UUID_DCE); ++#endif ++ ++ volume_id_set_uuid(id, hfs_id, 0, UUID_64BIT_BE); ++} ++ ++int volume_id_probe_hfs_hfsplus(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ unsigned int blocksize; ++ unsigned int cat_block; ++ unsigned int ext_block_start; ++ unsigned int ext_block_count; ++ int ext; ++ unsigned int leaf_node_head; ++ unsigned int leaf_node_count; ++ unsigned int leaf_node_size; ++ unsigned int leaf_block; ++ uint64_t leaf_off; ++ unsigned int alloc_block_size; ++ unsigned int alloc_first_block; ++ unsigned int embed_first_block; ++ unsigned int record_count; ++ struct hfsplus_bnode_descriptor *descr; ++ struct hfsplus_bheader_record *bnode; ++ struct hfsplus_catalog_key *key; ++ unsigned int label_len; ++ struct hfsplus_extent extents[HFSPLUS_EXTENT_COUNT]; ++ const uint8_t *buf; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ buf = volume_id_get_buffer(id, off + HFS_SUPERBLOCK_OFFSET, 0x200); ++ if (buf == NULL) ++ return -1; ++ ++ hfs = (struct hfs_mdb *) buf; ++ if (memcmp((char *)hfs->signature, "BD", 2) != 0) ++ goto checkplus; ++ ++ /* it may be just a hfs wrapper for hfs+ */ ++ if (memcmp((char *)hfs->embed_sig, "H+", 2) == 0) { ++ alloc_block_size = be32_to_cpu(hfs->al_blk_size); ++ dbg("alloc_block_size 0x%x", alloc_block_size); ++ ++ alloc_first_block = be16_to_cpu(hfs->al_bl_st); ++ dbg("alloc_first_block 0x%x", alloc_first_block); ++ ++ embed_first_block = be16_to_cpu(hfs->embed_startblock); ++ dbg("embed_first_block 0x%x", embed_first_block); ++ ++ off += (alloc_first_block * 512) + ++ (embed_first_block * alloc_block_size); ++ dbg("hfs wrapped hfs+ found at offset 0x%llx", (unsigned long long) off); ++ ++ buf = volume_id_get_buffer(id, off + HFS_SUPERBLOCK_OFFSET, 0x200); ++ if (buf == NULL) ++ return -1; ++ goto checkplus; ++ } ++ ++ if (hfs->label_len > 0 && hfs->label_len < 28) { ++ volume_id_set_label_raw(id, hfs->label, hfs->label_len); ++ volume_id_set_label_string(id, hfs->label, hfs->label_len) ; ++ } ++ ++ hfsid_set_uuid(id, hfs->finder_info.id); ++ ++ volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); ++ id->type = "hfs"; ++ ++ return 0; ++ ++checkplus: ++ hfsplus = (struct hfsplus_vol_header *) buf; ++ if (memcmp((char *)hfsplus->signature, "H+", 2) == 0) ++ goto hfsplus; ++ if (memcmp((char *)hfsplus->signature, "HX", 2) == 0) ++ goto hfsplus; ++ return -1; ++ ++hfsplus: ++ hfsid_set_uuid(id, hfsplus->finder_info.id); ++ ++ blocksize = be32_to_cpu(hfsplus->blocksize); ++ dbg("blocksize %u", blocksize); ++ ++ memcpy(extents, hfsplus->cat_file.extents, sizeof(extents)); ++ cat_block = be32_to_cpu(extents[0].start_block); ++ dbg("catalog start block 0x%x", cat_block); ++ ++ buf = volume_id_get_buffer(id, off + (cat_block * blocksize), 0x2000); ++ if (buf == NULL) ++ goto found; ++ ++ bnode = (struct hfsplus_bheader_record *) ++ &buf[sizeof(struct hfsplus_bnode_descriptor)]; ++ ++ leaf_node_head = be32_to_cpu(bnode->leaf_head); ++ dbg("catalog leaf node 0x%x", leaf_node_head); ++ ++ leaf_node_size = be16_to_cpu(bnode->node_size); ++ dbg("leaf node size 0x%x", leaf_node_size); ++ ++ leaf_node_count = be32_to_cpu(bnode->leaf_count); ++ dbg("leaf node count 0x%x", leaf_node_count); ++ if (leaf_node_count == 0) ++ goto found; ++ ++ leaf_block = (leaf_node_head * leaf_node_size) / blocksize; ++ ++ /* get physical location */ ++ for (ext = 0; ext < HFSPLUS_EXTENT_COUNT; ext++) { ++ ext_block_start = be32_to_cpu(extents[ext].start_block); ++ ext_block_count = be32_to_cpu(extents[ext].block_count); ++ dbg("extent start block 0x%x, count 0x%x", ext_block_start, ext_block_count); ++ ++ if (ext_block_count == 0) ++ goto found; ++ ++ /* this is our extent */ ++ if (leaf_block < ext_block_count) ++ break; ++ ++ leaf_block -= ext_block_count; ++ } ++ if (ext == HFSPLUS_EXTENT_COUNT) ++ goto found; ++ dbg("found block in extent %i", ext); ++ ++ leaf_off = (ext_block_start + leaf_block) * blocksize; ++ ++ buf = volume_id_get_buffer(id, off + leaf_off, leaf_node_size); ++ if (buf == NULL) ++ goto found; ++ ++ descr = (struct hfsplus_bnode_descriptor *) buf; ++ dbg("descriptor type 0x%x", descr->type); ++ ++ record_count = be16_to_cpu(descr->num_recs); ++ dbg("number of records %u", record_count); ++ if (record_count == 0) ++ goto found; ++ ++ if (descr->type != HFS_NODE_LEAF) ++ goto found; ++ ++ key = (struct hfsplus_catalog_key *) ++ &buf[sizeof(struct hfsplus_bnode_descriptor)]; ++ ++ dbg("parent id 0x%x", be32_to_cpu(key->parent_id)); ++ if (be32_to_cpu(key->parent_id) != HFSPLUS_POR_CNID) ++ goto found; ++ ++ label_len = be16_to_cpu(key->unicode_len) * 2; ++ dbg("label unicode16 len %i", label_len); ++ volume_id_set_label_raw(id, key->unicode, label_len); ++ volume_id_set_label_unicode16(id, key->unicode, BE, label_len); ++ ++found: ++ volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); ++ id->type = "hfsplus"; ++ ++ return 0; ++} + +=== added file 'libvolume_id/highpoint.c' +--- grub-0.97.orig/libvolume_id/highpoint.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/highpoint.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,91 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++struct hpt37x_meta { ++ uint8_t filler1[32]; ++ uint32_t magic; ++} PACKED; ++ ++struct hpt45x_meta { ++ uint32_t magic; ++} PACKED; ++ ++#define HPT37X_CONFIG_OFF 0x1200 ++#define HPT37X_MAGIC_OK 0x5a7816f0 ++#define HPT37X_MAGIC_BAD 0x5a7816fd ++ ++#define HPT45X_MAGIC_OK 0x5a7816f3 ++#define HPT45X_MAGIC_BAD 0x5a7816fd ++ ++ ++int volume_id_probe_highpoint_37x_raid(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ const uint8_t *buf; ++ struct hpt37x_meta *hpt; ++ uint32_t magic; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ buf = volume_id_get_buffer(id, off + HPT37X_CONFIG_OFF, 0x200); ++ if (buf == NULL) ++ return -1; ++ ++ hpt = (struct hpt37x_meta *) buf; ++ magic = le32_to_cpu(hpt->magic); ++ if (magic != HPT37X_MAGIC_OK && magic != HPT37X_MAGIC_BAD) ++ return -1; ++ ++ volume_id_set_usage(id, VOLUME_ID_RAID); ++ id->type = "highpoint_raid_member"; ++ ++ return 0; ++} ++ ++int volume_id_probe_highpoint_45x_raid(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ const uint8_t *buf; ++ struct hpt45x_meta *hpt; ++ uint64_t meta_off; ++ uint32_t magic; ++ ++ dbg("probing at offset 0x%llx, size 0x%llx", ++ (unsigned long long) off, (unsigned long long) size); ++ ++ if (size < 0x10000) ++ return -1; ++ ++ meta_off = ((size / 0x200)-11) * 0x200; ++ buf = volume_id_get_buffer(id, off + meta_off, 0x200); ++ if (buf == NULL) ++ return -1; ++ ++ hpt = (struct hpt45x_meta *) buf; ++ magic = le32_to_cpu(hpt->magic); ++ if (magic != HPT45X_MAGIC_OK && magic != HPT45X_MAGIC_BAD) ++ return -1; ++ ++ volume_id_set_usage(id, VOLUME_ID_RAID); ++ id->type = "highpoint_raid_member"; ++ ++ return 0; ++} + +=== added file 'libvolume_id/hpfs.c' +--- grub-0.97.orig/libvolume_id/hpfs.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/hpfs.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,51 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++struct hpfs_super ++{ ++ uint8_t magic[4]; ++ uint8_t version; ++} PACKED; ++ ++#define HPFS_SUPERBLOCK_OFFSET 0x2000 ++ ++int volume_id_probe_hpfs(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ struct hpfs_super *hs; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ hs = (struct hpfs_super *) volume_id_get_buffer(id, off + HPFS_SUPERBLOCK_OFFSET, 0x200); ++ if (hs == NULL) ++ return -1; ++ ++ if (memcmp((char *)hs->magic, "\x49\xe8\x95\xf9", 4) == 0) { ++ sprintf(id->type_version, "%u", hs->version); ++ ++ volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); ++ id->type = "hpfs"; ++ return 0; ++ } ++ ++ return -1; ++} + +=== added file 'libvolume_id/iso9660.c' +--- grub-0.97.orig/libvolume_id/iso9660.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/iso9660.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,119 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++#define ISO_SUPERBLOCK_OFFSET 0x8000 ++#define ISO_SECTOR_SIZE 0x800 ++#define ISO_VD_OFFSET (ISO_SUPERBLOCK_OFFSET + ISO_SECTOR_SIZE) ++#define ISO_VD_PRIMARY 0x1 ++#define ISO_VD_SUPPLEMENTARY 0x2 ++#define ISO_VD_END 0xff ++#define ISO_VD_MAX 16 ++ ++struct iso_volume_descriptor { ++ uint8_t type; ++ uint8_t id[5]; ++ uint8_t version; ++ uint8_t flags; ++ uint8_t system_id[32]; ++ uint8_t volume_id[32]; ++ uint8_t unused[8]; ++ uint8_t space_size[8]; ++ uint8_t escape_sequences[8]; ++} PACKED; ++ ++struct high_sierra_volume_descriptor { ++ uint8_t foo[8]; ++ uint8_t type; ++ uint8_t id[5]; ++ uint8_t version; ++} PACKED; ++ ++int volume_id_probe_iso9660(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ uint8_t *buf; ++ struct iso_volume_descriptor *is; ++ struct high_sierra_volume_descriptor *hs; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ buf = volume_id_get_buffer(id, off + ISO_SUPERBLOCK_OFFSET, 0x200); ++ if (buf == NULL) ++ return -1; ++ ++ is = (struct iso_volume_descriptor *) buf; ++ ++ if (memcmp((char*)is->id, "CD001", 5) == 0) { ++ int vd_offset; ++ int i; ++ ++ dbg("read label from PVD"); ++ volume_id_set_label_raw(id, is->volume_id, 32); ++ volume_id_set_label_string(id, is->volume_id, 32); ++ ++ dbg("looking for SVDs"); ++ vd_offset = ISO_VD_OFFSET; ++ for (i = 0; i < ISO_VD_MAX; i++) { ++ uint8_t svd_label[64]; ++ ++ is = (struct iso_volume_descriptor *) volume_id_get_buffer(id, off + vd_offset, 0x200); ++ if (is == NULL || is->type == ISO_VD_END) ++ break; ++ if (is->type != ISO_VD_SUPPLEMENTARY) ++ continue; ++ ++ dbg("found SVD at offset 0x%llx", (unsigned long long) (off + vd_offset)); ++ if (memcmp((char *)is->escape_sequences, "%/@", 3) == 0|| ++ memcmp((char *)is->escape_sequences, "%/C", 3) == 0|| ++ memcmp((char *)is->escape_sequences, "%/E", 3) == 0) { ++ dbg("Joliet extension found"); ++ volume_id_set_unicode16(svd_label, sizeof(svd_label), is->volume_id, BE, 32); ++ if (memcmp((char *)id->label, (char *)svd_label, 16) == 0) { ++ dbg("SVD label is identical, use the possibly longer PVD one"); ++ break; ++ } ++ ++ volume_id_set_label_raw(id, is->volume_id, 32); ++ volume_id_set_label_string(id, svd_label, 32); ++ strcpy(id->type_version, "Joliet Extension"); ++ goto found; ++ } ++ vd_offset += ISO_SECTOR_SIZE; ++ } ++ goto found; ++ } ++ ++ hs = (struct high_sierra_volume_descriptor *) buf; ++ ++ if (memcmp((char *)hs->id, "CDROM", 5) == 0) { ++ strcpy(id->type_version, "High Sierra"); ++ goto found; ++ } ++ ++ return -1; ++ ++found: ++ volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); ++ id->type = "iso9660"; ++ ++ return 0; ++} + +=== added file 'libvolume_id/isw_raid.c' +--- grub-0.97.orig/libvolume_id/isw_raid.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/isw_raid.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,61 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++struct isw_meta { ++ uint8_t sig[32]; ++ uint32_t check_sum; ++ uint32_t mpb_size; ++ uint32_t family_num; ++ uint32_t generation_num; ++} PACKED; ++ ++#define ISW_SIGNATURE "Intel Raid ISM Cfg Sig. " ++ ++ ++int volume_id_probe_intel_software_raid(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ const uint8_t *buf; ++ uint64_t meta_off; ++ struct isw_meta *isw; ++ ++ info("probing at offset 0x%llx, size 0x%llx", ++ (unsigned long long) off, (unsigned long long) size); ++ ++ if (size < 0x10000) ++ return -1; ++ ++ meta_off = ((size / 0x200)-2) * 0x200; ++ buf = volume_id_get_buffer(id, off + meta_off, 0x200); ++ if (buf == NULL) ++ return -1; ++ ++ isw = (struct isw_meta *) buf; ++ if (memcmp((char *)isw->sig, ISW_SIGNATURE, sizeof(ISW_SIGNATURE)-1) != 0) ++ return -1; ++ ++ volume_id_set_usage(id, VOLUME_ID_RAID); ++ memcpy(id->type_version, &isw->sig[sizeof(ISW_SIGNATURE)-1], 6); ++ id->type = "isw_raid_member"; ++ ++ return 0; ++} + +=== added file 'libvolume_id/jfs.c' +--- grub-0.97.orig/libvolume_id/jfs.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/jfs.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,60 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++struct jfs_super_block { ++ uint8_t magic[4]; ++ uint32_t version; ++ uint64_t size; ++ uint32_t bsize; ++ uint32_t dummy1; ++ uint32_t pbsize; ++ uint32_t dummy2[27]; ++ uint8_t uuid[16]; ++ uint8_t label[16]; ++ uint8_t loguuid[16]; ++} PACKED; ++ ++#define JFS_SUPERBLOCK_OFFSET 0x8000 ++ ++int volume_id_probe_jfs(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ struct jfs_super_block *js; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ js = (struct jfs_super_block *) volume_id_get_buffer(id, off + JFS_SUPERBLOCK_OFFSET, 0x200); ++ if (js == NULL) ++ return -1; ++ ++ if (memcmp((char *)js->magic, "JFS1", 4) != 0) ++ return -1; ++ ++ volume_id_set_label_raw(id, js->label, 16); ++ volume_id_set_label_string(id, js->label, 16); ++ volume_id_set_uuid(id, js->uuid, 0, UUID_DCE); ++ ++ volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); ++ id->type = "jfs"; ++ ++ return 0; ++} + +=== added file 'libvolume_id/jmicron_raid.c' +--- grub-0.97.orig/libvolume_id/jmicron_raid.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/jmicron_raid.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,57 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2006 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++struct jmicron_meta { ++ int8_t signature[2]; ++ uint8_t minor_version; ++ uint8_t major_version; ++ uint16_t checksum; ++} PACKED; ++ ++int volume_id_probe_jmicron_raid(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ const uint8_t *buf; ++ uint64_t meta_off; ++ struct jmicron_meta *jm; ++ ++ info("probing at offset 0x%llx, size 0x%llx", ++ (unsigned long long) off, (unsigned long long) size); ++ ++ if (size < 0x10000) ++ return -1; ++ ++ meta_off = ((size / 0x200)-1) * 0x200; ++ buf = volume_id_get_buffer(id, off + meta_off, 0x200); ++ if (buf == NULL) ++ return -1; ++ ++ jm = (struct jmicron_meta *) buf; ++ if (memcmp((char *)jm->signature, "JM", 2) != 0) ++ return -1; ++ ++ volume_id_set_usage(id, VOLUME_ID_RAID); ++ sprintf(id->type_version, "%u.%u", jm->major_version, jm->minor_version); ++ id->type = "jmicron_raid_member"; ++ ++ return 0; ++} + +=== added file 'libvolume_id/linux_raid.c' +--- grub-0.97.orig/libvolume_id/linux_raid.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/linux_raid.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,160 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++static struct mdp0_super_block { ++ uint32_t md_magic; ++ uint32_t major_version; ++ uint32_t minor_version; ++ uint32_t patch_version; ++ uint32_t gvalid_words; ++ uint32_t set_uuid0; ++ uint32_t ctime; ++ uint32_t level; ++ uint32_t size; ++ uint32_t nr_disks; ++ uint32_t raid_disks; ++ uint32_t md_minor; ++ uint32_t not_persistent; ++ uint32_t set_uuid1; ++ uint32_t set_uuid2; ++ uint32_t set_uuid3; ++} PACKED *mdp0; ++ ++struct mdp1_super_block { ++ uint32_t magic; ++ uint32_t major_version; ++ uint32_t feature_map; ++ uint32_t pad0; ++ uint8_t set_uuid[16]; ++ uint8_t set_name[32]; ++} PACKED *mdp1; ++ ++#define MD_RESERVED_BYTES 0x10000 ++#define MD_SB_MAGIC 0xa92b4efc ++ ++static int volume_id_probe_linux_raid0(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ const uint8_t *buf; ++ union { ++ uint32_t ints[4]; ++ uint8_t bytes[16]; ++ } uuid; ++ ++ info("probing at offset 0x%llx, size 0x%llx", ++ (unsigned long long) off, (unsigned long long) size); ++ if (size < 0x10000) ++ return -1; ++ ++ buf = volume_id_get_buffer(id, off, 0x800); ++ if (buf == NULL) ++ return -1; ++ mdp0 = (struct mdp0_super_block *) buf; ++ ++ if (le32_to_cpu(mdp0->md_magic) == MD_SB_MAGIC) { ++ uuid.ints[0] = bswap_32(mdp0->set_uuid0); ++ if (le32_to_cpu(mdp0->minor_version >= 90)) { ++ uuid.ints[1] = bswap_32(mdp0->set_uuid1); ++ uuid.ints[2] = bswap_32(mdp0->set_uuid2); ++ uuid.ints[3] = bswap_32(mdp0->set_uuid3); ++ } else { ++ uuid.ints[1] = 0; ++ uuid.ints[2] = 0; ++ uuid.ints[3] = 0; ++ } ++ volume_id_set_uuid(id, uuid.bytes, 0, UUID_FOURINT); ++ sprintf(id->type_version, "%u.%u.%u", ++ le32_to_cpu(mdp0->major_version), ++ le32_to_cpu(mdp0->minor_version), ++ le32_to_cpu(mdp0->patch_version)); ++ } else if (be32_to_cpu(mdp0->md_magic) == MD_SB_MAGIC) { ++ uuid.ints[0] = mdp0->set_uuid0; ++ if (be32_to_cpu(mdp0->minor_version >= 90)) { ++ uuid.ints[1] = mdp0->set_uuid1; ++ uuid.ints[2] = mdp0->set_uuid2; ++ uuid.ints[3] = mdp0->set_uuid3; ++ } else { ++ uuid.ints[1] = 0; ++ uuid.ints[2] = 0; ++ uuid.ints[3] = 0; ++ } ++ volume_id_set_uuid(id, uuid.bytes, 0, UUID_FOURINT); ++ sprintf(id->type_version, "%u.%u.%u", ++ be32_to_cpu(mdp0->major_version), ++ be32_to_cpu(mdp0->minor_version), ++ be32_to_cpu(mdp0->patch_version)); ++ } else ++ return -1; ++ ++ volume_id_set_usage(id, VOLUME_ID_RAID); ++ id->type = "linux_raid_member"; ++ return 0; ++} ++ ++static int volume_id_probe_linux_raid1(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ const uint8_t *buf; ++ ++ info("probing at offset 0x%llx, size 0x%llx", ++ (unsigned long long) off, (unsigned long long) size); ++ ++ buf = volume_id_get_buffer(id, off, 0x800); ++ if (buf == NULL) ++ return -1; ++ mdp1 = (struct mdp1_super_block *) buf; ++ ++ if (le32_to_cpu(mdp1->magic) != MD_SB_MAGIC) ++ return -1; ++ ++ volume_id_set_uuid(id, mdp1->set_uuid, 0, UUID_FOURINT); ++ volume_id_set_label_raw(id, mdp1->set_name, 32); ++ volume_id_set_label_string(id, mdp1->set_name, 32); ++ sprintf(id->type_version, "%u", le32_to_cpu(mdp1->major_version)); ++ volume_id_set_usage(id, VOLUME_ID_RAID); ++ id->type = "linux_raid_member"; ++ return 0; ++} ++ ++int volume_id_probe_linux_raid(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ uint64_t sboff; ++ ++ /* version 0 at the end of the device */ ++ sboff = (size & ~(MD_RESERVED_BYTES - 1)) - MD_RESERVED_BYTES; ++ if (volume_id_probe_linux_raid0(id, off + sboff, size) == 0) ++ return 0; ++ ++ /* version 1.0 at the end of the device */ ++ sboff = (size & ~(0x1000 - 1)) - 0x2000; ++ if (volume_id_probe_linux_raid1(id, off + sboff, size) == 0) ++ return 0; ++ ++ /* version 1.1 at the start of the device */ ++ if (volume_id_probe_linux_raid1(id, off, size) == 0) ++ return 0; ++ ++ /* version 1.2 at 4k offset from the start */ ++ if (volume_id_probe_linux_raid1(id, off + 0x1000, size) == 0) ++ return 0; ++ ++ return -1; ++} + +=== added file 'libvolume_id/linux_swap.c' +--- grub-0.97.orig/libvolume_id/linux_swap.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/linux_swap.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,85 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++struct swap_header_v1_2 { ++ uint8_t bootbits[1024]; ++ uint32_t version; ++ uint32_t last_page; ++ uint32_t nr_badpages; ++ uint8_t uuid[16]; ++ uint8_t volume_name[16]; ++} PACKED; ++ ++#define LARGEST_PAGESIZE 0x4000 ++ ++int volume_id_probe_linux_swap(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ const uint8_t *buf; ++ unsigned int page; ++ struct swap_header_v1_2 *sw; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ /* eek, the swap signature is at the end of the PAGE_SIZE */ ++ for (page = 0x1000; page <= LARGEST_PAGESIZE; page <<= 1) { ++ buf = volume_id_get_buffer(id, off + page-10, 10); ++ if (buf == NULL) ++ return -1; ++ ++ if (memcmp((char *)buf, "SWAP-SPACE", 10) == 0) { ++ strcpy(id->type_version, "1"); ++ goto found; ++ } ++ ++ if (memcmp((char *)buf, "SWAPSPACE2", 10) == 0) { ++ id->type = "swap"; ++ strcpy(id->type_version, "2"); ++ goto found_label; ++ } ++ ++ if (memcmp((char *)buf, "S1SUSPEND", 9) == 0) { ++ id->type = "suspend"; ++ strcpy(id->type_version, "s1suspend"); ++ goto found_label; ++ } ++ ++ if (memcmp((char *)buf, "ULSUSPEND", 9) == 0) { ++ id->type = "suspend"; ++ strcpy(id->type_version, "ulsuspend"); ++ goto found_label; ++ } ++ } ++ return -1; ++ ++found_label: ++ sw = (struct swap_header_v1_2 *) volume_id_get_buffer(id, off, sizeof(struct swap_header_v1_2)); ++ if (sw != NULL) { ++ volume_id_set_label_raw(id, sw->volume_name, 16); ++ volume_id_set_label_string(id, sw->volume_name, 16); ++ volume_id_set_uuid(id, sw->uuid, 0, UUID_DCE); ++ } ++ ++found: ++ volume_id_set_usage(id, VOLUME_ID_OTHER); ++ return 0; ++} + +=== added file 'libvolume_id/lsi_raid.c' +--- grub-0.97.orig/libvolume_id/lsi_raid.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/lsi_raid.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,55 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++struct lsi_meta { ++ uint8_t sig[6]; ++} PACKED; ++ ++#define LSI_SIGNATURE "$XIDE$" ++ ++int volume_id_probe_lsi_mega_raid(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ const uint8_t *buf; ++ uint64_t meta_off; ++ struct lsi_meta *lsi; ++ ++ info("probing at offset 0x%llx, size 0x%llx", ++ (unsigned long long) off, (unsigned long long) size); ++ ++ if (size < 0x10000) ++ return -1; ++ ++ meta_off = ((size / 0x200)-1) * 0x200; ++ buf = volume_id_get_buffer(id, off + meta_off, 0x200); ++ if (buf == NULL) ++ return -1; ++ ++ lsi = (struct lsi_meta *) buf; ++ if (memcmp((char *)lsi->sig, LSI_SIGNATURE, sizeof(LSI_SIGNATURE)-1) != 0) ++ return -1; ++ ++ volume_id_set_usage(id, VOLUME_ID_RAID); ++ id->type = "lsi_mega_raid_member"; ++ ++ return 0; ++} + +=== added file 'libvolume_id/luks.c' +--- grub-0.97.orig/libvolume_id/luks.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/luks.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,76 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2005 W. Michael Petullo <mike@flyn.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++#define LUKS_SECTOR_SHIFT 9 ++#define LUKS_SECTOR_SIZE (1 << LUKS_SECTOR_SHIFT) ++ ++#define LUKS_CIPHERNAME_L 32 ++#define LUKS_CIPHERMODE_L 32 ++#define LUKS_HASHSPEC_L 32 ++#define LUKS_DIGESTSIZE 20 ++#define LUKS_SALTSIZE 32 ++#define LUKS_NUMKEYS 8 ++ ++#define LUKS_MAGIC_L 6 ++#define LUKS_PHDR_SIZE (sizeof(struct luks_phdr)/LUKS_SECTOR_SIZE+1) ++#define UUID_STRING_L 40 ++static const uint8_t LUKS_MAGIC[] = {'L','U','K','S', 0xba, 0xbe}; ++ ++struct luks_phdr { ++ uint8_t magic[LUKS_MAGIC_L]; ++ uint16_t version; ++ uint8_t cipherName[LUKS_CIPHERNAME_L]; ++ uint8_t cipherMode[LUKS_CIPHERMODE_L]; ++ uint8_t hashSpec[LUKS_HASHSPEC_L]; ++ uint32_t payloadOffset; ++ uint32_t keyBytes; ++ uint8_t mkDigest[LUKS_DIGESTSIZE]; ++ uint8_t mkDigestSalt[LUKS_SALTSIZE]; ++ uint32_t mkDigestIterations; ++ uint8_t uuid[UUID_STRING_L]; ++ struct { ++ uint32_t active; ++ uint32_t passwordIterations; ++ uint8_t passwordSalt[LUKS_SALTSIZE]; ++ uint32_t keyMaterialOffset; ++ uint32_t stripes; ++ } keyblock[LUKS_NUMKEYS]; ++}; ++ ++int volume_id_probe_luks(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ struct luks_phdr *header; ++ ++ header = (struct luks_phdr*) volume_id_get_buffer(id, off, LUKS_PHDR_SIZE); ++ if (header == NULL) ++ return -1; ++ ++ if (memcmp((char *)header->magic, (char *)LUKS_MAGIC, LUKS_MAGIC_L)) ++ return -1; ++ ++ volume_id_set_usage(id, VOLUME_ID_CRYPTO); ++ volume_id_set_uuid(id, header->uuid, 36, UUID_HEX_STRING); ++ sprintf(id->type_version, "%u", le16_to_cpu(header->version)); ++ id->type = "crypto_LUKS"; ++ return 0; ++} + +=== added file 'libvolume_id/lvm.c' +--- grub-0.97.orig/libvolume_id/lvm.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/lvm.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,92 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++struct lvm1_super_block { ++ uint8_t id[2]; ++} PACKED; ++ ++struct lvm2_super_block { ++ uint8_t id[8]; ++ uint64_t sector_xl; ++ uint32_t crc_xl; ++ uint32_t offset_xl; ++ uint8_t type[8]; ++} PACKED; ++ ++#define LVM1_SB_OFF 0x400 ++#define LVM1_MAGIC "HM" ++ ++int volume_id_probe_lvm1(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ const uint8_t *buf; ++ struct lvm1_super_block *lvm; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ buf = volume_id_get_buffer(id, off + LVM1_SB_OFF, 0x800); ++ if (buf == NULL) ++ return -1; ++ ++ lvm = (struct lvm1_super_block *) buf; ++ ++ if (memcmp((char *)lvm->id, LVM1_MAGIC, 2) != 0) ++ return -1; ++ ++ volume_id_set_usage(id, VOLUME_ID_RAID); ++ id->type = "LVM1_member"; ++ ++ return 0; ++} ++ ++#define LVM2_LABEL_ID "LABELONE" ++#define LVM2LABEL_SCAN_SECTORS 4 ++ ++int volume_id_probe_lvm2(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ const uint8_t *buf; ++ unsigned int soff; ++ struct lvm2_super_block *lvm; ++ ++ dbg("probing at offset 0x%llx", (unsigned long long) off); ++ ++ buf = volume_id_get_buffer(id, off, LVM2LABEL_SCAN_SECTORS * 0x200); ++ if (buf == NULL) ++ return -1; ++ ++ ++ for (soff = 0; soff < LVM2LABEL_SCAN_SECTORS * 0x200; soff += 0x200) { ++ lvm = (struct lvm2_super_block *) &buf[soff]; ++ ++ if (memcmp((char *)lvm->id, LVM2_LABEL_ID, 8) == 0) ++ goto found; ++ } ++ ++ return -1; ++ ++found: ++ memcpy(id->type_version, lvm->type, 8); ++ volume_id_set_usage(id, VOLUME_ID_RAID); ++ id->type = "LVM2_member"; ++ ++ return 0; ++} + +=== added file 'libvolume_id/minix.c' +--- grub-0.97.orig/libvolume_id/minix.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/minix.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,112 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2005-2007 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++#define MINIX_SUPERBLOCK_OFFSET 0x400 ++ ++#define MINIX_SUPER_MAGIC 0x137F ++#define MINIX_SUPER_MAGIC2 0x138F ++#define MINIX2_SUPER_MAGIC 0x2468 ++#define MINIX2_SUPER_MAGIC2 0x2478 ++#define MINIX3_SUPER_MAGIC 0x4d5a ++ ++struct minix_super_block ++{ ++ uint16_t s_ninodes; ++ uint16_t s_nzones; ++ uint16_t s_imap_blocks; ++ uint16_t s_zmap_blocks; ++ uint16_t s_firstdatazone; ++ uint16_t s_log_zone_size; ++ uint32_t s_max_size; ++ uint16_t s_magic; ++ uint16_t s_state; ++ uint32_t s_zones; ++} PACKED; ++ ++struct minix3_super_block { ++ uint32_t s_ninodes; ++ uint16_t s_pad0; ++ uint16_t s_imap_blocks; ++ uint16_t s_zmap_blocks; ++ uint16_t s_firstdatazone; ++ uint16_t s_log_zone_size; ++ uint16_t s_pad1; ++ uint32_t s_max_size; ++ uint32_t s_zones; ++ uint16_t s_magic; ++ uint16_t s_pad2; ++ uint16_t s_blocksize; ++ uint8_t s_disk_version; ++} PACKED; ++ ++int volume_id_probe_minix(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ uint8_t *buf; ++ struct minix_super_block *ms; ++ struct minix3_super_block *m3s; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ buf = volume_id_get_buffer(id, off + MINIX_SUPERBLOCK_OFFSET, 0x200); ++ if (buf == NULL) ++ return -1; ++ ++ ms = (struct minix_super_block *) buf; ++ ++ if (ms->s_magic == MINIX_SUPER_MAGIC || ++ ms->s_magic == bswap_16(MINIX_SUPER_MAGIC)) { ++ strcpy(id->type_version, "1"); ++ goto found; ++ } ++ if (ms->s_magic == MINIX_SUPER_MAGIC2 || ++ ms->s_magic == bswap_16(MINIX_SUPER_MAGIC2)) { ++ strcpy(id->type_version, "1"); ++ goto found; ++ } ++ if (ms->s_magic == MINIX2_SUPER_MAGIC || ++ ms->s_magic == bswap_16(MINIX2_SUPER_MAGIC)) { ++ strcpy(id->type_version, "2"); ++ goto found; ++ } ++ if (ms->s_magic == MINIX2_SUPER_MAGIC2 || ++ ms->s_magic == bswap_16(MINIX2_SUPER_MAGIC2)) { ++ strcpy(id->type_version, "2"); ++ goto found; ++ } ++ ++ m3s = (struct minix3_super_block *) buf; ++ if (m3s->s_magic == MINIX3_SUPER_MAGIC || ++ m3s->s_magic == bswap_16(MINIX3_SUPER_MAGIC)) { ++ strcpy(id->type_version, "3"); ++ goto found; ++ } ++ goto exit; ++ ++found: ++ volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); ++ id->type = "minix"; ++ return 0; ++ ++exit: ++ return -1; ++} + +=== added file 'libvolume_id/misc.c' +--- grub-0.97.orig/libvolume_id/misc.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/misc.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,34 @@ ++/* ++ * volume_id/misc.c ++ * ++ * Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++#define _GNU_SOURCE ++#include <string.h> ++ ++/* ++ * Misc auxiliary functions required for volume_id inside grub ++ */ ++size_t strnlen(const char *s, size_t limit) ++{ ++ size_t length = 0; ++ while ( (length < limit) && (*s++) ) ++ length++; ++ ++ return length; ++} ++ ++char *strchr (const char *s, int c) ++{ ++ do { ++ if ( *s == c ) { ++ return (char*)s; ++ } ++ } while ( *s++ ); ++ ++ return 0; ++} + +=== added file 'libvolume_id/netware.c' +--- grub-0.97.orig/libvolume_id/netware.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/netware.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,98 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2006 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++#define NW_SUPERBLOCK_OFFSET 0x1000 ++ ++struct netware_super_block { ++ uint8_t SBH_Signature[4]; ++ uint16_t SBH_VersionMajor; ++ uint16_t SBH_VersionMinor; ++ uint16_t SBH_VersionMediaMajor; ++ uint16_t SBH_VersionMediaMinor; ++ uint32_t SBH_ItemsMoved; ++ uint8_t SBH_InternalID[16]; ++ uint32_t SBH_PackedSize; ++ uint32_t SBH_Checksum; ++ uint32_t supersyncid; ++ int64_t superlocation[4]; ++ uint32_t physSizeUsed; ++ uint32_t sizeUsed; ++ uint32_t superTimeStamp; ++ uint32_t reserved0[1]; ++ int64_t SBH_LoggedPoolDataBlk; ++ int64_t SBH_PoolDataBlk; ++ uint8_t SBH_OldInternalID[16]; ++ uint32_t SBH_PoolToLVStartUTC; ++ uint32_t SBH_PoolToLVEndUTC; ++ uint16_t SBH_VersionMediaMajorCreate; ++ uint16_t SBH_VersionMediaMinorCreate; ++ uint32_t SBH_BlocksMoved; ++ uint32_t SBH_TempBTSpBlk; ++ uint32_t SBH_TempFTSpBlk; ++ uint32_t SBH_TempFTSpBlk1; ++ uint32_t SBH_TempFTSpBlk2; ++ uint32_t nssMagicNumber; ++ uint32_t poolClassID; ++ uint32_t poolID; ++ uint32_t createTime; ++ int64_t SBH_LoggedVolumeDataBlk; ++ int64_t SBH_VolumeDataBlk; ++ int64_t SBH_SystemBeastBlkNum; ++ uint64_t totalblocks; ++ uint16_t SBH_Name[64]; ++ uint8_t SBH_VolumeID[16]; ++ uint8_t SBH_PoolID[16]; ++ uint8_t SBH_PoolInternalID[16]; ++ uint64_t SBH_Lsn; ++ uint32_t SBH_SS_Enabled; ++ uint32_t SBH_SS_CreateTime; ++ uint8_t SBH_SS_OriginalPoolID[16]; ++ uint8_t SBH_SS_OriginalVolumeID[16]; ++ uint8_t SBH_SS_Guid[16]; ++ uint16_t SBH_SS_OriginalName[64]; ++ uint32_t reserved2[64-(2+46)]; ++} PACKED; ++ ++int volume_id_probe_netware(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ struct netware_super_block *nw; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ nw = (struct netware_super_block *) volume_id_get_buffer(id, off + NW_SUPERBLOCK_OFFSET, 0x200); ++ if (nw == NULL) ++ return -1; ++ ++ if (memcmp((char *)nw->SBH_Signature, "SPB5", 4) != 0) ++ return -1; ++ ++ volume_id_set_uuid(id, nw->SBH_PoolID, 0, UUID_DCE); ++ ++ sprintf(id->type_version, "%u.%02u", ++ le16_to_cpu(nw->SBH_VersionMediaMajor), le16_to_cpu(nw->SBH_VersionMediaMinor)); ++ ++ volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); ++ id->type = "nss"; ++ ++ return 0; ++} + +=== added file 'libvolume_id/ntfs.c' +--- grub-0.97.orig/libvolume_id/ntfs.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/ntfs.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,192 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++static struct ntfs_super_block { ++ uint8_t jump[3]; ++ uint8_t oem_id[8]; ++ uint16_t bytes_per_sector; ++ uint8_t sectors_per_cluster; ++ uint16_t reserved_sectors; ++ uint8_t fats; ++ uint16_t root_entries; ++ uint16_t sectors; ++ uint8_t media_type; ++ uint16_t sectors_per_fat; ++ uint16_t sectors_per_track; ++ uint16_t heads; ++ uint32_t hidden_sectors; ++ uint32_t large_sectors; ++ uint16_t unused[2]; ++ uint64_t number_of_sectors; ++ uint64_t mft_cluster_location; ++ uint64_t mft_mirror_cluster_location; ++ int8_t cluster_per_mft_record; ++ uint8_t reserved1[3]; ++ int8_t cluster_per_index_record; ++ uint8_t reserved2[3]; ++ uint8_t volume_serial[8]; ++ uint16_t checksum; ++} PACKED *ns; ++ ++static struct master_file_table_record { ++ uint8_t magic[4]; ++ uint16_t usa_ofs; ++ uint16_t usa_count; ++ uint64_t lsn; ++ uint16_t sequence_number; ++ uint16_t link_count; ++ uint16_t attrs_offset; ++ uint16_t flags; ++ uint32_t bytes_in_use; ++ uint32_t bytes_allocated; ++} PACKED *mftr; ++ ++static struct file_attribute { ++ uint32_t type; ++ uint32_t len; ++ uint8_t non_resident; ++ uint8_t name_len; ++ uint16_t name_offset; ++ uint16_t flags; ++ uint16_t instance; ++ uint32_t value_len; ++ uint16_t value_offset; ++} PACKED *attr; ++ ++static struct volume_info { ++ uint64_t reserved; ++ uint8_t major_ver; ++ uint8_t minor_ver; ++} PACKED *info; ++ ++#define MFT_RECORD_VOLUME 3 ++#define MFT_RECORD_ATTR_VOLUME_NAME 0x60 ++#define MFT_RECORD_ATTR_VOLUME_INFO 0x70 ++#define MFT_RECORD_ATTR_OBJECT_ID 0x40 ++#define MFT_RECORD_ATTR_END 0xffffffffu ++ ++#undef debug ++#define debug grub_printf ++ ++int volume_id_probe_ntfs(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ unsigned int sector_size; ++ unsigned int cluster_size; ++ uint64_t mft_cluster; ++ uint64_t mft_off; ++ unsigned int mft_record_size; ++ unsigned int attr_type; ++ unsigned int attr_off; ++ unsigned int attr_len; ++ unsigned int val_off; ++ unsigned int val_len; ++ const uint8_t *buf; ++ const uint8_t *val; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ ns = (struct ntfs_super_block *) volume_id_get_buffer(id, off, 0x200); ++ if (ns == NULL) ++ return -1; ++ ++ if (memcmp((char *)ns->oem_id, "NTFS", 4) != 0) ++ return -1; ++ ++ volume_id_set_uuid(id, ns->volume_serial, 0, UUID_64BIT_LE); ++ ++ sector_size = le16_to_cpu(ns->bytes_per_sector); ++ if (sector_size < 0x200) ++ return -1; ++ ++ cluster_size = ns->sectors_per_cluster * sector_size; ++ mft_cluster = le64_to_cpu(ns->mft_cluster_location); ++ mft_off = mft_cluster * cluster_size; ++ ++ if (ns->cluster_per_mft_record < 0) ++ /* size = -log2(mft_record_size); normally 1024 Bytes */ ++ mft_record_size = 1 << -ns->cluster_per_mft_record; ++ else ++ mft_record_size = ns->cluster_per_mft_record * cluster_size; ++ ++ dbg("sectorsize 0x%x", sector_size); ++ dbg("clustersize 0x%x", cluster_size); ++ dbg("mftcluster %llu", (unsigned long long) mft_cluster); ++ dbg("mftoffset 0x%llx", (unsigned long long) mft_off); ++ dbg("cluster per mft_record %i", ns->cluster_per_mft_record); ++ dbg("mft record size %i", mft_record_size); ++ ++ buf = volume_id_get_buffer(id, off + mft_off + (MFT_RECORD_VOLUME * mft_record_size), ++ mft_record_size); ++ if (buf == NULL) ++ return -1; ++ ++ mftr = (struct master_file_table_record*) buf; ++ dbg("mftr->magic '%c%c%c%c'", mftr->magic[0], mftr->magic[1], mftr->magic[2], mftr->magic[3]); ++ if (memcmp((char *)mftr->magic, "FILE", 4) != 0) ++ return -1; ++ ++ attr_off = le16_to_cpu(mftr->attrs_offset); ++ dbg("file $Volume's attributes are at offset %i", attr_off); ++ ++ while (1) { ++ attr = (struct file_attribute*) &buf[attr_off]; ++ attr_type = le32_to_cpu(attr->type); ++ attr_len = le16_to_cpu(attr->len); ++ val_off = le16_to_cpu(attr->value_offset); ++ val_len = le32_to_cpu(attr->value_len); ++ attr_off += attr_len; ++ ++ if (attr_len == 0) ++ break; ++ ++ if (attr_off >= mft_record_size) ++ break; ++ ++ if (attr_type == MFT_RECORD_ATTR_END) ++ break; ++ ++ dbg("found attribute type 0x%x, len %i, at offset %i", ++ attr_type, attr_len, attr_off); ++ ++ if (attr_type == MFT_RECORD_ATTR_VOLUME_INFO) { ++ dbg("found info, len %i", val_len); ++ info = (struct volume_info*) (((uint8_t *) attr) + val_off); ++ sprintf(id->type_version, "%u.%u", info->major_ver, info->minor_ver); ++ } ++ ++ if (attr_type == MFT_RECORD_ATTR_VOLUME_NAME) { ++ dbg("found label, len %i", val_len); ++ if (val_len > VOLUME_ID_LABEL_SIZE) ++ val_len = VOLUME_ID_LABEL_SIZE; ++ ++ val = ((uint8_t *) attr) + val_off; ++ volume_id_set_label_raw(id, val, val_len); ++ volume_id_set_label_unicode16(id, val, LE, val_len); ++ } ++ } ++ ++ volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); ++ id->type = "ntfs"; ++ ++ return 0; ++} + +=== added file 'libvolume_id/nvidia_raid.c' +--- grub-0.97.orig/libvolume_id/nvidia_raid.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/nvidia_raid.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,59 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++struct nvidia_meta { ++ uint8_t vendor[8]; ++ uint32_t size; ++ uint32_t chksum; ++ uint16_t version; ++} PACKED; ++ ++#define NVIDIA_SIGNATURE "NVIDIA" ++ ++int volume_id_probe_nvidia_raid(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ const uint8_t *buf; ++ uint64_t meta_off; ++ struct nvidia_meta *nv; ++ ++ info("probing at offset 0x%llx, size 0x%llx", ++ (unsigned long long) off, (unsigned long long) size); ++ ++ if (size < 0x10000) ++ return -1; ++ ++ meta_off = ((size / 0x200)-2) * 0x200; ++ buf = volume_id_get_buffer(id, off + meta_off, 0x200); ++ if (buf == NULL) ++ return -1; ++ ++ nv = (struct nvidia_meta *) buf; ++ if (memcmp((char *)nv->vendor, NVIDIA_SIGNATURE, sizeof(NVIDIA_SIGNATURE)-1) != 0) ++ return -1; ++ ++ volume_id_set_usage(id, VOLUME_ID_RAID); ++ sprintf(id->type_version, "%u", le16_to_cpu(nv->version)); ++ id->type = "nvidia_raid_member"; ++ ++ return 0; ++} + +=== added file 'libvolume_id/ocfs.c' +--- grub-0.97.orig/libvolume_id/ocfs.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/ocfs.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,186 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2004 Andre Masella <andre@masella.no-ip.org> ++ * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++struct ocfs1_super_block_header { ++ uint32_t minor_version; ++ uint32_t major_version; ++ uint8_t signature[128]; ++ uint8_t mount_point[128]; ++ uint64_t serial_num; ++ uint64_t device_size; ++ uint64_t start_off; ++ uint64_t bitmap_off; ++ uint64_t publ_off; ++ uint64_t vote_off; ++ uint64_t root_bitmap_off; ++ uint64_t data_start_off; ++ uint64_t root_bitmap_size; ++ uint64_t root_off; ++ uint64_t root_size; ++ uint64_t cluster_size; ++ uint64_t num_nodes; ++ uint64_t num_clusters; ++ uint64_t dir_node_size; ++ uint64_t file_node_size; ++ uint64_t internal_off; ++ uint64_t node_cfg_off; ++ uint64_t node_cfg_size; ++ uint64_t new_cfg_off; ++ uint32_t prot_bits; ++ int32_t excl_mount; ++} PACKED; ++ ++struct ocfs1_super_block_label { ++ struct ocfs1_disk_lock { ++ uint32_t curr_master; ++ uint8_t file_lock; ++ uint8_t compat_pad[3]; ++ uint64_t last_write_time; ++ uint64_t last_read_time; ++ uint32_t writer_node_num; ++ uint32_t reader_node_num; ++ uint64_t oin_node_map; ++ uint64_t dlock_seq_num; ++ } PACKED disk_lock; ++ uint8_t label[64]; ++ uint16_t label_len; ++ uint8_t vol_id[16]; ++ uint16_t vol_id_len; ++ uint8_t cluster_name[64]; ++ uint16_t cluster_name_len; ++} PACKED; ++ ++struct ocfs2_super_block { ++ uint8_t i_signature[8]; ++ uint32_t i_generation; ++ int16_t i_suballoc_slot; ++ uint16_t i_suballoc_bit; ++ uint32_t i_reserved0; ++ uint32_t i_clusters; ++ uint32_t i_uid; ++ uint32_t i_gid; ++ uint64_t i_size; ++ uint16_t i_mode; ++ uint16_t i_links_count; ++ uint32_t i_flags; ++ uint64_t i_atime; ++ uint64_t i_ctime; ++ uint64_t i_mtime; ++ uint64_t i_dtime; ++ uint64_t i_blkno; ++ uint64_t i_last_eb_blk; ++ uint32_t i_fs_generation; ++ uint32_t i_atime_nsec; ++ uint32_t i_ctime_nsec; ++ uint32_t i_mtime_nsec; ++ uint64_t i_reserved1[9]; ++ uint64_t i_pad1; ++ uint16_t s_major_rev_level; ++ uint16_t s_minor_rev_level; ++ uint16_t s_mnt_count; ++ int16_t s_max_mnt_count; ++ uint16_t s_state; ++ uint16_t s_errors; ++ uint32_t s_checkinterval; ++ uint64_t s_lastcheck; ++ uint32_t s_creator_os; ++ uint32_t s_feature_compat; ++ uint32_t s_feature_incompat; ++ uint32_t s_feature_ro_compat; ++ uint64_t s_root_blkno; ++ uint64_t s_system_dir_blkno; ++ uint32_t s_blocksize_bits; ++ uint32_t s_clustersize_bits; ++ uint16_t s_max_slots; ++ uint16_t s_reserved1; ++ uint32_t s_reserved2; ++ uint64_t s_first_cluster_group; ++ uint8_t s_label[64]; ++ uint8_t s_uuid[16]; ++} PACKED; ++ ++int volume_id_probe_ocfs1(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ const uint8_t *buf; ++ struct ocfs1_super_block_header *osh; ++ struct ocfs1_super_block_label *osl; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ buf = volume_id_get_buffer(id, off, 0x200); ++ if (buf == NULL) ++ return -1; ++ ++ osh = (struct ocfs1_super_block_header *) buf; ++ if (memcmp((char *)osh->signature, "OracleCFS", 9) != 0) ++ return -1; ++ sprintf(id->type_version, "%u.%u", osh->major_version, osh->minor_version); ++ ++ dbg("found OracleCFS signature, now reading label"); ++ buf = volume_id_get_buffer(id, off + 0x200, 0x200); ++ if (buf == NULL) ++ return -1; ++ ++ osl = (struct ocfs1_super_block_label *) buf; ++ volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); ++ if (osl->label_len <= 64) { ++ volume_id_set_label_raw(id, osl->label, 64); ++ volume_id_set_label_string(id, osl->label, 64); ++ } ++ if (osl->vol_id_len == 16) ++ volume_id_set_uuid(id, osl->vol_id, 0, UUID_DCE); ++ id->type = "ocfs"; ++ return 0; ++} ++ ++#define OCFS2_MAX_BLOCKSIZE 0x1000 ++#define OCFS2_SUPER_BLOCK_BLKNO 2 ++ ++int volume_id_probe_ocfs2(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ const uint8_t *buf; ++ struct ocfs2_super_block *os; ++ size_t blksize; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ for (blksize = 0x200; blksize <= OCFS2_MAX_BLOCKSIZE; blksize <<= 1) { ++ buf = volume_id_get_buffer(id, off + OCFS2_SUPER_BLOCK_BLKNO * blksize, 0x200); ++ if (buf == NULL) ++ return -1; ++ ++ os = (struct ocfs2_super_block *) buf; ++ if (memcmp((char *)os->i_signature, "OCFSV2", 6) != 0) ++ continue; ++ ++ volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); ++ volume_id_set_label_raw(id, os->s_label, 64); ++ volume_id_set_label_string(id, os->s_label, 64); ++ volume_id_set_uuid(id, os->s_uuid, 0, UUID_DCE); ++ sprintf(id->type_version, "%u.%u", os->s_major_rev_level, os->s_minor_rev_level); ++ id->type = "ocfs2"; ++ return 0; ++ } ++ return -1; ++} + +=== added file 'libvolume_id/promise_raid.c' +--- grub-0.97.orig/libvolume_id/promise_raid.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/promise_raid.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,65 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++struct promise_meta { ++ uint8_t sig[24]; ++} PACKED; ++ ++#define PDC_CONFIG_OFF 0x1200 ++#define PDC_SIGNATURE "Promise Technology, Inc." ++ ++int volume_id_probe_promise_fasttrack_raid(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ const uint8_t *buf; ++ struct promise_meta *pdc; ++ unsigned int i; ++ static unsigned int sectors[] = { ++ 63, 255, 256, 16, 399, 0 ++ }; ++ ++ info("probing at offset 0x%llx, size 0x%llx", ++ (unsigned long long) off, (unsigned long long) size); ++ ++ if (size < 0x40000) ++ return -1; ++ ++ for (i = 0; sectors[i] != 0; i++) { ++ uint64_t meta_off; ++ ++ meta_off = ((size / 0x200) - sectors[i]) * 0x200; ++ buf = volume_id_get_buffer(id, off + meta_off, 0x200); ++ if (buf == NULL) ++ return -1; ++ ++ pdc = (struct promise_meta *) buf; ++ if (memcmp((char *)pdc->sig, PDC_SIGNATURE, sizeof(PDC_SIGNATURE)-1) == 0) ++ goto found; ++ } ++ return -1; ++ ++found: ++ volume_id_set_usage(id, VOLUME_ID_RAID); ++ id->type = "promise_fasttrack_raid_member"; ++ ++ return 0; ++} + +=== added file 'libvolume_id/reiserfs.c' +--- grub-0.97.orig/libvolume_id/reiserfs.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/reiserfs.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,113 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> ++ * Copyright (C) 2005 Tobias Klauser <tklauser@access.unizh.ch> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++struct reiserfs_super_block { ++ uint32_t blocks_count; ++ uint32_t free_blocks; ++ uint32_t root_block; ++ uint32_t journal_block; ++ uint32_t journal_dev; ++ uint32_t orig_journal_size; ++ uint32_t dummy2[5]; ++ uint16_t blocksize; ++ uint16_t dummy3[3]; ++ uint8_t magic[12]; ++ uint32_t dummy4[5]; ++ uint8_t uuid[16]; ++ uint8_t label[16]; ++} PACKED; ++ ++struct reiser4_super_block { ++ uint8_t magic[16]; ++ uint16_t dummy[2]; ++ uint8_t uuid[16]; ++ uint8_t label[16]; ++ uint64_t dummy2; ++} PACKED; ++ ++#define REISERFS1_SUPERBLOCK_OFFSET 0x2000 ++#define REISERFS_SUPERBLOCK_OFFSET 0x10000 ++ ++int volume_id_probe_reiserfs(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ struct reiserfs_super_block *rs; ++ struct reiser4_super_block *rs4; ++ uint8_t *buf; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ buf = volume_id_get_buffer(id, off + REISERFS_SUPERBLOCK_OFFSET, 0x200); ++ if (buf == NULL) ++ return -1; ++ ++ rs = (struct reiserfs_super_block *) buf; ++ if (memcmp((char *)rs->magic, "ReIsErFs", 8) == 0) { ++ strcpy(id->type_version, "3.5"); ++ id->type = "reiserfs"; ++ goto found; ++ } ++ if (memcmp((char *)rs->magic, "ReIsEr2Fs", 9) == 0) { ++ strcpy(id->type_version, "3.6"); ++ id->type = "reiserfs"; ++ goto found_label; ++ } ++ if (memcmp((char *)rs->magic, "ReIsEr3Fs", 9) == 0) { ++ strcpy(id->type_version, "JR"); ++ id->type = "reiserfs"; ++ goto found_label; ++ } ++ ++ rs4 = (struct reiser4_super_block *) buf; ++ if (memcmp((char *)rs4->magic, "ReIsEr4", 7) == 0) { ++ strcpy(id->type_version, "4"); ++ volume_id_set_label_raw(id, rs4->label, 16); ++ volume_id_set_label_string(id, rs4->label, 16); ++ volume_id_set_uuid(id, rs4->uuid, 0, UUID_DCE); ++ id->type = "reiser4"; ++ goto found; ++ } ++ ++ buf = volume_id_get_buffer(id, off + REISERFS1_SUPERBLOCK_OFFSET, 0x200); ++ if (buf == NULL) ++ return -1; ++ ++ rs = (struct reiserfs_super_block *) buf; ++ if (memcmp((char *)rs->magic, "ReIsErFs", 8) == 0) { ++ strcpy(id->type_version, "3.5"); ++ id->type = "reiserfs"; ++ goto found; ++ } ++ ++ return -1; ++ ++found_label: ++ volume_id_set_label_raw(id, rs->label, 16); ++ volume_id_set_label_string(id, rs->label, 16); ++ volume_id_set_uuid(id, rs->uuid, 0, UUID_DCE); ++ ++found: ++ volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); ++ ++ return 0; ++} + +=== added file 'libvolume_id/romfs.c' +--- grub-0.97.orig/libvolume_id/romfs.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/romfs.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,55 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++struct romfs_super { ++ uint8_t magic[8]; ++ uint32_t size; ++ uint32_t checksum; ++ uint8_t name[0]; ++} PACKED; ++ ++int volume_id_probe_romfs(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ struct romfs_super *rfs; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ rfs = (struct romfs_super *) volume_id_get_buffer(id, off, 0x200); ++ if (rfs == NULL) ++ return -1; ++ ++ if (memcmp((char *)rfs->magic, "-rom1fs-", 4) == 0) { ++ size_t len = strlen((char *)rfs->name); ++ ++ if (len) { ++ volume_id_set_label_raw(id, rfs->name, len); ++ volume_id_set_label_string(id, rfs->name, len); ++ } ++ ++ volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); ++ id->type = "romfs"; ++ return 0; ++ } ++ ++ return -1; ++} + +=== added file 'libvolume_id/silicon_raid.c' +--- grub-0.97.orig/libvolume_id/silicon_raid.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/silicon_raid.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,71 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++struct silicon_meta { ++ uint8_t unknown0[0x2E]; ++ uint8_t ascii_version[0x36 - 0x2E]; ++ uint8_t diskname[0x56 - 0x36]; ++ uint8_t unknown1[0x60 - 0x56]; ++ uint32_t magic; ++ uint32_t unknown1a[0x6C - 0x64]; ++ uint32_t array_sectors_low; ++ uint32_t array_sectors_high; ++ uint8_t unknown2[0x78 - 0x74]; ++ uint32_t thisdisk_sectors; ++ uint8_t unknown3[0x100 - 0x7C]; ++ uint8_t unknown4[0x104 - 0x100]; ++ uint16_t product_id; ++ uint16_t vendor_id; ++ uint16_t minor_ver; ++ uint16_t major_ver; ++} PACKED; ++ ++#define SILICON_MAGIC 0x2F000000 ++ ++int volume_id_probe_silicon_medley_raid(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ const uint8_t *buf; ++ uint64_t meta_off; ++ struct silicon_meta *sil; ++ ++ info("probing at offset 0x%llx, size 0x%llx", ++ (unsigned long long) off, (unsigned long long) size); ++ ++ if (size < 0x10000) ++ return -1; ++ ++ meta_off = ((size / 0x200)-1) * 0x200; ++ buf = volume_id_get_buffer(id, off + meta_off, 0x200); ++ if (buf == NULL) ++ return -1; ++ ++ sil = (struct silicon_meta *) buf; ++ if (le32_to_cpu(sil->magic) != SILICON_MAGIC) ++ return -1; ++ ++ volume_id_set_usage(id, VOLUME_ID_RAID); ++ sprintf(id->type_version, "%u.%u", le16_to_cpu(sil->major_ver), le16_to_cpu(sil->minor_ver)); ++ id->type = "silicon_medley_raid_member"; ++ ++ return 0; ++} + +=== added file 'libvolume_id/squashfs.c' +--- grub-0.97.orig/libvolume_id/squashfs.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/squashfs.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,63 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2006 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++#define SQUASHFS_MAGIC 0x73717368 ++ ++struct squashfs_super { ++ uint32_t s_magic; ++ uint32_t inodes; ++ uint32_t bytes_used_2; ++ uint32_t uid_start_2; ++ uint32_t guid_start_2; ++ uint32_t inode_table_start_2; ++ uint32_t directory_table_start_2; ++ uint16_t s_major; ++ uint16_t s_minor; ++} PACKED; ++ ++int volume_id_probe_squashfs(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ struct squashfs_super *sqs; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ sqs = (struct squashfs_super *) volume_id_get_buffer(id, off, 0x200); ++ if (sqs == NULL) ++ return -1; ++ ++ if (sqs->s_magic == SQUASHFS_MAGIC) { ++ sprintf(id->type_version, "%u.%u", sqs->s_major, sqs->s_minor); ++ goto found; ++ } ++ if (sqs->s_magic == bswap_32(SQUASHFS_MAGIC)) { ++ sprintf(id->type_version, "%u.%u", bswap_16(sqs->s_major), bswap_16(sqs->s_minor)); ++ goto found; ++ } ++ ++ return -1; ++ ++found: ++ volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); ++ id->type = "squashfs"; ++ return 0; ++} + +=== added file 'libvolume_id/strfuncs.h' +--- grub-0.97.orig/libvolume_id/strfuncs.h 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/strfuncs.h 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,5 @@ ++ ++#include <stdlib.h> ++ ++size_t strnlen(const char *s, size_t limit); ++char *strchr (const char *s, int c); + +=== added file 'libvolume_id/sysv.c' +--- grub-0.97.orig/libvolume_id/sysv.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/sysv.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,128 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++#define SYSV_NICINOD 100 ++#define SYSV_NICFREE 50 ++ ++struct sysv_super ++{ ++ uint16_t s_isize; ++ uint16_t s_pad0; ++ uint32_t s_fsize; ++ uint16_t s_nfree; ++ uint16_t s_pad1; ++ uint32_t s_free[SYSV_NICFREE]; ++ uint16_t s_ninode; ++ uint16_t s_pad2; ++ uint16_t s_inode[SYSV_NICINOD]; ++ uint8_t s_flock; ++ uint8_t s_ilock; ++ uint8_t s_fmod; ++ uint8_t s_ronly; ++ uint32_t s_time; ++ uint16_t s_dinfo[4]; ++ uint32_t s_tfree; ++ uint16_t s_tinode; ++ uint16_t s_pad3; ++ uint8_t s_fname[6]; ++ uint8_t s_fpack[6]; ++ uint32_t s_fill[12]; ++ uint32_t s_state; ++ uint32_t s_magic; ++ uint32_t s_type; ++} PACKED; ++ ++#define XENIX_NICINOD 100 ++#define XENIX_NICFREE 100 ++ ++struct xenix_super { ++ uint16_t s_isize; ++ uint32_t s_fsize; ++ uint16_t s_nfree; ++ uint32_t s_free[XENIX_NICFREE]; ++ uint16_t s_ninode; ++ uint16_t s_inode[XENIX_NICINOD]; ++ uint8_t s_flock; ++ uint8_t s_ilock; ++ uint8_t s_fmod; ++ uint8_t s_ronly; ++ uint32_t s_time; ++ uint32_t s_tfree; ++ uint16_t s_tinode; ++ uint16_t s_dinfo[4]; ++ uint8_t s_fname[6]; ++ uint8_t s_fpack[6]; ++ uint8_t s_clean; ++ uint8_t s_fill[371]; ++ uint32_t s_magic; ++ uint32_t s_type; ++} PACKED; ++ ++#define SYSV_SUPERBLOCK_BLOCK 0x01 ++#define SYSV_MAGIC 0xfd187e20 ++#define XENIX_SUPERBLOCK_BLOCK 0x18 ++#define XENIX_MAGIC 0x2b5544 ++#define SYSV_MAX_BLOCKSIZE 0x800 ++ ++int volume_id_probe_sysv(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ struct sysv_super *vs; ++ struct xenix_super *xs; ++ unsigned int boff; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ for (boff = 0x200; boff <= SYSV_MAX_BLOCKSIZE; boff <<= 1) { ++ vs = (struct sysv_super *) ++ volume_id_get_buffer(id, off + (boff * SYSV_SUPERBLOCK_BLOCK), 0x200); ++ if (vs == NULL) ++ return -1; ++ ++ if (vs->s_magic == cpu_to_le32(SYSV_MAGIC) || vs->s_magic == cpu_to_be32(SYSV_MAGIC)) { ++ volume_id_set_label_raw(id, vs->s_fname, 6); ++ volume_id_set_label_string(id, vs->s_fname, 6); ++ id->type = "sysv"; ++ goto found; ++ } ++ } ++ ++ for (boff = 0x200; boff <= SYSV_MAX_BLOCKSIZE; boff <<= 1) { ++ xs = (struct xenix_super *) ++ volume_id_get_buffer(id, off + (boff + XENIX_SUPERBLOCK_BLOCK), 0x200); ++ if (xs == NULL) ++ return -1; ++ ++ if (xs->s_magic == cpu_to_le32(XENIX_MAGIC) || xs->s_magic == cpu_to_be32(XENIX_MAGIC)) { ++ volume_id_set_label_raw(id, xs->s_fname, 6); ++ volume_id_set_label_string(id, xs->s_fname, 6); ++ id->type = "xenix"; ++ goto found; ++ } ++ } ++ ++ return -1; ++ ++found: ++ volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); ++ return 0; ++} + +=== added file 'libvolume_id/udf.c' +--- grub-0.97.orig/libvolume_id/udf.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/udf.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,173 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++struct volume_descriptor { ++ struct descriptor_tag { ++ uint16_t id; ++ uint16_t version; ++ uint8_t checksum; ++ uint8_t reserved; ++ uint16_t serial; ++ uint16_t crc; ++ uint16_t crc_len; ++ uint32_t location; ++ } PACKED tag; ++ union { ++ struct anchor_descriptor { ++ uint32_t length; ++ uint32_t location; ++ } PACKED anchor; ++ struct primary_descriptor { ++ uint32_t seq_num; ++ uint32_t desc_num; ++ struct dstring { ++ uint8_t clen; ++ uint8_t c[31]; ++ } PACKED ident; ++ } PACKED primary; ++ } PACKED type; ++} PACKED; ++ ++struct volume_structure_descriptor { ++ uint8_t type; ++ uint8_t id[5]; ++ uint8_t version; ++} PACKED; ++ ++#define UDF_VSD_OFFSET 0x8000 ++ ++int volume_id_probe_udf(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ struct volume_descriptor *vd; ++ struct volume_structure_descriptor *vsd; ++ unsigned int bs; ++ unsigned int b; ++ unsigned int type; ++ unsigned int count; ++ unsigned int loc; ++ unsigned int clen; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ vsd = (struct volume_structure_descriptor *) volume_id_get_buffer(id, off + UDF_VSD_OFFSET, 0x200); ++ if (vsd == NULL) ++ return -1; ++ ++ if (memcmp((char *)vsd->id, "NSR02", 5) == 0) ++ goto blocksize; ++ if (memcmp((char *)vsd->id, "NSR03", 5) == 0) ++ goto blocksize; ++ if (memcmp((char *)vsd->id, "BEA01", 5) == 0) ++ goto blocksize; ++ if (memcmp((char *)vsd->id, "BOOT2", 5) == 0) ++ goto blocksize; ++ if (memcmp((char *)vsd->id, "CD001", 5) == 0) ++ goto blocksize; ++ if (memcmp((char *)vsd->id, "CDW02", 5) == 0) ++ goto blocksize; ++ if (memcmp((char *)vsd->id, "TEA03", 5) == 0) ++ goto blocksize; ++ return -1; ++ ++blocksize: ++ /* search the next VSD to get the logical block size of the volume */ ++ for (bs = 0x800; bs < 0x8000; bs += 0x800) { ++ vsd = (struct volume_structure_descriptor *) volume_id_get_buffer(id, off + UDF_VSD_OFFSET + bs, 0x800); ++ if (vsd == NULL) ++ return -1; ++ dbg("test for blocksize: 0x%x", bs); ++ if (vsd->id[0] != '\0') ++ goto nsr; ++ } ++ return -1; ++ ++nsr: ++ /* search the list of VSDs for a NSR descriptor */ ++ for (b = 0; b < 64; b++) { ++ vsd = (struct volume_structure_descriptor *) volume_id_get_buffer(id, off + UDF_VSD_OFFSET + (b * bs), 0x800); ++ if (vsd == NULL) ++ return -1; ++ ++ dbg("vsd: %c%c%c%c%c", ++ vsd->id[0], vsd->id[1], vsd->id[2], vsd->id[3], vsd->id[4]); ++ ++ if (vsd->id[0] == '\0') ++ return -1; ++ if (memcmp((char *)vsd->id, "NSR02", 5) == 0) ++ goto anchor; ++ if (memcmp((char *)vsd->id, "NSR03", 5) == 0) ++ goto anchor; ++ } ++ return -1; ++ ++anchor: ++ /* read anchor volume descriptor */ ++ vd = (struct volume_descriptor *) volume_id_get_buffer(id, off + (256 * bs), 0x200); ++ if (vd == NULL) ++ return -1; ++ ++ type = le16_to_cpu(vd->tag.id); ++ if (type != 2) /* TAG_ID_AVDP */ ++ goto found; ++ ++ /* get desriptor list address and block count */ ++ count = le32_to_cpu(vd->type.anchor.length) / bs; ++ loc = le32_to_cpu(vd->type.anchor.location); ++ dbg("0x%x descriptors starting at logical secor 0x%x", count, loc); ++ ++ /* pick the primary descriptor from the list */ ++ for (b = 0; b < count; b++) { ++ vd = (struct volume_descriptor *) volume_id_get_buffer(id, off + ((loc + b) * bs), 0x200); ++ if (vd == NULL) ++ return -1; ++ ++ type = le16_to_cpu(vd->tag.id); ++ dbg("descriptor type %i", type); ++ ++ /* check validity */ ++ if (type == 0) ++ goto found; ++ if (le32_to_cpu(vd->tag.location) != loc + b) ++ goto found; ++ ++ if (type == 1) /* TAG_ID_PVD */ ++ goto pvd; ++ } ++ goto found; ++ ++pvd: ++ volume_id_set_label_raw(id, &(vd->type.primary.ident.clen), 32); ++ ++ clen = vd->type.primary.ident.clen; ++ dbg("label string charsize=%i bit", clen); ++ if (clen == 8) ++ volume_id_set_label_string(id, vd->type.primary.ident.c, 31); ++ else if (clen == 16) ++ volume_id_set_label_unicode16(id, vd->type.primary.ident.c, BE,31); ++ ++found: ++ volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); ++ id->type = "udf"; ++ ++ return 0; ++} + +=== added file 'libvolume_id/ufs.c' +--- grub-0.97.orig/libvolume_id/ufs.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/ufs.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,217 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++struct ufs_super_block { ++ uint32_t fs_link; ++ uint32_t fs_rlink; ++ uint32_t fs_sblkno; ++ uint32_t fs_cblkno; ++ uint32_t fs_iblkno; ++ uint32_t fs_dblkno; ++ uint32_t fs_cgoffset; ++ uint32_t fs_cgmask; ++ uint32_t fs_time; ++ uint32_t fs_size; ++ uint32_t fs_dsize; ++ uint32_t fs_ncg; ++ uint32_t fs_bsize; ++ uint32_t fs_fsize; ++ uint32_t fs_frag; ++ uint32_t fs_minfree; ++ uint32_t fs_rotdelay; ++ uint32_t fs_rps; ++ uint32_t fs_bmask; ++ uint32_t fs_fmask; ++ uint32_t fs_bshift; ++ uint32_t fs_fshift; ++ uint32_t fs_maxcontig; ++ uint32_t fs_maxbpg; ++ uint32_t fs_fragshift; ++ uint32_t fs_fsbtodb; ++ uint32_t fs_sbsize; ++ uint32_t fs_csmask; ++ uint32_t fs_csshift; ++ uint32_t fs_nindir; ++ uint32_t fs_inopb; ++ uint32_t fs_nspf; ++ uint32_t fs_optim; ++ uint32_t fs_npsect_state; ++ uint32_t fs_interleave; ++ uint32_t fs_trackskew; ++ uint32_t fs_id[2]; ++ uint32_t fs_csaddr; ++ uint32_t fs_cssize; ++ uint32_t fs_cgsize; ++ uint32_t fs_ntrak; ++ uint32_t fs_nsect; ++ uint32_t fs_spc; ++ uint32_t fs_ncyl; ++ uint32_t fs_cpg; ++ uint32_t fs_ipg; ++ uint32_t fs_fpg; ++ struct ufs_csum { ++ uint32_t cs_ndir; ++ uint32_t cs_nbfree; ++ uint32_t cs_nifree; ++ uint32_t cs_nffree; ++ } PACKED fs_cstotal; ++ int8_t fs_fmod; ++ int8_t fs_clean; ++ int8_t fs_ronly; ++ int8_t fs_flags; ++ union { ++ struct { ++ int8_t fs_fsmnt[512]; ++ uint32_t fs_cgrotor; ++ uint32_t fs_csp[31]; ++ uint32_t fs_maxcluster; ++ uint32_t fs_cpc; ++ uint16_t fs_opostbl[16][8]; ++ } PACKED fs_u1; ++ struct { ++ int8_t fs_fsmnt[468]; ++ uint8_t fs_volname[32]; ++ uint64_t fs_swuid; ++ int32_t fs_pad; ++ uint32_t fs_cgrotor; ++ uint32_t fs_ocsp[28]; ++ uint32_t fs_contigdirs; ++ uint32_t fs_csp; ++ uint32_t fs_maxcluster; ++ uint32_t fs_active; ++ int32_t fs_old_cpc; ++ int32_t fs_maxbsize; ++ int64_t fs_sparecon64[17]; ++ int64_t fs_sblockloc; ++ struct ufs2_csum_total { ++ uint64_t cs_ndir; ++ uint64_t cs_nbfree; ++ uint64_t cs_nifree; ++ uint64_t cs_nffree; ++ uint64_t cs_numclusters; ++ uint64_t cs_spare[3]; ++ } PACKED fs_cstotal; ++ struct ufs_timeval { ++ int32_t tv_sec; ++ int32_t tv_usec; ++ } PACKED fs_time; ++ int64_t fs_size; ++ int64_t fs_dsize; ++ uint64_t fs_csaddr; ++ int64_t fs_pendingblocks; ++ int32_t fs_pendinginodes; ++ } PACKED fs_u2; ++ } fs_u11; ++ union { ++ struct { ++ int32_t fs_sparecon[53]; ++ int32_t fs_reclaim; ++ int32_t fs_sparecon2[1]; ++ int32_t fs_state; ++ uint32_t fs_qbmask[2]; ++ uint32_t fs_qfmask[2]; ++ } PACKED fs_sun; ++ struct { ++ int32_t fs_sparecon[53]; ++ int32_t fs_reclaim; ++ int32_t fs_sparecon2[1]; ++ uint32_t fs_npsect; ++ uint32_t fs_qbmask[2]; ++ uint32_t fs_qfmask[2]; ++ } PACKED fs_sunx86; ++ struct { ++ int32_t fs_sparecon[50]; ++ int32_t fs_contigsumsize; ++ int32_t fs_maxsymlinklen; ++ int32_t fs_inodefmt; ++ uint32_t fs_maxfilesize[2]; ++ uint32_t fs_qbmask[2]; ++ uint32_t fs_qfmask[2]; ++ int32_t fs_state; ++ } PACKED fs_44; ++ } fs_u2; ++ int32_t fs_postblformat; ++ int32_t fs_nrpos; ++ int32_t fs_postbloff; ++ int32_t fs_rotbloff; ++ uint32_t fs_magic; ++ uint8_t fs_space[1]; ++} PACKED; ++ ++#define UFS_MAGIC 0x00011954 ++#define UFS2_MAGIC 0x19540119 ++#define UFS_MAGIC_FEA 0x00195612 ++#define UFS_MAGIC_LFN 0x00095014 ++ ++int volume_id_probe_ufs(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ uint32_t magic; ++ int i; ++ struct ufs_super_block *ufs; ++ int offsets[] = {0, 8, 64, 256, -1}; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ for (i = 0; offsets[i] >= 0; i++) { ++ ufs = (struct ufs_super_block *) volume_id_get_buffer(id, off + (offsets[i] * 0x400), 0x800); ++ if (ufs == NULL) ++ return -1; ++ ++ dbg("offset 0x%x", offsets[i] * 0x400); ++ magic = be32_to_cpu(ufs->fs_magic); ++ if ((magic == UFS_MAGIC) || ++ (magic == UFS2_MAGIC) || ++ (magic == UFS_MAGIC_FEA) || ++ (magic == UFS_MAGIC_LFN)) { ++ dbg("magic 0x%08x(be)", magic); ++ goto found; ++ } ++ magic = le32_to_cpu(ufs->fs_magic); ++ if ((magic == UFS_MAGIC) || ++ (magic == UFS2_MAGIC) || ++ (magic == UFS_MAGIC_FEA) || ++ (magic == UFS_MAGIC_LFN)) { ++ dbg("magic 0x%08x(le)", magic); ++ goto found; ++ } ++ } ++ return -1; ++ ++found: ++ volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); ++ id->type = "ufs"; ++ switch (magic) { ++ case UFS_MAGIC: ++ strcpy(id->type_version, "1"); ++ break; ++ case UFS2_MAGIC: ++ strcpy(id->type_version, "2"); ++ volume_id_set_label_raw(id, ufs->fs_u11.fs_u2.fs_volname, 32); ++ volume_id_set_label_string(id, ufs->fs_u11.fs_u2.fs_volname, 32); ++ break; ++ default: ++ break; ++ } ++ ++ return 0; ++} + +=== added file 'libvolume_id/util.c' +--- grub-0.97.orig/libvolume_id/util.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/util.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,472 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2005-2007 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include <stdlib.h> ++ ++#include "strfuncs.h" ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++static char hex[] = "0123456789abcdef"; ++ ++#define hexhi(val) hex[val >> 4] ++#define hexlo(val) hex[val & 0xf] ++ ++/* count of characters used to encode one unicode char */ ++static int utf8_encoded_expected_len(const char *str) ++{ ++ unsigned char c = (unsigned char)str[0]; ++ ++ if (c < 0x80) ++ return 1; ++ if ((c & 0xe0) == 0xc0) ++ return 2; ++ if ((c & 0xf0) == 0xe0) ++ return 3; ++ if ((c & 0xf8) == 0xf0) ++ return 4; ++ if ((c & 0xfc) == 0xf8) ++ return 5; ++ if ((c & 0xfe) == 0xfc) ++ return 6; ++ return 0; ++} ++ ++/* decode one unicode char */ ++static int utf8_encoded_to_unichar(const char *str) ++{ ++ int unichar; ++ int len; ++ int i; ++ ++ len = utf8_encoded_expected_len(str); ++ switch (len) { ++ case 1: ++ return (int)str[0]; ++ case 2: ++ unichar = str[0] & 0x1f; ++ break; ++ case 3: ++ unichar = (int)str[0] & 0x0f; ++ break; ++ case 4: ++ unichar = (int)str[0] & 0x07; ++ break; ++ case 5: ++ unichar = (int)str[0] & 0x03; ++ break; ++ case 6: ++ unichar = (int)str[0] & 0x01; ++ break; ++ default: ++ return -1; ++ } ++ ++ for (i = 1; i < len; i++) { ++ if (((int)str[i] & 0xc0) != 0x80) ++ return -1; ++ unichar <<= 6; ++ unichar |= (int)str[i] & 0x3f; ++ } ++ ++ return unichar; ++} ++ ++/* expected size used to encode one unicode char */ ++static int utf8_unichar_to_encoded_len(int unichar) ++{ ++ if (unichar < 0x80) ++ return 1; ++ if (unichar < 0x800) ++ return 2; ++ if (unichar < 0x10000) ++ return 3; ++ if (unichar < 0x200000) ++ return 4; ++ if (unichar < 0x4000000) ++ return 5; ++ return 6; ++} ++ ++/* check if unicode char has a valid numeric range */ ++static int utf8_unichar_valid_range(int unichar) ++{ ++ if (unichar > 0x10ffff) ++ return 0; ++ if ((unichar & 0xfffff800) == 0xd800) ++ return 0; ++ if ((unichar > 0xfdcf) && (unichar < 0xfdf0)) ++ return 0; ++ if ((unichar & 0xffff) == 0xffff) ++ return 0; ++ return 1; ++} ++ ++/* validate one encoded unicode char and return its length */ ++int volume_id_utf8_encoded_valid_unichar(const char *str) ++{ ++ int len; ++ int unichar; ++ int i; ++ ++ len = utf8_encoded_expected_len(str); ++ if (len == 0) ++ return -1; ++ ++ /* ascii is valid */ ++ if (len == 1) ++ return 1; ++ ++ /* check if expected encoded chars are available */ ++ for (i = 0; i < len; i++) ++ if ((str[i] & 0x80) != 0x80) ++ return -1; ++ ++ unichar = utf8_encoded_to_unichar(str); ++ ++ /* check if encoded length matches encoded value */ ++ if (utf8_unichar_to_encoded_len(unichar) != len) ++ return -1; ++ ++ /* check if value has valid range */ ++ if (!utf8_unichar_valid_range(unichar)) ++ return -1; ++ ++ return len; ++} ++ ++size_t volume_id_set_unicode16(uint8_t *str, size_t len, const uint8_t *buf, enum endian endianess, size_t count) ++{ ++ size_t i, j; ++ uint16_t c; ++ ++ j = 0; ++ for (i = 0; i + 2 <= count; i += 2) { ++ if (endianess == LE) ++ c = (buf[i+1] << 8) | buf[i]; ++ else ++ c = (buf[i] << 8) | buf[i+1]; ++ if (c == 0) { ++ str[j] = '\0'; ++ break; ++ } else if (c < 0x80) { ++ if (j+1 >= len) ++ break; ++ str[j++] = (uint8_t) c; ++ } else if (c < 0x800) { ++ if (j+2 >= len) ++ break; ++ str[j++] = (uint8_t) (0xc0 | (c >> 6)); ++ str[j++] = (uint8_t) (0x80 | (c & 0x3f)); ++ } else { ++ if (j+3 >= len) ++ break; ++ str[j++] = (uint8_t) (0xe0 | (c >> 12)); ++ str[j++] = (uint8_t) (0x80 | ((c >> 6) & 0x3f)); ++ str[j++] = (uint8_t) (0x80 | (c & 0x3f)); ++ } ++ } ++ str[j] = '\0'; ++ return j; ++} ++ ++static char *usage_to_string(enum volume_id_usage usage_id) ++{ ++ switch (usage_id) { ++ case VOLUME_ID_FILESYSTEM: ++ return "filesystem"; ++ case VOLUME_ID_OTHER: ++ return "other"; ++ case VOLUME_ID_RAID: ++ return "raid"; ++ case VOLUME_ID_DISKLABEL: ++ return "disklabel"; ++ case VOLUME_ID_CRYPTO: ++ return "crypto"; ++ case VOLUME_ID_UNPROBED: ++ return "unprobed"; ++ case VOLUME_ID_UNUSED: ++ return "unused"; ++ } ++ return NULL; ++} ++ ++void volume_id_set_usage(struct volume_id *id, enum volume_id_usage usage_id) ++{ ++ id->usage_id = usage_id; ++ id->usage = usage_to_string(usage_id); ++} ++ ++void volume_id_set_label_raw(struct volume_id *id, const uint8_t *buf, size_t count) ++{ ++ if (count > sizeof(id->label)) ++ count = sizeof(id->label); ++ ++ memcpy(id->label_raw, buf, count); ++ id->label_raw_len = count; ++} ++ ++void volume_id_set_label_string(struct volume_id *id, const uint8_t *buf, size_t count) ++{ ++ size_t i; ++ ++ if (count >= sizeof(id->label)) ++ count = sizeof(id->label)-1; ++ ++ memcpy(id->label, buf, count); ++ id->label[count] = '\0'; ++ ++ /* remove trailing whitespace */ ++ i = strnlen(id->label, count); ++ while (i--) { ++ if (!isspace(id->label[i])) ++ break; ++ } ++ id->label[i+1] = '\0'; ++} ++ ++void volume_id_set_label_unicode16(struct volume_id *id, const uint8_t *buf, enum endian endianess, size_t count) ++{ ++ if (count >= sizeof(id->label)) ++ count = sizeof(id->label)-1; ++ ++ volume_id_set_unicode16((uint8_t *)id->label, sizeof(id->label), buf, endianess, count); ++} ++ ++void volume_id_set_uuid(struct volume_id *id, const uint8_t *buf, size_t len, enum uuid_format format) ++{ ++ unsigned int i; ++ unsigned int count = 0; ++ char *uuid; ++ ++ if (len > sizeof(id->uuid_raw)) ++ len = sizeof(id->uuid_raw); ++ ++ switch(format) { ++ case UUID_STRING: ++ count = len; ++ break; ++ case UUID_HEX_STRING: ++ count = len; ++ break; ++ case UUID_DOS: ++ count = 4; ++ break; ++ case UUID_64BIT_LE: ++ case UUID_64BIT_BE: ++ count = 8; ++ break; ++ case UUID_DCE: ++ count = 16; ++ break; ++ case UUID_FOURINT: ++ count = 35; ++ break; ++ } ++ memcpy(id->uuid_raw, buf, count); ++ id->uuid_raw_len = count; ++ ++ /* if set, create string in the same format, the native platform uses */ ++ for (i = 0; i < count; i++) ++ if (buf[i] != 0) ++ goto set; ++ return; ++ ++set: ++ uuid = id->uuid; ++ switch(format) { ++ case UUID_DOS: ++ *uuid++ = hexhi(buf[3]); ++ *uuid++ = hexlo(buf[3]); ++ *uuid++ = hexhi(buf[2]); ++ *uuid++ = hexlo(buf[2]); ++ *uuid++ = '-'; ++ *uuid++ = hexhi(buf[1]); ++ *uuid++ = hexlo(buf[1]); ++ *uuid++ = hexhi(buf[0]); ++ *uuid++ = hexlo(buf[0]); ++ *uuid = '\0'; ++ break; ++ case UUID_64BIT_LE: ++ *uuid++ = hexhi(buf[7]); ++ *uuid++ = hexlo(buf[7]); ++ *uuid++ = hexhi(buf[6]); ++ *uuid++ = hexlo(buf[6]); ++ *uuid++ = hexhi(buf[5]); ++ *uuid++ = hexlo(buf[5]); ++ *uuid++ = hexhi(buf[4]); ++ *uuid++ = hexlo(buf[4]); ++ *uuid++ = hexhi(buf[3]); ++ *uuid++ = hexlo(buf[3]); ++ *uuid++ = hexhi(buf[2]); ++ *uuid++ = hexlo(buf[2]); ++ *uuid++ = hexhi(buf[1]); ++ *uuid++ = hexlo(buf[1]); ++ *uuid++ = hexhi(buf[0]); ++ *uuid++ = hexlo(buf[0]); ++ *uuid = '\0'; ++ break; ++ case UUID_64BIT_BE: ++ *uuid++ = hexhi(buf[0]); ++ *uuid++ = hexlo(buf[0]); ++ *uuid++ = hexhi(buf[1]); ++ *uuid++ = hexlo(buf[1]); ++ *uuid++ = hexhi(buf[2]); ++ *uuid++ = hexlo(buf[2]); ++ *uuid++ = hexhi(buf[3]); ++ *uuid++ = hexlo(buf[3]); ++ *uuid++ = hexhi(buf[4]); ++ *uuid++ = hexlo(buf[4]); ++ *uuid++ = hexhi(buf[5]); ++ *uuid++ = hexlo(buf[5]); ++ *uuid++ = hexhi(buf[6]); ++ *uuid++ = hexlo(buf[6]); ++ *uuid++ = hexhi(buf[7]); ++ *uuid++ = hexlo(buf[7]); ++ *uuid = '\0'; ++ break; ++ case UUID_DCE: ++ *uuid++ = hexhi(buf[0]); ++ *uuid++ = hexlo(buf[0]); ++ *uuid++ = hexhi(buf[1]); ++ *uuid++ = hexlo(buf[1]); ++ *uuid++ = hexhi(buf[2]); ++ *uuid++ = hexlo(buf[2]); ++ *uuid++ = hexhi(buf[3]); ++ *uuid++ = hexlo(buf[3]); ++ *uuid++ = '-'; ++ *uuid++ = hexhi(buf[4]); ++ *uuid++ = hexlo(buf[4]); ++ *uuid++ = hexhi(buf[5]); ++ *uuid++ = hexlo(buf[5]); ++ *uuid++ = '-'; ++ *uuid++ = hexhi(buf[6]); ++ *uuid++ = hexlo(buf[6]); ++ *uuid++ = hexhi(buf[7]); ++ *uuid++ = hexlo(buf[7]); ++ *uuid++ = '-'; ++ *uuid++ = hexhi(buf[8]); ++ *uuid++ = hexlo(buf[8]); ++ *uuid++ = hexhi(buf[9]); ++ *uuid++ = hexlo(buf[9]); ++ *uuid++ = '-'; ++ *uuid++ = hexhi(buf[10]); ++ *uuid++ = hexlo(buf[10]); ++ *uuid++ = hexhi(buf[11]); ++ *uuid++ = hexlo(buf[11]); ++ *uuid++ = hexhi(buf[12]); ++ *uuid++ = hexlo(buf[12]); ++ *uuid++ = hexhi(buf[13]); ++ *uuid++ = hexlo(buf[13]); ++ *uuid++ = hexhi(buf[14]); ++ *uuid++ = hexlo(buf[14]); ++ *uuid++ = hexhi(buf[15]); ++ *uuid++ = hexlo(buf[15]); ++ *uuid = '\0'; ++ break; ++ case UUID_HEX_STRING: ++ /* translate A..F to a..f */ ++ memcpy(id->uuid, buf, count); ++ for (i = 0; i < count; i++) ++ if (id->uuid[i] >= 'A' && id->uuid[i] <= 'F') ++ id->uuid[i] = (id->uuid[i] - 'A') + 'a'; ++ id->uuid[count] = '\0'; ++ break; ++ case UUID_STRING: ++ memcpy(id->uuid, buf, count); ++ id->uuid[count] = '\0'; ++ break; ++ case UUID_FOURINT: ++ *uuid++ = hexhi(buf[0]); ++ *uuid++ = hexlo(buf[0]); ++ *uuid++ = hexhi(buf[1]); ++ *uuid++ = hexlo(buf[1]); ++ *uuid++ = hexhi(buf[2]); ++ *uuid++ = hexlo(buf[2]); ++ *uuid++ = hexhi(buf[3]); ++ *uuid++ = hexlo(buf[3]); ++ *uuid++ = ':'; ++ *uuid++ = hexhi(buf[4]); ++ *uuid++ = hexlo(buf[4]); ++ *uuid++ = hexhi(buf[5]); ++ *uuid++ = hexlo(buf[5]); ++ *uuid++ = hexhi(buf[6]); ++ *uuid++ = hexlo(buf[6]); ++ *uuid++ = hexhi(buf[7]); ++ *uuid++ = hexlo(buf[7]); ++ *uuid++ = ':'; ++ *uuid++ = hexhi(buf[8]); ++ *uuid++ = hexlo(buf[8]); ++ *uuid++ = hexhi(buf[9]); ++ *uuid++ = hexlo(buf[9]); ++ *uuid++ = hexhi(buf[10]); ++ *uuid++ = hexlo(buf[10]); ++ *uuid++ = hexhi(buf[11]); ++ *uuid++ = hexlo(buf[11]); ++ *uuid++ = ':'; ++ *uuid++ = hexhi(buf[12]); ++ *uuid++ = hexlo(buf[12]); ++ *uuid++ = hexhi(buf[13]); ++ *uuid++ = hexlo(buf[13]); ++ *uuid++ = hexhi(buf[14]); ++ *uuid++ = hexlo(buf[14]); ++ *uuid++ = hexhi(buf[15]); ++ *uuid++ = hexlo(buf[15]); ++ *uuid = '\0'; ++ break; ++ default: ++ *uuid = '\0'; ++ break; ++ } ++} ++ ++uint8_t *volume_id_get_buffer(struct volume_id *id, uint64_t off, size_t len) ++{ ++ info("get buffer off 0x%llx(%llu), len 0x%zx", (unsigned long long) off, (unsigned long long) off, len); ++ /* check if requested area fits in superblock buffer */ ++ if (off + len <= SB_BUFFER_SIZE) { ++ /* check if we need to read */ ++ if ((off + len) > id->sbbuf_len) { ++ if (devread (0, 0, off + len, (char*)id->sbbuf) == 0) ++ { ++ return NULL; ++ } ++ id->sbbuf_len = off + len; ++ } ++ return &(id->sbbuf[off]); ++ } else { ++ if (len > SEEK_BUFFER_SIZE) { ++ dbg("seek buffer too small %d", SEEK_BUFFER_SIZE); ++ return NULL; ++ } ++ ++ /* check if we need to read */ ++ if ((off < id->seekbuf_off) || ((off + len) > (id->seekbuf_off + id->seekbuf_len))) { ++ info("read seekbuf off:0x%llx len:0x%zx", (unsigned long long) off, len); ++ if (devread(off >> 9, off & 0x1ff, len, (char*)id->seekbuf) == 0) ++ { ++ return NULL; ++ } ++ id->seekbuf_off = off; ++ id->seekbuf_len = len; ++ } ++ return &(id->seekbuf[off - id->seekbuf_off]); ++ } ++} + +=== added file 'libvolume_id/util.h' +--- grub-0.97.orig/libvolume_id/util.h 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/util.h 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,98 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2005-2006 Kay Sievers <kay.sievers@vrfy.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _VOLUME_ID_UTIL_ ++#define _VOLUME_ID_UTIL_ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include <endian.h> ++#include <byteswap.h> ++#include <syslog.h> ++ ++#define ALLOWED_CHARS "#+-.:=@_" ++ ++#ifndef PACKED ++#define PACKED __attribute__((packed)) ++#endif ++ ++#define err(format, arg...) volume_id_log_fn(LOG_ERR, __FILE__, __LINE__, format, ##arg) ++#ifdef INFO ++#define info(format, arg...) volume_id_log_fn(LOG_INFO, __FILE__, __LINE__, format, ##arg) ++#else ++#define info(format, arg...) do { } while (0) ++#endif ++ ++#ifdef DEBUG ++#define dbg(format, arg...) volume_id_log_fn(LOG_DEBUG, __FILE__, __LINE__, format, ##arg) ++#else ++#define dbg(format, arg...) do { } while (0) ++#endif ++ ++/* size of superblock buffer, reiserfs block is at 64k */ ++#define SB_BUFFER_SIZE 0x11000 ++/* size of seek buffer, FAT cluster is 32k max */ ++#define SEEK_BUFFER_SIZE 0x10000 ++ ++#ifdef __BYTE_ORDER ++#if (__BYTE_ORDER == __LITTLE_ENDIAN) ++#define le16_to_cpu(x) (x) ++#define le32_to_cpu(x) (x) ++#define le64_to_cpu(x) (x) ++#define be16_to_cpu(x) bswap_16(x) ++#define be32_to_cpu(x) bswap_32(x) ++#define cpu_to_le16(x) (x) ++#define cpu_to_le32(x) (x) ++#define cpu_to_be32(x) bswap_32(x) ++#elif (__BYTE_ORDER == __BIG_ENDIAN) ++#define le16_to_cpu(x) bswap_16(x) ++#define le32_to_cpu(x) bswap_32(x) ++#define le64_to_cpu(x) bswap_64(x) ++#define be16_to_cpu(x) (x) ++#define be32_to_cpu(x) (x) ++#define cpu_to_le16(x) bswap_16(x) ++#define cpu_to_le32(x) bswap_32(x) ++#define cpu_to_be32(x) (x) ++#endif ++#endif /* __BYTE_ORDER */ ++ ++enum uuid_format { ++ UUID_STRING, ++ UUID_HEX_STRING, ++ UUID_DCE, ++ UUID_DOS, ++ UUID_64BIT_LE, ++ UUID_64BIT_BE, ++ UUID_FOURINT, ++}; ++ ++enum endian { ++ LE = 0, ++ BE = 1 ++}; ++ ++extern int volume_id_utf8_encoded_valid_unichar(const char *str); ++extern size_t volume_id_set_unicode16(uint8_t *str, size_t len, const uint8_t *buf, enum endian endianess, size_t count); ++extern void volume_id_set_usage(struct volume_id *id, enum volume_id_usage usage_id); ++extern void volume_id_set_label_raw(struct volume_id *id, const uint8_t *buf, size_t count); ++extern void volume_id_set_label_string(struct volume_id *id, const uint8_t *buf, size_t count); ++extern void volume_id_set_label_unicode16(struct volume_id *id, const uint8_t *buf, enum endian endianess, size_t count); ++extern void volume_id_set_uuid(struct volume_id *id, const uint8_t *buf, size_t len, enum uuid_format format); ++extern uint8_t *volume_id_get_buffer(struct volume_id *id, uint64_t off, size_t len); ++extern void volume_id_free_buffer(struct volume_id *id); ++ ++#endif /* _VOLUME_ID_UTIL_ */ ++ + +=== added file 'libvolume_id/via_raid.c' +--- grub-0.97.orig/libvolume_id/via_raid.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/via_raid.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,88 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * Based on information taken from dmraid: ++ * Copyright (C) 2004-2006 Heinz Mauelshagen, Red Hat GmbH ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++struct via_meta { ++ uint16_t signature; ++ uint8_t version_number; ++ struct via_array { ++ uint16_t disk_bit_mask; ++ uint8_t disk_array_ex; ++ uint32_t capacity_low; ++ uint32_t capacity_high; ++ uint32_t serial_checksum; ++ } PACKED array; ++ uint32_t serial_checksum[8]; ++ uint8_t checksum; ++} PACKED; ++ ++#define VIA_SIGNATURE 0xAA55 ++ ++/* 8 bit checksum on first 50 bytes of metadata. */ ++static uint8_t meta_checksum(struct via_meta *via) ++{ ++ uint8_t i = 50, sum = 0; ++ ++ while (i--) ++ sum += ((uint8_t*) via)[i]; ++ ++ return sum == via->checksum; ++} ++ ++ ++int volume_id_probe_via_raid(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ const uint8_t *buf; ++ uint64_t meta_off; ++ struct via_meta *via; ++ ++ dbg("probing at offset 0x%llx, size 0x%llx", ++ (unsigned long long) off, (unsigned long long) size); ++ ++ if (size < 0x10000) ++ return -1; ++ ++ meta_off = ((size / 0x200)-1) * 0x200; ++ ++ buf = volume_id_get_buffer(id, off + meta_off, 0x200); ++ if (buf == NULL) ++ return -1; ++ ++ via = (struct via_meta *) buf; ++ if (le16_to_cpu(via->signature) != VIA_SIGNATURE) ++ return -1; ++ ++ if (via->version_number > 1) ++ return -1; ++ ++ if (!meta_checksum(via)) ++ return -1; ++ ++ volume_id_set_usage(id, VOLUME_ID_RAID); ++ sprintf(id->type_version, "%u", via->version_number); ++ id->type = "via_raid_member"; ++ ++ return 0; ++} + +=== added file 'libvolume_id/volume_id.c' +--- grub-0.97.orig/libvolume_id/volume_id.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/volume_id.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,222 @@ ++/* ++ * volume_id - reads volume label and uuid ++ * ++ * Copyright (C) 2005-2007 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include <fcntl.h> ++#include <sys/stat.h> ++ ++#include "volume_id.h" ++#include "util.h" ++#include "strfuncs.h" ++#include "shared.h" ++ ++#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) ++ ++struct prober { ++ volume_id_probe_fn_t prober; ++ const char *name[4]; ++}; ++ ++#define NOT_SUPPORTED(x) ++#define SUPPORTED(x) x ++ ++static const struct prober prober_raid[] = { ++ { volume_id_probe_ddf_raid, { "ddf_raid", } }, ++ ++ /* { volume_id_probe_linux_raid, { "linux_raid", } }, */ ++ /* { volume_id_probe_intel_software_raid, { "isw_raid", } }, */ ++ /* { volume_id_probe_lsi_mega_raid, { "lsi_mega_raid", } }, */ ++ /* { volume_id_probe_via_raid, { "via_raid", } }, */ ++ /* { volume_id_probe_silicon_medley_raid, { "silicon_medley_raid", } }, */ ++ /* { volume_id_probe_nvidia_raid, { "nvidia_raid", } }, */ ++ /* { volume_id_probe_promise_fasttrack_raid, { "promise_fasttrack_raid", } }, */ ++ /* { volume_id_probe_highpoint_45x_raid, { "highpoint_raid", } }, */ ++ /* { volume_id_probe_adaptec_raid, { "adaptec_raid", } }, */ ++ /* { volume_id_probe_jmicron_raid, { "jmicron_raid", } }, */ ++ /* { volume_id_probe_lvm1, { "lvm1", } }, */ ++ /* { volume_id_probe_lvm2, { "lvm2", } }, */ ++ /* { volume_id_probe_highpoint_37x_raid, { "highpoint_raid", } }, */ ++}; ++ ++static const struct prober prober_filesystem[] = { ++ { volume_id_probe_vfat, { "vfat", } }, ++ { volume_id_probe_luks, { "luks", } }, ++ { volume_id_probe_xfs, { "xfs", } }, ++ { volume_id_probe_ext, { "ext2", "ext3", "jbd", } }, ++ { volume_id_probe_reiserfs, { "reiserfs", "reiser4", } }, ++ { volume_id_probe_jfs, { "jfs", } }, ++ { volume_id_probe_hfs_hfsplus, { "hfs", "hfsplus", } }, ++ { volume_id_probe_ntfs, { "ntfs", } }, ++ { volume_id_probe_ocfs1, { "ocfs1", } }, ++ { volume_id_probe_ocfs2, { "ocfs2", } }, ++ ++ /* { volume_id_probe_linux_swap, { "swap", } }, */ ++ /* { volume_id_probe_udf, { "udf", } }, */ ++ /* { volume_id_probe_iso9660, { "iso9660", } }, */ ++ /* { volume_id_probe_ufs, { "ufs", } }, */ ++ /* { volume_id_probe_cramfs, { "cramfs", } }, */ ++ /* { volume_id_probe_romfs, { "romfs", } }, */ ++ /* { volume_id_probe_hpfs, { "hpfs", } }, */ ++ /* { volume_id_probe_sysv, { "sysv", "xenix", } }, */ ++ /* { volume_id_probe_minix, { "minix", } }, */ ++ /* { volume_id_probe_vxfs, { "vxfs", } }, */ ++ /* { volume_id_probe_squashfs, { "squashfs", } }, */ ++ /* { volume_id_probe_netware, { "netware", } }, */ ++}; ++ ++/* the user can overwrite this log function */ ++static void default_log(int priority, const char *file, int line, const char *format, ...) ++{ ++ return; ++} ++ ++volume_id_log_fn_t volume_id_log_fn = default_log; ++ ++/** ++ * volume_id_get_type: ++ * @id: Probing context ++ * @type: Type string. Must not be freed by the caller. ++ * ++ * Get the type string after a successful probe. ++ * ++ * Returns: 1 if the value was set, 0 otherwise. ++ **/ ++int volume_id_get_type(struct volume_id *id, const char **type) ++{ ++ if (id == NULL) ++ return 0; ++ if (type == NULL) ++ return 0; ++ if (id->usage_id == VOLUME_ID_UNUSED) ++ return 0; ++ ++ *type = id->type; ++ return 1; ++} ++ ++ ++/** ++ * volume_id_get_uuid: ++ * @id: Probing context. ++ * @uuid: UUID string. Must not be freed by the caller. ++ * ++ * Get the raw UUID string after a successful probe. ++ * ++ * Returns: 1 if the value was set, 0 otherwise. ++ **/ ++int volume_id_get_uuid(struct volume_id *id, const char **uuid) ++{ ++ if (id == NULL) ++ return 0; ++ if (uuid == NULL) ++ return 0; ++ if (id->usage_id == VOLUME_ID_UNUSED) ++ return 0; ++ ++ *uuid = id->uuid; ++ return 1; ++} ++ ++/** ++ * volume_id_probe_raid: ++ * @id: Probing context. ++ * @off: Probing offset relative to the start of the device. ++ * @size: Total size of the device. ++ * ++ * Probe device for all known raid signatures. ++ * ++ * Returns: 0 on successful probe, otherwise negative value. ++ **/ ++int volume_id_probe_raid(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ unsigned int i; ++ ++ if (id == NULL) ++ return -1; ++ ++ info("probing at offset 0x%llx, size 0x%llx", ++ (unsigned long long) off, (unsigned long long) size); ++ ++ for (i = 0; i < ARRAY_SIZE(prober_raid); i++) ++ if (prober_raid[i].prober(id, off, size) == 0) ++ goto found; ++ return -1; ++ ++found: ++ return 0; ++} ++ ++/** ++ * volume_id_probe_filesystem: ++ * @id: Probing context. ++ * @off: Probing offset relative to the start of the device. ++ * @size: Total size of the device. ++ * ++ * Probe device for all known filesystem signatures. ++ * ++ * Returns: 0 on successful probe, otherwise negative value. ++ **/ ++int volume_id_probe_filesystem(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ unsigned int i; ++ ++ if (id == NULL) ++ return -1; ++ ++ info("probing at offset 0x%llx, size 0x%llx", ++ (unsigned long long) off, (unsigned long long) size); ++ ++ for (i = 0; i < ARRAY_SIZE(prober_filesystem); i++) ++ if (prober_filesystem[i].prober(id, off, size) == 0) ++ goto found; ++ return -1; ++ ++found: ++ return 0; ++} ++ ++/** ++ * volume_id_probe_raid: ++ * @all_probers_fn: prober function to called for all known probing routines. ++ * @id: Context passed to prober function. ++ * @off: Offset value passed to prober function. ++ * @size: Size value passed to prober function. ++ * @data: Arbitrary data passed to the prober function. ++ * ++ * Run a custom function for all known probing routines. ++ **/ ++void volume_id_all_probers(all_probers_fn_t all_probers_fn, ++ struct volume_id *id, uint64_t off, uint64_t size, ++ void *data) ++{ ++ unsigned int i; ++ ++ if (all_probers_fn == NULL) ++ return; ++ ++ for (i = 0; i < ARRAY_SIZE(prober_raid); i++) { ++ if (all_probers_fn(prober_raid[i].prober, id, off, size, data) != 0) ++ goto out; ++ } ++ for (i = 0; i < ARRAY_SIZE(prober_filesystem); i++) { ++ if (all_probers_fn(prober_filesystem[i].prober, id, off, size, data) != 0) ++ goto out; ++ } ++out: ++ return; ++} + +=== added file 'libvolume_id/volume_id.h' +--- grub-0.97.orig/libvolume_id/volume_id.h 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/volume_id.h 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,137 @@ ++/* ++ * volume_id - reads volume label and uuid ++ * ++ * Copyright (C) 2005-2007 Kay Sievers <kay.sievers@vrfy.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _LIBVOLUME_ID_H_ ++#define _LIBVOLUME_ID_H_ ++ ++#include <stdint.h> ++#include <stddef.h> ++ ++typedef void (*volume_id_log_fn_t)(int priority, const char *file, int line, const char *format, ...) ; ++ ++extern volume_id_log_fn_t volume_id_log_fn; ++ ++struct volume_id; ++typedef int (*volume_id_probe_fn_t)(struct volume_id *id, uint64_t off, uint64_t size); ++typedef int (*all_probers_fn_t)(volume_id_probe_fn_t probe_fn, ++ struct volume_id *id, uint64_t off, uint64_t size, ++ void *data); ++ ++extern struct volume_id *volume_id_open_fd(int fd); ++extern void volume_id_close(struct volume_id *id); ++extern int volume_id_probe_filesystem(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_raid(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_all(struct volume_id *id, uint64_t off, uint64_t size); ++extern const volume_id_probe_fn_t *volume_id_get_prober_by_type(const char *type); ++extern void volume_id_all_probers(all_probers_fn_t all_probers_fn, ++ struct volume_id *id, uint64_t off, uint64_t size, ++ void *data); ++extern int volume_id_get_label(struct volume_id *id, const char **label); ++extern int volume_id_get_label_raw(struct volume_id *id, const uint8_t **label, size_t *len); ++extern int volume_id_get_uuid(struct volume_id *id, const char **uuid); ++extern int volume_id_get_uuid_raw(struct volume_id *id, const uint8_t **uuid, size_t *len); ++extern int volume_id_get_usage(struct volume_id *id, const char **usage); ++extern int volume_id_get_type(struct volume_id *id, const char **type); ++extern int volume_id_get_type_version(struct volume_id *id, const char **type_version); ++extern int volume_id_encode_string(const char *str, char *str_enc, size_t len); ++ ++/* ++ * Note: everything below will be made private or removed from ++ * a future version, and a new major release of libvolume_id ++ */ ++ ++extern struct volume_id *volume_id_open_node(const char *path); ++ ++#define VOLUME_ID_LABEL_SIZE 64 ++#define VOLUME_ID_UUID_SIZE 36 ++#define VOLUME_ID_FORMAT_SIZE 32 ++#define VOLUME_ID_PATH_MAX 256 ++#define VOLUME_ID_PARTITIONS_MAX 256 ++ ++enum volume_id_usage { ++ VOLUME_ID_UNUSED, ++ VOLUME_ID_UNPROBED, ++ VOLUME_ID_OTHER, ++ VOLUME_ID_FILESYSTEM, ++ VOLUME_ID_RAID, ++ VOLUME_ID_DISKLABEL, ++ VOLUME_ID_CRYPTO, ++}; ++ ++#include <util.h> ++ ++struct volume_id { ++ uint8_t label_raw[VOLUME_ID_LABEL_SIZE]; ++ size_t label_raw_len; ++ char label[VOLUME_ID_LABEL_SIZE+1]; ++ uint8_t uuid_raw[VOLUME_ID_UUID_SIZE]; ++ size_t uuid_raw_len; ++ char uuid[VOLUME_ID_UUID_SIZE+1]; ++ enum volume_id_usage usage_id; ++ char *usage; ++ char *type; ++ char type_version[VOLUME_ID_FORMAT_SIZE]; ++ ++ int fd; ++ uint8_t sbbuf[SB_BUFFER_SIZE]; ++ size_t sbbuf_len; ++ uint8_t seekbuf[SEEK_BUFFER_SIZE]; ++ uint64_t seekbuf_off; ++ size_t seekbuf_len; ++ int fd_close:1; ++}; ++ ++/* filesystems */ ++extern int volume_id_probe_cramfs(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_ext(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_vfat(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_hfs_hfsplus(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_hpfs(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_iso9660(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_jfs(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_minix(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_ntfs(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_ocfs1(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_ocfs2(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_reiserfs(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_romfs(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_sysv(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_udf(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_ufs(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_vxfs(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_xfs(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_squashfs(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_netware(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_gfs(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_gfs2(struct volume_id *id, uint64_t off, uint64_t size); ++ ++/* special formats */ ++extern int volume_id_probe_linux_swap(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_luks(struct volume_id *id, uint64_t off, uint64_t size); ++ ++/* raid */ ++extern int volume_id_probe_linux_raid(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_lvm1(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_lvm2(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_ddf_raid(struct volume_id *id, uint64_t off, uint64_t size); ++ ++/* bios raid */ ++extern int volume_id_probe_intel_software_raid(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_highpoint_37x_raid(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_highpoint_45x_raid(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_lsi_mega_raid(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_nvidia_raid(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_promise_fasttrack_raid(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_silicon_medley_raid(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_via_raid(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_adaptec_raid(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_jmicron_raid(struct volume_id *id, uint64_t off, uint64_t size); ++ ++#endif + +=== added file 'libvolume_id/vxfs.c' +--- grub-0.97.orig/libvolume_id/vxfs.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/vxfs.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,49 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++#define VXFS_SUPER_MAGIC 0xa501FCF5 ++ ++struct vxfs_super { ++ uint32_t vs_magic; ++ int32_t vs_version; ++} PACKED; ++ ++int volume_id_probe_vxfs(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ struct vxfs_super *vxs; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ vxs = (struct vxfs_super *) volume_id_get_buffer(id, off + 0x200, 0x200); ++ if (vxs == NULL) ++ return -1; ++ ++ if (vxs->vs_magic == cpu_to_le32(VXFS_SUPER_MAGIC)) { ++ sprintf(id->type_version, "%u", (unsigned int) vxs->vs_version); ++ volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); ++ id->type = "vxfs"; ++ return 0; ++ } ++ ++ return -1; ++} + +=== added file 'libvolume_id/xfs.c' +--- grub-0.97.orig/libvolume_id/xfs.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/xfs.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,59 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++struct xfs_super_block { ++ uint8_t magic[4]; ++ uint32_t blocksize; ++ uint64_t dblocks; ++ uint64_t rblocks; ++ uint32_t dummy1[2]; ++ uint8_t uuid[16]; ++ uint32_t dummy2[15]; ++ uint8_t fname[12]; ++ uint32_t dummy3[2]; ++ uint64_t icount; ++ uint64_t ifree; ++ uint64_t fdblocks; ++} PACKED; ++ ++int volume_id_probe_xfs(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ struct xfs_super_block *xs; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ xs = (struct xfs_super_block *) volume_id_get_buffer(id, off, 0x200); ++ if (xs == NULL) ++ return -1; ++ ++ if (memcmp((char *)xs->magic, "XFSB", 4) != 0) ++ return -1; ++ ++ volume_id_set_label_raw(id, xs->fname, 12); ++ volume_id_set_label_string(id, xs->fname, 12); ++ volume_id_set_uuid(id, xs->uuid, 0, UUID_DCE); ++ ++ volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); ++ id->type = "xfs"; ++ ++ return 0; ++} + +=== modified file 'stage2/Makefile.am' +--- grub-0.97.orig/stage2/Makefile.am 2005-02-02 20:40:05 +0000 ++++ grub-0.97/stage2/Makefile.am 2008-07-09 17:23:44 +0000 +@@ -13,6 +13,10 @@ + # For <stage1.h>. + INCLUDES = -I$(top_srcdir)/stage1 + ++if UUID_SUPPORT ++INCLUDES += -I$(top_srcdir)/libvolume_id ++endif ++ + # The library for /sbin/grub. + noinst_LIBRARIES = libgrub.a + libgrub_a_SOURCES = boot.c builtins.c char_io.c cmdline.c common.c \ +@@ -61,6 +65,12 @@ + PXELOADER_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,7C00 + START_ELTORITO_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,7C00 + ++if UUID_SUPPORT ++UUID_FLAGS = -DSUPPORT_UUID=1 ++else ++UUID_FLAGS = ++endif ++ + if NETBOOT_SUPPORT + NETBOOT_FLAGS = -I$(top_srcdir)/netboot -DSUPPORT_NETBOOT=1 + else +@@ -82,6 +92,8 @@ + STAGE2_COMPILE = $(STAGE2_CFLAGS) -fno-builtin -nostdinc \ + $(NETBOOT_FLAGS) $(SERIAL_FLAGS) $(HERCULES_FLAGS) + ++STAGE2_COMPILE += $(UUID_FLAGS) ++ + STAGE1_5_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,2000 + STAGE1_5_COMPILE = $(STAGE2_COMPILE) -DNO_DECOMPRESSION=1 -DSTAGE1_5=1 + +@@ -97,7 +109,12 @@ + + if NETBOOT_SUPPORT + pre_stage2_exec_LDADD = ../netboot/libdrivers.a +-endif ++else ++if UUID_SUPPORT ++pre_stage2_exec_LDADD = ../libvolume_id/libvolume_id.a ++endif ++endif ++ + + if DISKLESS_SUPPORT + BUILT_SOURCES = stage2_size.h diskless_size.h + +=== modified file 'stage2/builtins.c' +--- grub-0.97.orig/stage2/builtins.c 2008-01-28 18:15:31 +0000 ++++ grub-0.97/stage2/builtins.c 2008-07-09 17:23:44 +0000 +@@ -49,6 +49,10 @@ + # include <md5.h> + #endif + ++#ifdef SUPPORT_UUID ++#include <volume_id.h> ++#endif ++ + /* The type of kernel loaded. */ + kernel_t kernel_type; + /* The boot device. */ +@@ -4790,6 +4794,168 @@ + "Probe VBE information. If the mode number MODE is specified, show only" + " the information about only the mode." + }; ++ ++ ++ ++#ifdef SUPPORT_UUID ++ ++struct uuid_callback_data ++{ ++ int found; /* 1 if uuid matches */ ++ char *uuid; /* uuid to look for */ ++}; ++ ++static void uuid_info_print(struct volume_id *id, const char *uuid) ++{ ++ const char *type; ++ int i; ++ ++ volume_id_get_type(id, &type); ++ grub_printf("(hd%d", current_drive - 0x80); ++ if ((current_partition & 0xFF0000) != 0xFF0000) ++ { ++ grub_printf (",%d", (current_partition >> 16) & 0xFF); ++ } ++ if ((current_partition & 0x00FF00) != 0x00FF00) ++ { ++ grub_printf (",%c", 'a' + ((current_partition >> 8) & 0xFF)); ++ } ++ grub_printf(") %s",type); ++ for (i=0;i<6-strlen(type);i++) ++ { ++ grub_putchar(' '); ++ } ++ grub_printf(" %s\n",uuid); ++} ++ ++static int uuid_all_probers(volume_id_probe_fn_t probe_fn, ++ struct volume_id *id, ++ uint64_t off, ++ uint64_t size, ++ void *data) ++{ ++ struct uuid_callback_data *uc_data = (struct uuid_callback_data*)data; ++ ++ if (probe_fn(id, off, size) == 0) ++ { ++ const char *volume_uuid; ++ if (volume_id_get_uuid(id, &volume_uuid)) ++ { ++ if (!*(uc_data->uuid)) ++ { ++ uuid_info_print(id, volume_uuid); ++ } ++ else ++ { ++ if (strcmp(volume_uuid, uc_data->uuid) == 0) ++ { ++ grub_printf("Boot from "); ++ uuid_info_print(id, volume_uuid); ++ uc_data->found = 1; ++ return 1; ++ } ++ } ++ } ++ } ++ return 0; ++} ++ ++/* uuid find */ ++/* Search for the uuid arg in all of partitions. */ ++static int ++uuid_func(char *arg, int flag) ++{ ++ unsigned long drive; ++ unsigned long tmp_drive = saved_drive; ++ unsigned long tmp_partition = saved_partition; ++ struct uuid_callback_data uc_data; ++ ++ uc_data.uuid = arg; ++ uc_data.found = 0; ++ ++ /* Just hard disks and USB drives supported by BIOS */ ++ for (drive = 0x80; drive < 0x88; drive++) ++ { ++ unsigned long part = 0xFFFFFF; ++ unsigned long start, len, offset, ext_offset, gpt_offset; ++ int type, entry, gpt_count, gpt_size; ++ char *buf = (char *) RAW_ADDR(0x100000); ++ struct volume_id *vol_id = (struct volume_id *) RAW_ADDR (0x100000 + SECTOR_SIZE); ++ ++ current_drive = drive; ++ while (next_partition (drive, 0xFFFFFF, &part, &type, ++ &start, &len, &offset, &entry, ++ &ext_offset, &gpt_offset, ++ &gpt_count, &gpt_size, buf)) ++ { ++ if (type != PC_SLICE_TYPE_NONE ++ && ! IS_PC_SLICE_TYPE_BSD (type) ++ && ! IS_PC_SLICE_TYPE_EXTENDED (type)) ++ { ++ current_partition = part; ++ errnum = ERR_NONE; ++ /* Attempt to open device, conventional way */ ++ if (! open_device ()) ++ { ++ errnum = ERR_NONE; ++ /* Failed, like NTFS or FAT filesystems, so try the rootnoverify way */ ++ if (open_partition ()) ++ { ++ set_bootdev (0); ++ if (errnum) ++ { ++ /* Give up */ ++ errnum = ERR_NONE; ++ continue; ++ } ++ } ++ } ++ ++ /* And probe for uuid across all fs types */ ++ saved_drive = current_drive; ++ saved_partition = current_partition; ++ ++ grub_memset(vol_id, 0, sizeof(struct volume_id) ); ++ volume_id_all_probers(uuid_all_probers, vol_id, 0, len, (void*)&uc_data); ++ if (uc_data.found) ++ { ++ /* Success! */ ++ errnum = ERR_NONE; ++ return 0; ++ } ++ } ++ /* We want to ignore any error here. */ ++ errnum = ERR_NONE; ++ } ++ ++ /* next_partition always sets ERRNUM in the last call, so clear it. */ ++ errnum = ERR_NONE; ++ } ++ ++ saved_drive = tmp_drive; ++ saved_partition = tmp_partition; ++ current_drive = GRUB_INVALID_DRIVE; ++ current_partition = 0xFFFFFF; ++ errnum = ERR_FILE_NOT_FOUND; ++ ++ if (!*arg) ++ { ++ errnum = ERR_NONE; ++ return 0; ++ } ++ return 1; ++} ++ ++static struct builtin builtin_uuid = ++{ ++ "uuid", ++ uuid_func, ++ BUILTIN_CMDLINE | BUILTIN_HELP_LIST, ++ "uuid UUID", ++ "Set the current \"root device\" to the device with the uuid UUID," ++ " then attempt to mount it" ++}; ++#endif + + + /* The table of builtin commands. Sorted in dictionary order. */ +@@ -4879,6 +5045,9 @@ + &builtin_title, + &builtin_unhide, + &builtin_uppermem, ++#ifdef SUPPORT_UUID ++ &builtin_uuid, ++#endif + &builtin_vbeprobe, + 0 + }; + |