d8205b2ccc
git-svn-id: http://svn.sabayonlinux.org/overlay@2875 d7aec97c-591d-0410-af39-a8856400b30a
5407 lines
141 KiB
Diff
5407 lines
141 KiB
Diff
=== 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
|
|
};
|
|
|