NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: install/45990: sysinst uses traditional 63 sector MBR offset
The following reply was made to PR install/45990; it has been noted by GNATS.
From: Izumi Tsutsui <tsutsui%ceres.dti.ne.jp@localhost>
To: gnats-bugs%NetBSD.org@localhost
Cc: netbsd-bugs%NetBSD.org@localhost, tsutsui%ceres.dti.ne.jp@localhost
Subject: Re: install/45990: sysinst uses traditional 63 sector MBR offset
Date: Sun, 4 Mar 2012 12:37:43 +0900
> >Synopsis: sysinst uses traditional 63 sector MBR offset
:
> >Fix:
> Fix src/utils/sysinst/mbr.c to use proper boundary?
The attached patch fixes mbr.c to use ths same strategy as fdisk(8):
>> the alignment of the first partition is
>> inspected. If it ends on a 2048 sector boundary, then the align-
>> ment is set to 2048, if the start is a power of 2 less than, or
>> equal to 2048 then the offset is set to the start sector. If the
>> first partition isn't defined then the alignment and offset for
>> disks larger than 128GB is set to 2048 (1MB). In all other cases
>> the alignment default to a cylinder and the offset to a track
>> (both using the BIOS geometry). The 1MB alignment is the same as
>> that used by recent windows versions.
I wonder if using 1MB boundary for smaller disks is still worth
for modern SSD or other flash media, but it's a different problem.
---
Index: mbr.c
===================================================================
RCS file: /cvsroot/src/distrib/utils/sysinst/mbr.c,v
retrieving revision 1.89
diff -u -p -r1.89 mbr.c
--- mbr.c 5 Jan 2012 21:29:24 -0000 1.89
+++ mbr.c 4 Mar 2012 03:20:54 -0000
@@ -113,6 +113,10 @@ static int get_mapping(struct mbr_partit
daddr_t *);
static void convert_mbr_chs(int, int, int, uint8_t *, uint8_t *,
uint8_t *, uint32_t);
+static void get_ptn_0_offset(struct mbr_partition *);
+
+static unsigned int ptn_alignment;
+static unsigned int ptn_0_offset;
/*
* Notes on the extended partition editor.
@@ -462,8 +466,9 @@ set_mbr_type(menudesc *m, void *arg)
return 0;
mbri->extended = ext;
ext->sector = mbrp->mbrp_start;
- ext->mbr.mbr_parts[0].mbrp_start = bsec;
- ext->mbr.mbr_parts[0].mbrp_size = mbrp->mbrp_size - bsec;
+ ext->mbr.mbr_parts[0].mbrp_start = ptn_0_offset;
+ ext->mbr.mbr_parts[0].mbrp_size =
+ mbrp->mbrp_size - ptn_0_offset;
}
mbrp->mbrp_type = type;
@@ -742,14 +747,14 @@ edit_mbr_size(menudesc *m, void *arg)
/* If unchanged, don't re-round size */
new = dflt;
else {
- /* Round end to cylinder boundary */
+ /* Round end to the partition alignment */
if (sizemult != 1) {
new *= sizemult;
- new += rounddown(start, current_cylsize);
- new = roundup(new, current_cylsize);
+ new += rounddown(start, ptn_alignment);
+ new = roundup(new, ptn_alignment);
new -= start;
while (new <= 0)
- new += current_cylsize;
+ new += ptn_alignment;
}
}
if (new > max)
@@ -1237,12 +1242,12 @@ mbr_use_wholedisk(mbr_info_t *mbri)
memset(&mbri->mbrb, 0, sizeof mbri->mbrb);
#endif
part[0].mbrp_type = MBR_PTYPE_NETBSD;
- part[0].mbrp_size = dlsize - bsec;
- part[0].mbrp_start = bsec;
+ part[0].mbrp_size = dlsize - ptn_0_offset;
+ part[0].mbrp_start = ptn_0_offset;
part[0].mbrp_flag = MBR_PFLAG_ACTIVE;
- ptstart = bsec;
- ptsize = dlsize - bsec;
+ ptstart = ptn_0_offset;
+ ptsize = dlsize - ptn_0_offset;
return 1;
}
@@ -1450,6 +1455,10 @@ read_mbr(const char *disk, mbr_info_t *m
*/
if (bsec == 0)
bsec = dlsec;
+ ptn_0_offset = bsec;
+ /* use 1MB default offset on large disks as fdisk(8) */
+ if (dlsize > 2048 * 1024 * 128)
+ ptn_0_offset = 2048;
memset(mbri, 0, sizeof *mbri);
@@ -1467,7 +1476,9 @@ read_mbr(const char *disk, mbr_info_t *m
break;
mbrp = &mbrs->mbr_parts[0];
- if (ext_base != 0) {
+ if (ext_base == 0) {
+ get_ptn_0_offset(mbrp);
+ } else {
/* sanity check extended chain */
if (MBR_IS_EXTENDED(mbrp[0].mbrp_type))
break;
@@ -1547,9 +1558,9 @@ read_mbr(const char *disk, mbr_info_t *m
ext->sector = base;
ext->mbr.mbr_magic = htole16(MBR_MAGIC);
ext->mbr.mbr_parts[1] = mbrp[1];
- ext->mbr.mbr_parts[0].mbrp_start = bsec;
+ ext->mbr.mbr_parts[0].mbrp_start = ptn_0_offset;
ext->mbr.mbr_parts[0].mbrp_size =
- ext_base + limit - base - bsec;
+ ext_base + limit - base - ptn_0_offset;
mbrp[1].mbrp_type = MBR_PTYPE_EXT;
mbrp[1].mbrp_start = base - ext_base;
mbrp[1].mbrp_size = limit - mbrp[1].mbrp_start;
@@ -1850,3 +1861,36 @@ get_mapping(struct mbr_partition *parts,
return 0;
}
+
+/*
+ * Determine first partition header offset value as fdisk(8) does.
+ */
+static void
+get_ptn_0_offset(struct mbr_partition *mbrp0)
+{
+ uint32_t ptn_0_base, ptn_0_limit;
+
+ /* Default to using 'traditional' cylinder alignment */
+ ptn_alignment = bhead * bsec;
+ ptn_0_offset = bsec;
+
+ if (mbrp0->mbrp_type != 0) {
+ /* Try to copy offset of first partition */
+ ptn_0_base = le32toh(mbrp0->mbrp_start);
+ ptn_0_limit = ptn_0_base + le32toh(mbrp0->mbrp_size);
+ if (!(ptn_0_limit & 2047)) {
+ /* Partition ends on a 1MB boundary, align to 1MB */
+ ptn_alignment = 2048;
+ if (ptn_0_base <= 2048
+ && !(ptn_0_base & (ptn_0_base - 1))) {
+ /* ptn_base is a power of 2, use it */
+ ptn_0_offset = ptn_0_base;
+ }
+ }
+ } else {
+ /* Use 1MB offset for large (>128GB) disks */
+ if (dlsize > 2048 * 1024 * 128)
+ ptn_alignment = 2048;
+ ptn_0_offset = 2048;
+ }
+}
---
Izumi Tsutsui
Home |
Main Index |
Thread Index |
Old Index