From mboxrd@z Thu Jan 1 00:00:00 1970 Date: Mon, 28 May 2007 20:05:58 +0200 From: tlaronde@polynum.com To: Fans of the OS Plan 9 from Bell Labs <9fans@cse.psu.edu> Message-ID: <20070528180558.GA162@polynum.com> References: <20070523183556.GA2037@polynum.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20070523183556.GA2037@polynum.com> User-Agent: Mutt/1.4.2.2i Subject: [9fans] Re: [explanations] MBR messed up on installation Topicbox-Message-UUID: 73ce2f9a-ead2-11e9-9d60-3106f5b1d025 Hello, The time for me to discover Plan 9 and to be able to dig/edit/compile under Plan 9 for the patches here are, at least, explanations about the process on i386 involving CHS addressing, the BIOS and the partition table. Position of the problem 1. After installing Plan 9 on an i386 with already NetBSD installed, the partition table hold by the MBR was changed: the absolute start (sector in LBA) for the NetBSD partition was changed, the CHS values too (but irrelevant in part because out of reach of CHS addressing), leading to the impossibility to boot in NetBSD. The story ATA CHS addressing scheme 2. The ATA standard specified a CHS based addressing scheme on 28 bits, allowing theorically 128 GiB of disk space (2^28 for sectors, with 512 bytes per sector). The mapping was this: C H S 16 4 8 3. The PC BIOS provides services. The INT 13H is dedicated to disk access, and one of its function deals with CHS addressing. The CHS addressing passed to the BIOS was supposed, in legacy PC, to be passed as is to the ATA controler. But, since it's the PC, the CHS addressing used by the BIOS is distinct from the CHS addressing used by ATA... In the BIOS: C H S 10 8 6 that is only 24 bits. Furthermore, to make things even more interesting, while cylinders and heads are indexed starting at 0, sectors are indexed starting at 1: C: 0..1023 H: 0..255 S: 1..63 To continue in the same mood, Microsoft made a fault in the initial programmation, and didn't even allow the maximum of 256 heads, leading to: C: 0..1023 H: 0..254 S: 1..63 4. The main result, since the legacy BIOS passes the CHS values as is to the ATA controler, is that only the minimal common denominator between the two specification can be used: C H S 10 4 6 that is the limit: 1024 * 16 * 63 sectors hence the 504MiB. 5. Since the disk finally exceeded this 504MiB, a hack was designed. The BIOS was modified to _not_ pass the specification as is to the ATA controler, but to do a mapping between BIOS CHS addressing and ATA CHS addressing, allowing the use of the full range (minus the idiosyncrasies) of the 24 bits. This is called ECHS, and this works even with legacy boot loaders using INT 13H services, since this is the BIOS that does the job. This has nothing to do with LBA, but this allows disk up to: 1024 * 254 * 63 sectors that is 7.8GiB. The first problem is that the cylinder boundary in BIOS CHS addressing may not match the hardware ATA CHS cylinder boundary. The "correct" value is to align on a hardware boundary (if this makes sense). Some fdisk(8) programs try to find a match between BIOS "cylinders" and ATA (hardware) cylinders (that is what NetBSD seems to do): ------ fdisk on NetBSD Disk: /dev/rwd0d NetBSD disklabel disk geometry: cylinders: 38792, heads: 16, sectors/track: 63 (1008 sectors/cylinder) total sectors: 39102336 BIOS disk geometry: cylinders: 1024, heads: 255, sectors/track: 63 (16065 sectors/cylinder) total sectors: 39102336 ------ The first specification is the hardware description (ATA). The second is an ECHS description. 6. If the disk capacity exceeds the BIOS CHS addressing capabilities, the only option is for the boot loader to use LBA services (and for the BIOS to provide these services). 7. The only value that shall not be touched for a chunk (partition) already in use in the absolute sector value (LBA) [and the problem is that Plan 9 fdisk modifies this value]. The partition table. 8. Since the MBR is a "BIOS" program---by a signature, and because, due to its size, it has to use BIOS services---the CHS values are already computed in the partition table for a direct use by the BIOS services, i.e. in the partition table one finds BIOS CHS values. Here is the description in pseudo-code (pseudo because it is not portable, assumes packing of fields and little endianness): /* 3 bytes i.e. 24 bits */ struct Chs { unsigned int head: 8; unsigned int sector: 6; unsigned int cylh: 2; /* high two bits of cylinder */ unsigned int cyll: 8; /* low eight bits of cylinder */ }; /* 16 bytes */ struc Part { uint8_t status; struct Chs Chs_start; uint8_t type; struct Chs Chs_end; uint32_t lba_start; uint32_t size_in_sectors; }; 9. In the MBR the partition table starts at offset 0x1BE (446), with 4 Part entries (4 * 16 = 64) and the last two byte with the signature. Hence, it is easy to see the details of the computation (here using NetBSD tool hexdump(1) ---same can be done with xd(1)--- and awk(1)): ------awk script { print "partition:", NR print "status:", ($1 == 128) ? "ACTIVE" : "NOT ACTIVE" print "start CHS:", int($3 / 64) * 256 + $4, $2, $3 % 64 printf "type: %#x\n", $5 print "end CHS:", int($7 / 64) * 256 + $8, $6, $7 % 64 print "start LBA:", $9 + $10 * 256 + $11 * 65536 + $12 * 16777216 print "size in sectors:", $13 + $14 * 256 + $15 * 65536 + $16 * 16777216 print "" } ----- Looking at the NetBSD computed mbr : $ hexdump -s 0x1BE -n 64 -e '16/1 "%u " "\n"' /tmp/mbr | awk -f mbrtbl.awk partition: 1 status: NOT ACTIVE start CHS: 0 1 1 type: 0x39 end CHS: 138 254 63 start LBA: 63 size in sectors: 2232972 partition: 2 status: NOT ACTIVE start CHS: 139 139 1 type: 0xa9 end CHS: 1023 134 63 start LBA: 2241792 size in sectors: 14329728 partition: 3 status: ACTIVE start CHS: 1023 135 1 type: 0xa9 end CHS: 1023 116 63 start LBA: 16571520 size in sectors: 8192016 partition: 4 status: NOT ACTIVE start CHS: 0 0 0 type: 0 end CHS: 0 0 0 start LBA: 0 size in sectors: 0 As can be seen the values are ECHS (more than 16 heads). Have no sense when we cross the 7.8 GiB border. TODO: track the Plan 9 sources to see the manipulation done. Found where the hardware description is obtained (for the ATA CHS values at least). Problem of portability (this is i386 specific). Why is fdisk(8) recomputing the absolute sector to put it in a BIOS cylinder boundary (that has almost no sense). And why does it redefines the starting sector of a partition it has neither created nor modified (for the geometry). It seems that this is modified when setting the ACTIVE flag, that is all the record is overwritten, including recomputed CHS and LBA values. To be continued. -- Thierry Laronde (Alceste) http://www.kergis.com/ Key fingerprint = 0FF7 E906 FBAF FE95 FD89 250D 52B1 AE95 6006 F40C