SDB:在大型磁盘上安装
请参阅本文的页面以获取更多信息。
GRUB 问题
如果没有补丁,GRUB 将无法从大型磁盘阵列启动(因为您需要使用 GPT 磁盘标签),因此您的安装将会很复杂。首先,获取一台 32 位机器。您需要使 GRUB 成为 32 位,如果您有一台 32 位机器,这将更容易。获取 0.97 源代码树并使用上述文章中提到的两个补丁对其进行修补。
构建 grub。我将其构建为安装在 /opt/grub 中。在您的构建机器上安装它,并将该树(在我的例子中为 /opt/grub)复制到 USB 存储设备或 CD 或其他介质上。
YaST 安装
默认情况下,YaST 会使用 MSDOS 磁盘标签对您的磁盘进行分区。这不起作用,因为存在 2TB 的限制。在进入分区程序之前,切换 VT 以获取 shell。运行 gpart 并将 GPT 磁盘标签放在磁盘上。如果您愿意,也可以创建一些分区。
在 YaST-2 安装程序中,完成您的分区。YaST 会很好地保留 GPT 磁盘标签。
正常进行安装。YaST 会警告您并告诉您 grub 将无法工作。确实如此。点击通过。当安装的第一阶段完成后,系统将重新启动,但不会走太远。
此时,启动到救援系统。将您的根磁盘挂载到 /mnt。chroot 到 /mnt。手动 mknod 您的磁盘阵列和分区的 /dev 文件(/dev/sda 是 b 8 0,/dev/sda1 是 b 8 1,等等)。挂载您的 /boot。将您修补的 grub 树从您保存它的介质复制到 /opt/grub(或者您在运行 Configure 时所说的位置)。然后,cd /opt/grub/sbin。./grub-install /dev/sda。
现在 umount 您的 /boot,并删除您创建的 /dev/sda* 文件。
退出 chroot 并 umount 您的根目录。
reboot
您的机器应该从这个大型磁盘阵列启动,并且 YaST 应该正常继续。
补丁
GRUB 0.97 的 Initrd 补丁
Date: 2005-11-11
Author: Otavio Salvador
Comment: Stolen from SuSE grub package.
It fix the max address of initrd image and include a safe
default in case of it isn't available
--- grub-0.94/stage2/boot.c.orig 2004-01-11 09:49:05.000000000 +0100
+++ grub-0.94/stage2/boot.c 2004-03-04 16:11:21.857403508 +0100
@@ -810,8 +810,11 @@
moveto = (mbi.mem_upper + 0x400) << 10;
moveto = (moveto - len) & 0xfffff000;
- max_addr = (lh->header == LINUX_MAGIC_SIGNATURE && lh->version >= 0x0203
- ? lh->initrd_addr_max : LINUX_INITRD_MAX_ADDRESS);
+ max_addr = LINUX_INITRD_MAX_ADDRESS;
+ if (lh->header == LINUX_MAGIC_SIGNATURE &&
+ lh->version >= 0x0203 &&
+ lh->initrd_addr_max < max_addr)
+ max_addr = lh->initrd_addr_max;
if (moveto + len >= max_addr)
moveto = (max_addr - len) & 0xfffff000;
GRUB 0.96 的 GPT 补丁(适用于 0.97)
--- grub-0.96/stage2/builtins.c 2004-06-20 09:33:04.000000000 -0400
+++ grub-0.96-patched/stage2/builtins.c 2007-01-04 13:56:06.000000000 -0500
@@ -1229,14 +1229,15 @@
for (drive = 0x80; drive < 0x88; drive++)
{
unsigned long part = 0xFFFFFF;
- unsigned long start, len, offset, ext_offset;
- int type, entry;
+ unsigned long start, len, offset, ext_offset, gpt_offset;
+ int type, entry, gpt_count, gpt_size;
char buf[SECTOR_SIZE];
current_drive = drive;
while (next_partition (drive, 0xFFFFFF, &part, &type,
&start, &len, &offset, &entry,
- &ext_offset, buf))
+ &ext_offset, &gpt_offset,
+ &gpt_count, &gpt_size, buf))
{
if (type != PC_SLICE_TYPE_NONE
&& ! IS_PC_SLICE_TYPE_BSD (type)
@@ -2806,8 +2807,8 @@
{
int new_type;
unsigned long part = 0xFFFFFF;
- unsigned long start, len, offset, ext_offset;
- int entry, type;
+ unsigned long start, len, offset, ext_offset, gpt_offset;
+ int entry, type, gpt_count, gpt_size;
char mbr[512];
/* Get the drive and the partition. */
@@ -2844,7 +2845,14 @@
/* Look for the partition. */
while (next_partition (current_drive, 0xFFFFFF, &part, &type,
&start, &len, &offset, &entry,
- &ext_offset, mbr))
+ &ext_offset, &gpt_offset, &gpt_count, &gpt_size, mbr))
+ /* The partition may not be a GPT partition. */
+ if (gpt_offset != 0)
+ {
+ errnum = ERR_BAD_ARGUMENT;
+ return 1;
+ }
+
{
if (part == current_partition)
{
diff -ruBbd --unidirectional-new-file grub-0.96/stage2/disk_io.c grub-0.96-patched/stage2/disk_io.c
--- grub-0.96/stage2/disk_io.c 2004-05-23 12:35:24.000000000 -0400
+++ grub-0.96-patched/stage2/disk_io.c 2007-01-04 14:01:08.000000000 -0500
@@ -21,6 +21,7 @@
#include <shared.h>
#include <filesys.h>
+#include <gpt.h>
#ifdef SUPPORT_NETBOOT
# define GRUB 1
@@ -502,8 +503,8 @@
set_partition_hidden_flag (int hidden)
{
unsigned long part = 0xFFFFFF;
- unsigned long start, len, offset, ext_offset;
- int entry, type;
+ unsigned long start, len, offset, ext_offset, gpt_offset;
+ int entry, type, gpt_count, gpt_size;
char mbr[512];
/* The drive must be a hard disk. */
@@ -524,7 +525,14 @@
/* Look for the partition. */
while (next_partition (current_drive, 0xFFFFFF, &part, &type,
&start, &len, &offset, &entry,
- &ext_offset, mbr))
+ &ext_offset, &gpt_offset, &gpt_count, &gpt_size, mbr))
+ /* The partition may not be a GPT partition. */
+ if (gpt_offset != 0)
+ {
+ errnum = ERR_BAD_ARGUMENT;
+ return 1;
+ }
+
{
if (part == current_partition)
{
@@ -577,11 +585,14 @@
unsigned long *partition, int *type,
unsigned long *start, unsigned long *len,
unsigned long *offset, int *entry,
- unsigned long *ext_offset, char *buf)
+ unsigned long *ext_offset,
+ unsigned long *gpt_offset, int *gpt_count,
+ int *gpt_size, char *buf)
{
/* Forward declarations. */
auto int next_bsd_partition (void);
auto int next_pc_slice (void);
+ auto int next_gpt_slice(void);
/* Get next BSD partition in current PC slice. */
int next_bsd_partition (void)
@@ -666,6 +677,40 @@
return 0;
}
+ /* If this is a GPT partition table, read it as such. */
+ if (*entry == -1 && *offset == 0 && PC_SLICE_TYPE (buf, 0) == PC_SLICE_TYPE_GPT)
+ {
+ struct grub_gpt_header *hdr = (struct grub_gpt_header *) buf;
+
+ /* Read in the GPT Partition table header. */
+ if (! rawread (drive, 1, 0, SECTOR_SIZE, buf))
+ return 0;
+
+ if (hdr->magic == GPT_HEADER_MAGIC && hdr->version == 0x10000)
+ {
+ /* Let gpt_offset point to the first entry in the GPT
+ partition table. This can also be used by callers of
+ next_partition to determine if a entry comes from a
+ GPT partition table or not. */
+ *gpt_offset = hdr->partitions;
+ *gpt_count = hdr->maxpart;
+ *gpt_size = hdr->partentry_size;
+
+ return next_gpt_slice();
+ }
+ else
+ {
+ /* This is not a valid header for a GPT partition table.
+ Re-read the MBR or the boot sector of the extended
+ partition. */
+ if (! rawread (drive, *offset, 0, SECTOR_SIZE, buf))
+ return 0;
+ }
+ }
+
+ /* Not a GPT partition. */
+ *gpt_offset = 0;
+
/* Increase the entry number. */
(*entry)++;
@@ -710,6 +755,43 @@
return 1;
}
+ /* Get the next GPT slice. */
+ int next_gpt_slice (void)
+ {
+ struct grub_gpt_partentry *gptentry = (struct grub_gpt_partentry *) buf;
+ /* Make GPT partitions show up as PC slices. */
+ int pc_slice_no = (*partition & 0xFF0000) >> 16;
+
+ /* If this is the first time... */
+ if (pc_slice_no == 0xFF)
+ {
+ pc_slice_no = -1;
+ *entry = -1;
+ }
+
+ do {
+ (*entry)++;
+
+ if (*entry >= *gpt_count)
+ {
+ errnum = ERR_NO_PART;
+ return 0;
+ }
+ /* Read in the GPT Partition table entry. */
+ if (! rawread (drive, (*gpt_offset) + GPT_ENTRY_SECTOR (*gpt_size, *entry), GPT_ENTRY_INDEX (*gpt_s
ize, *entry), *gpt_size, buf))
+ return 0;
+ } while (! (gptentry->type1 && gptentry->type2));
+
+ pc_slice_no++;
+ *start = gptentry->start;
+ *len = gptentry->end - gptentry->start + 1;
+ *type = PC_SLICE_TYPE_EXT2FS;
+ *entry = pc_slice_no;
+ *partition = (*entry << 16) | 0xFFFF;
+
+ return 1;
+ }
+
/* Start the body of this function. */
#ifndef STAGE1_5
@@ -717,6 +799,9 @@
return 0;
#endif
+ if (*partition != 0xFFFFFF && *gpt_offset != 0)
+ return next_gpt_slice ();
+
/* If previous partition is a BSD partition or a PC slice which
contains BSD partitions... */
if ((*partition != 0xFFFFFF && IS_PC_SLICE_TYPE_BSD (*type & 0xff))
@@ -755,6 +840,9 @@
unsigned long dest_partition = current_partition;
unsigned long part_offset;
unsigned long ext_offset;
+ unsigned long gpt_offset;
+ int gpt_count;
+ int gpt_size;
int entry;
char buf[SECTOR_SIZE];
int bsd_part, pc_slice;
@@ -766,7 +854,8 @@
int ret = next_partition (current_drive, dest_partition,
¤t_partition, ¤t_slice,
&part_start, &part_length,
- &part_offset, &entry, &ext_offset, buf);
+ &part_offset, &entry, &ext_offset,
+ &gpt_offset, &gpt_count, &gpt_size, buf);
bsd_part = (current_partition >> 8) & 0xFF;
pc_slice = current_partition >> 16;
return ret;
diff -ruBbd --unidirectional-new-file grub-0.96/stage2/gpt.h grub-0.96-patched/stage2/gpt.h
--- grub-0.96/stage2/gpt.h 1969-12-31 19:00:00.000000000 -0500
+++ grub-0.96-patched/stage2/gpt.h 2007-01-04 13:52:14.000000000 -0500
@@ -0,0 +1,68 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2002,2005,2006 Free Software Foundation, Inc.
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _GPT_H
+#define _GPT_H
+
+typedef signed char grub_int8_t;
+typedef signed short grub_int16_t;
+typedef signed int grub_int32_t;
+typedef signed long long int grub_int64_t;
+typedef unsigned char grub_uint8_t;
+typedef unsigned short grub_uint16_t;
+typedef unsigned int grub_uint32_t;
+typedef unsigned long long int grub_uint64_t;
+
+struct grub_gpt_header
+{
+ grub_uint64_t magic;
+ grub_uint32_t version;
+ grub_uint32_t headersize;
+ grub_uint32_t crc32;
+ grub_uint32_t unused1;
+ grub_uint64_t primary;
+ grub_uint64_t backup;
+ grub_uint64_t start;
+ grub_uint64_t end;
+ grub_uint8_t guid[16];
+ grub_uint64_t partitions;
+ grub_uint32_t maxpart;
+ grub_uint32_t partentry_size;
+ grub_uint32_t partentry_crc32;
+} __attribute__ ((packed));
+
+struct grub_gpt_partentry
+{
+ grub_uint64_t type1;
+ grub_uint64_t type2;
+ grub_uint8_t guid[16];
+ grub_uint64_t start;
+ grub_uint64_t end;
+ grub_uint8_t attrib;
+ char name[72];
+} __attribute__ ((packed));
+
+#define GPT_HEADER_MAGIC 0x5452415020494645UL
+
+#define GPT_ENTRY_SECTOR(size,entry) \
+ ((((entry) * (size) + 1) & ~(SECTOR_SIZE - 1)) >> SECTOR_BITS)
+#define GPT_ENTRY_INDEX(size,entry) \
+ ((((entry) * (size) + 1) & (SECTOR_SIZE - 1)) - 1)
+
+#endif /* _GPT_H */
diff -ruBbd --unidirectional-new-file grub-0.96/stage2/pc_slice.h grub-0.96-patched/stage2/pc_slice.h
--- grub-0.96/stage2/pc_slice.h 2003-07-09 07:45:53.000000000 -0400
+++ grub-0.96-patched/stage2/pc_slice.h 2007-01-04 13:52:14.000000000 -0500
@@ -115,6 +115,7 @@
#define PC_SLICE_TYPE_LINUX_EXTENDED 0x85
#define PC_SLICE_TYPE_VSTAFS 0x9e
#define PC_SLICE_TYPE_DELL_UTIL 0xde
+#define PC_SLICE_TYPE_GPT 0xee
#define PC_SLICE_TYPE_LINUX_RAID 0xfd
diff -ruBbd --unidirectional-new-file grub-0.96/stage2/shared.h grub-0.96-patched/stage2/shared.h
--- grub-0.96/stage2/shared.h 2004-06-19 12:40:09.000000000 -0400
+++ grub-0.96-patched/stage2/shared.h 2007-01-04 13:52:15.000000000 -0500
@@ -934,7 +934,9 @@
unsigned long *partition, int *type,
unsigned long *start, unsigned long *len,
unsigned long *offset, int *entry,
- unsigned long *ext_offset, char *buf);
+ unsigned long *ext_offset,
+ unsigned long *gpt_offset, int *gpt_count,
+ int *gpt_size, char *buf);
/* Sets device to the one represented by the SAVED_* parameters. */
int make_saved_active (void);