* Re: C/H/S from user space
@ 2006-02-17 20:30 Seewer Philippe
0 siblings, 0 replies; 14+ messages in thread
From: Seewer Philippe @ 2006-02-17 20:30 UTC (permalink / raw)
To: linux-os (Dick Johnson); +Cc: linux-kernel
<snip>
wow this is really great... but just for your information
on my ibm notebook the output is this:
Disk parameter table(s) at vector 0x41
Disk0
Cylinders = 1024
Sectors = 63
Heads = 240
Write precomp = 255
Landing zone = 65296
Reserved bit 0 set
Reserved bit 1 set
Reserved bit 2 set
More than 8 heads
Reserved bit 4 set
Defect map present
Disable retries
Disable retries
Disk1
Cylinders = 1024
Sectors = 4
Heads = 16
Write precomp = 0
Landing zone = 0
Disk parameter table(s) at vector 0x46
Disk0
Cylinders = 34281
Sectors = 240
Heads = 230
Write precomp = 7950
Landing zone = 61
Reserved bit 2 set
More than 8 heads
Disable retries
Disk1
Cylinders = 47631
Sectors = 102
Heads = 46
Write precomp = 3698
Landing zone = 7952
More than 8 heads
Defect map present
Disable retries
Just Note the "MAX" of 240 heads (very typical for IBM notebooks).
But anyway this tool is very useful for me. many, many thanks.
^ permalink raw reply [flat|nested] 14+ messages in thread* C/H/S from user space
@ 2006-02-17 17:01 linux-os (Dick Johnson)
2006-02-17 18:37 ` Jeff V. Merkey
0 siblings, 1 reply; 14+ messages in thread
From: linux-os (Dick Johnson) @ 2006-02-17 17:01 UTC (permalink / raw)
To: Linux kernel
[-- Attachment #1: Type: text/plain, Size: 1720 bytes --]
For those who think that C/H/S translation is useful,
attached is a simple program that gets whatever the BIOS
used from user-space. If you have large media (most do),
you will descover that C/H/S is useless because it is
always set to "MAX" like this:
Disk parameter table(s) at vector 0x41
Disk0
Cylinders = 1024
Sectors = 63
Heads = 255
Write precomp = 0
Landing zone = 65296
Reserved bit 0 set
Reserved bit 1 set
Reserved bit 2 set
More than 8 heads
Reserved bit 4 set
Defect map present
Disable retries
Disable retries
Disk1
Cylinders = 306
Sectors = 1
Heads = 4
Write precomp = 0
Landing zone = 12544
Disk parameter table(s) at vector 0x46
Disk0
Cylinders = 306
Sectors = 1
Heads = 4
Write precomp = 0
Landing zone = 12544
Disk1
Cylinders = 306
Sectors = 1
Heads = 4
Write precomp = 0
Landing zone = 12544
Cheers,
Dick Johnson
Penguin : Linux version 2.6.15.4 on an i686 machine (5589.55 BogoMips).
Warning : 98.36% of all statistics are fiction.
_
\x1a\x04
****************************************************************
The information transmitted in this message is confidential and may be privileged. Any review, retransmission, dissemination, or other use of this information by persons or entities other than the intended recipient is prohibited. If you are not the intended recipient, please notify Analogic Corporation immediately - by replying to this message or by sending an email to DeliveryErrors@analogic.com - and destroy all copies of this information, including any attachments, without reading or disclosing them.
Thank you.
[-- Attachment #2: CHS.tar.gz --]
[-- Type: APPLICATION/x-gzip, Size: 4141 bytes --]
^ permalink raw reply [flat|nested] 14+ messages in thread* Re: C/H/S from user space 2006-02-17 17:01 linux-os (Dick Johnson) @ 2006-02-17 18:37 ` Jeff V. Merkey 2006-02-17 19:59 ` Phillip Susi 2006-02-17 20:04 ` linux-os (Dick Johnson) 0 siblings, 2 replies; 14+ messages in thread From: Jeff V. Merkey @ 2006-02-17 18:37 UTC (permalink / raw) To: linux-os (Dick Johnson); +Cc: Linux kernel Dick, The model Netware uses for large drives for calculating C/H/S addressed this problem years ago and provides more useful output, since C/H/S is converted into a hieristic which acts almost like an MD5 hash and for a given dimension, does provide unique output for even very large drives. Code Attached. Jeff ULONG SetPartitionTableGeometry(BYTE *hd, BYTE *sec, BYTE *cyl, ULONG LBA, ULONG TracksPerCylinder, ULONG SectorsPerTrack) { ULONG offset, cylinders, head, sector; if (!cyl || !hd || !sec) return -1; cylinders = (LBA / (TracksPerCylinder * SectorsPerTrack)); offset = LBA % (TracksPerCylinder * SectorsPerTrack); head = (WORD)(offset / SectorsPerTrack); sector = (WORD)(offset % SectorsPerTrack) + 1; if (cylinders < 1023) { *sec = (BYTE)sector; *hd = (BYTE)head; *cyl = (BYTE)(cylinders & 0xff); *sec |= (BYTE)((cylinders >> 2) & 0xC0); } else { *sec = (BYTE)(SectorsPerTrack | 0xC0); *hd = (BYTE)(TracksPerCylinder - 1); *cyl = (BYTE)0xFE; } return 0; } ULONG SetPartitionTableValues(struct PartitionTableEntry *Part, ULONG Type, ULONG StartingLBA, ULONG EndingLBA, ULONG Flag, ULONG TracksPerCylinder, ULONG SectorsPerTrack) { Part->SysFlag = (BYTE) Type; Part->fBootable = (BYTE) Flag; Part->StartLBA = StartingLBA; Part->nSectorsTotal = (EndingLBA - StartingLBA) + 1; SetPartitionTableGeometry(&Part->HeadStart, &Part->SecStart, &Part->CylStart, StartingLBA, TracksPerCylinder, SectorsPerTrack); SetPartitionTableGeometry(&Part->HeadEnd, &Part->SecEnd, &Part->CylEnd, EndingLBA, TracksPerCylinder, SectorsPerTrack); return 0; } linux-os (Dick Johnson) wrote: >For those who think that C/H/S translation is useful, >attached is a simple program that gets whatever the BIOS >used from user-space. If you have large media (most do), >you will descover that C/H/S is useless because it is >always set to "MAX" like this: > > Disk parameter table(s) at vector 0x41 >Disk0 > Cylinders = 1024 > Sectors = 63 > Heads = 255 >Write precomp = 0 > Landing zone = 65296 > Reserved bit 0 set > Reserved bit 1 set > Reserved bit 2 set > More than 8 heads > Reserved bit 4 set > Defect map present > Disable retries > Disable retries >Disk1 > Cylinders = 306 > Sectors = 1 > Heads = 4 >Write precomp = 0 > Landing zone = 12544 > Disk parameter table(s) at vector 0x46 >Disk0 > Cylinders = 306 > Sectors = 1 > Heads = 4 >Write precomp = 0 > Landing zone = 12544 >Disk1 > Cylinders = 306 > Sectors = 1 > Heads = 4 >Write precomp = 0 > Landing zone = 12544 > > >Cheers, >Dick Johnson >Penguin : Linux version 2.6.15.4 on an i686 machine (5589.55 BogoMips). >Warning : 98.36% of all statistics are fiction. >_ >\x1a\x04 > > >**************************************************************** >The information transmitted in this message is confidential and may be privileged. Any review, retransmission, dissemination, or other use of this information by persons or entities other than the intended recipient is prohibited. If you are not the intended recipient, please notify Analogic Corporation immediately - by replying to this message or by sending an email to DeliveryErrors@analogic.com - and destroy all copies of this information, including any attachments, without reading or disclosing them. > >Thank you. > ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: C/H/S from user space 2006-02-17 18:37 ` Jeff V. Merkey @ 2006-02-17 19:59 ` Phillip Susi 2006-02-17 20:04 ` linux-os (Dick Johnson) 1 sibling, 0 replies; 14+ messages in thread From: Phillip Susi @ 2006-02-17 19:59 UTC (permalink / raw) To: Jeff V. Merkey; +Cc: linux-os (Dick Johnson), Linux kernel Other than generate CHS addresses that are invalid due to having S > 62, what is this code supposed to do? Jeff V. Merkey wrote: > > Dick, > > The model Netware uses for large drives for calculating C/H/S addressed > this problem years ago and > provides more useful output, since C/H/S is converted into a hieristic > which acts almost like an MD5 hash > and for a given dimension, does provide unique output for even very > large drives. > > Code Attached. > > Jeff > > > > ULONG SetPartitionTableGeometry(BYTE *hd, BYTE *sec, BYTE *cyl, > ULONG LBA, ULONG TracksPerCylinder, > ULONG SectorsPerTrack) > { > ULONG offset, cylinders, head, sector; > > if (!cyl || !hd || !sec) > return -1; > > cylinders = (LBA / (TracksPerCylinder * SectorsPerTrack)); > offset = LBA % (TracksPerCylinder * SectorsPerTrack); > head = (WORD)(offset / SectorsPerTrack); > sector = (WORD)(offset % SectorsPerTrack) + 1; > > if (cylinders < 1023) > { > *sec = (BYTE)sector; > *hd = (BYTE)head; > *cyl = (BYTE)(cylinders & 0xff); > *sec |= (BYTE)((cylinders >> 2) & 0xC0); > } > else > { > *sec = (BYTE)(SectorsPerTrack | 0xC0); > *hd = (BYTE)(TracksPerCylinder - 1); > *cyl = (BYTE)0xFE; > } > > return 0; > } > > ULONG SetPartitionTableValues(struct PartitionTableEntry *Part, > ULONG Type, > ULONG StartingLBA, > ULONG EndingLBA, > ULONG Flag, > ULONG TracksPerCylinder, > ULONG SectorsPerTrack) > { > > Part->SysFlag = (BYTE) Type; > Part->fBootable = (BYTE) Flag; > Part->StartLBA = StartingLBA; > Part->nSectorsTotal = (EndingLBA - StartingLBA) + 1; > > SetPartitionTableGeometry(&Part->HeadStart, &Part->SecStart, > &Part->CylStart, > StartingLBA, TracksPerCylinder, SectorsPerTrack); > > SetPartitionTableGeometry(&Part->HeadEnd, &Part->SecEnd, &Part->CylEnd, > EndingLBA, TracksPerCylinder, SectorsPerTrack); > > return 0; > > } > > ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: C/H/S from user space 2006-02-17 18:37 ` Jeff V. Merkey 2006-02-17 19:59 ` Phillip Susi @ 2006-02-17 20:04 ` linux-os (Dick Johnson) 2006-02-17 20:24 ` Nick Warne 2006-02-17 21:04 ` Phillip Susi 1 sibling, 2 replies; 14+ messages in thread From: linux-os (Dick Johnson) @ 2006-02-17 20:04 UTC (permalink / raw) To: Jeff V. Merkey; +Cc: Linux kernel On Fri, 17 Feb 2006, Jeff V. Merkey wrote: > > Dick, > > The model Netware uses for large drives for calculating C/H/S addressed > this problem years ago and > provides more useful output, since C/H/S is converted into a hieristic > which acts almost like an MD5 hash > and for a given dimension, does provide unique output for even very > large drives. > > Code Attached. > > Jeff > > > > ULONG SetPartitionTableGeometry(BYTE *hd, BYTE *sec, BYTE *cyl, > ULONG LBA, ULONG TracksPerCylinder, > ULONG SectorsPerTrack) > { > ULONG offset, cylinders, head, sector; > > if (!cyl || !hd || !sec) > return -1; > > cylinders = (LBA / (TracksPerCylinder * SectorsPerTrack)); > offset = LBA % (TracksPerCylinder * SectorsPerTrack); > head = (WORD)(offset / SectorsPerTrack); > sector = (WORD)(offset % SectorsPerTrack) + 1; > > if (cylinders < 1023) > { > *sec = (BYTE)sector; > *hd = (BYTE)head; > *cyl = (BYTE)(cylinders & 0xff); > *sec |= (BYTE)((cylinders >> 2) & 0xC0); > } > else > { > *sec = (BYTE)(SectorsPerTrack | 0xC0); > *hd = (BYTE)(TracksPerCylinder - 1); > *cyl = (BYTE)0xFE; > } > > return 0; > } > > ULONG SetPartitionTableValues(struct PartitionTableEntry *Part, > ULONG Type, > ULONG StartingLBA, > ULONG EndingLBA, > ULONG Flag, > ULONG TracksPerCylinder, > ULONG SectorsPerTrack) > { > > Part->SysFlag = (BYTE) Type; > Part->fBootable = (BYTE) Flag; > Part->StartLBA = StartingLBA; > Part->nSectorsTotal = (EndingLBA - StartingLBA) + 1; > > SetPartitionTableGeometry(&Part->HeadStart, &Part->SecStart, > &Part->CylStart, > StartingLBA, TracksPerCylinder, SectorsPerTrack); > > SetPartitionTableGeometry(&Part->HeadEnd, &Part->SecEnd, &Part->CylEnd, > EndingLBA, TracksPerCylinder, SectorsPerTrack); > > return 0; > > } > > > [SNIPPED...] Yes, it's a very good model, in fact what I've been talking about. However, several people who refused to read or understand, insisted upon obtaining the exact same C/H/S that the machine claimed to use when it was booted. So, since Linux doesn't destroy that information remaining in the BIOS tables, I show how to make it available to a 'root' user. Observation over several machines will show that the BIOS always uses the same stuff for large media and, in fact, it has no choice. Basically, this means that the first part of the boot-code, the stuff that needs to be translated to fit into the int 0x13 registers, needs to be below 1024 cylinders, 63 sectors-track, and 256 heads. Trivial... even LILO was able to do that! Once the machine boots past the requirement to use the BIOS services, it's a CHS=NOP. Cheers, Dick Johnson Penguin : Linux version 2.6.15.4 on an i686 machine (5589.53 BogoMips). Warning : 98.36% of all statistics are fiction. _ \x1a\x04 **************************************************************** The information transmitted in this message is confidential and may be privileged. Any review, retransmission, dissemination, or other use of this information by persons or entities other than the intended recipient is prohibited. If you are not the intended recipient, please notify Analogic Corporation immediately - by replying to this message or by sending an email to DeliveryErrors@analogic.com - and destroy all copies of this information, including any attachments, without reading or disclosing them. Thank you. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: C/H/S from user space 2006-02-17 20:04 ` linux-os (Dick Johnson) @ 2006-02-17 20:24 ` Nick Warne 2006-02-17 20:39 ` linux-os (Dick Johnson) 2006-02-17 21:04 ` Phillip Susi 1 sibling, 1 reply; 14+ messages in thread From: Nick Warne @ 2006-02-17 20:24 UTC (permalink / raw) To: linux-os (Dick Johnson); +Cc: Jeff V. Merkey, Linux kernel > So, since Linux doesn't destroy that information remaining in > the BIOS tables, I show how to make it available to a 'root' user. > Observation over several machines will show that the BIOS always > uses the same stuff for large media and, in fact, it has no choice. > Basically, this means that the first part of the boot-code, the > stuff that needs to be translated to fit into the int 0x13 registers, > needs to be below 1024 cylinders, 63 sectors-track, and 256 heads. > Trivial... even LILO was able to do that! Once the machine boots > past the requirement to use the BIOS services, it's a CHS=NOP. If I am off the mark here, forgive me. Since I moved exclusively to GNU/Linux 2 years ago, I notice when I update kernel I get this: nick@linuxamd:nick$ sudo /sbin/lilo -v LILO version 22.5.9, Copyright (C) 1992-1998 Werner Almesberger Development beyond version 21 Copyright (C) 1999-2004 John Coffman Released 08-Apr-2004 and compiled at 00:18:50 on May 21 2004. Warning: LBA32 addressing assumed Reading boot sector from /dev/hda2 Warning: Kernel & BIOS return differing head/sector geometries for device 0x80 Kernel: 65535 cylinders, 16 heads, 63 sectors BIOS: 1024 cylinders, 255 heads, 63 sectors Warning: Kernel & BIOS return differing head/sector geometries for device 0x81 Kernel: 29777 cylinders, 16 heads, 63 sectors BIOS: 1024 cylinders, 255 heads, 63 sectors Now, from day one I never used the -v option with lilo, but as I get more experienced (!) I do now and see the above... I have never investigated due to worrying if I start messing with it I will trash my disks - as I see all anyway on this disks (and no errors), all works great/fast etc. Is this what is going on here (re this thread?). Nick ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: C/H/S from user space 2006-02-17 20:24 ` Nick Warne @ 2006-02-17 20:39 ` linux-os (Dick Johnson) 0 siblings, 0 replies; 14+ messages in thread From: linux-os (Dick Johnson) @ 2006-02-17 20:39 UTC (permalink / raw) To: Nick Warne; +Cc: Jeff V. Merkey, Linux kernel On Fri, 17 Feb 2006, Nick Warne wrote: > > So, since Linux doesn't destroy that information remaining in >> the BIOS tables, I show how to make it available to a 'root' user. >> Observation over several machines will show that the BIOS always >> uses the same stuff for large media and, in fact, it has no choice. >> Basically, this means that the first part of the boot-code, the >> stuff that needs to be translated to fit into the int 0x13 registers, >> needs to be below 1024 cylinders, 63 sectors-track, and 256 heads. >> Trivial... even LILO was able to do that! Once the machine boots >> past the requirement to use the BIOS services, it's a CHS=NOP. > > > If I am off the mark here, forgive me. > > Since I moved exclusively to GNU/Linux 2 years ago, I notice when I > update kernel I get this: > > nick@linuxamd:nick$ sudo /sbin/lilo -v > LILO version 22.5.9, Copyright (C) 1992-1998 Werner Almesberger > Development beyond version 21 Copyright (C) 1999-2004 John Coffman > Released 08-Apr-2004 and compiled at 00:18:50 on May 21 2004. > > Warning: LBA32 addressing assumed > Reading boot sector from /dev/hda2 > Warning: Kernel & BIOS return differing head/sector geometries for device 0x80 > Kernel: 65535 cylinders, 16 heads, 63 sectors > BIOS: 1024 cylinders, 255 heads, 63 sectors > Warning: Kernel & BIOS return differing head/sector geometries for device 0x81 > Kernel: 29777 cylinders, 16 heads, 63 sectors > BIOS: 1024 cylinders, 255 heads, 63 sectors > > Now, from day one I never used the -v option with lilo, but as I get > more experienced (!) I do now and see the above... I have never > investigated due to worrying if I start messing with it I will trash > my disks - as I see all anyway on this disks (and no errors), all > works great/fast etc. > > Is this what is going on here (re this thread?). > > Nick > Nothing to worry about. If you make lots of new kernels to try them out, you might wish to use GRUB instead of LILO. However, once the boot-process gets out of 16-bit mode, it isn't going to use the 16-bit disk services so it doesn't care about any of that stuff. C/H/S is just a "key" to get you through the fact that the 16-bit BIOS puts some minimal stuff in registers to access the disk. Cheers, Dick Johnson Penguin : Linux version 2.6.15.4 on an i686 machine (5589.53 BogoMips). Warning : 98.36% of all statistics are fiction. _ \x1a\x04 **************************************************************** The information transmitted in this message is confidential and may be privileged. Any review, retransmission, dissemination, or other use of this information by persons or entities other than the intended recipient is prohibited. If you are not the intended recipient, please notify Analogic Corporation immediately - by replying to this message or by sending an email to DeliveryErrors@analogic.com - and destroy all copies of this information, including any attachments, without reading or disclosing them. Thank you. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: C/H/S from user space 2006-02-17 20:04 ` linux-os (Dick Johnson) 2006-02-17 20:24 ` Nick Warne @ 2006-02-17 21:04 ` Phillip Susi 2006-02-17 21:22 ` linux-os (Dick Johnson) 2006-02-17 22:22 ` Jeff V. Merkey 1 sibling, 2 replies; 14+ messages in thread From: Phillip Susi @ 2006-02-17 21:04 UTC (permalink / raw) To: linux-os (Dick Johnson); +Cc: Jeff V. Merkey, Linux kernel linux-os (Dick Johnson) wrote: > > Yes, it's a very good model, in fact what I've been talking about. > However, several people who refused to read or understand, insisted > upon obtaining the exact same C/H/S that the machine claimed to > use when it was booted. > That's because if you don't use the same geometry that the bios reports when calculating the CHS addresses of the sectors you intend to load, you won't be requesting the right sectors from int 13. > So, since Linux doesn't destroy that information remaining in > the BIOS tables, I show how to make it available to a 'root' user. > Observation over several machines will show that the BIOS always > uses the same stuff for large media and, in fact, it has no choice. > Basically, this means that the first part of the boot-code, the > stuff that needs to be translated to fit into the int 0x13 registers, > needs to be below 1024 cylinders, 63 sectors-track, and 256 heads. > Trivial... even LILO was able to do that! Once the machine boots > past the requirement to use the BIOS services, it's a CHS=NOP. > Generally yes, modern large disks will get clamped at 1024 cylinders, 255 heads, and 63 sectors. You seem to be arguing that this will always be the case. If that is so, then the kernel doesn't need to store these values since it is known a priori does it? But it isn't always going to be 255/63, there are some bioses ( I forget which ) that cap the number of heads at 240, and disks that are smaller than 8 gigs also will have less than 255 heads. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: C/H/S from user space 2006-02-17 21:04 ` Phillip Susi @ 2006-02-17 21:22 ` linux-os (Dick Johnson) 2006-02-17 22:20 ` Phillip Susi 2006-02-17 22:24 ` Jeff V. Merkey 2006-02-17 22:22 ` Jeff V. Merkey 1 sibling, 2 replies; 14+ messages in thread From: linux-os (Dick Johnson) @ 2006-02-17 21:22 UTC (permalink / raw) To: Phillip Susi; +Cc: Jeff V. Merkey, Linux kernel On Fri, 17 Feb 2006, Phillip Susi wrote: > linux-os (Dick Johnson) wrote: >> >> Yes, it's a very good model, in fact what I've been talking about. >> However, several people who refused to read or understand, insisted >> upon obtaining the exact same C/H/S that the machine claimed to >> use when it was booted. >> > > That's because if you don't use the same geometry that the bios reports > when calculating the CHS addresses of the sectors you intend to load, > you won't be requesting the right sectors from int 13. ^^^____ Who is YOU??? I would certainly be requesting the right sectors if I (or anybody else who knows what they are doing), wrote the boot code. The boot loader knows about OFFSETS into the device where it's going to get its data, which eventually becomes a whole operating system. It doesn't give a *uck about anything else. There is a table of OFFSETS, obtained from the file-system, of the correct pieces of files (since there will not be a file-system until the machine is booted). This table of offsets needs to be read somewhere in the first 63 sectors (32256 bytes). These offsets contain the junk to be loaded into memory. The boot-code, the code that executes in the 16-bit environment, converts those offsets (after getting data from the DPB) into the respective junk to put into the registers as I explained over and over and over again. You refuse to learn. Please go away. [SNIPPED...] Cheers, Dick Johnson Penguin : Linux version 2.6.15.4 on an i686 machine (5589.53 BogoMips). Warning : 98.36% of all statistics are fiction. _ \x1a\x04 **************************************************************** The information transmitted in this message is confidential and may be privileged. Any review, retransmission, dissemination, or other use of this information by persons or entities other than the intended recipient is prohibited. If you are not the intended recipient, please notify Analogic Corporation immediately - by replying to this message or by sending an email to DeliveryErrors@analogic.com - and destroy all copies of this information, including any attachments, without reading or disclosing them. Thank you. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: C/H/S from user space 2006-02-17 21:22 ` linux-os (Dick Johnson) @ 2006-02-17 22:20 ` Phillip Susi 2006-02-18 3:42 ` Marcin Dalecki 2006-02-17 22:24 ` Jeff V. Merkey 1 sibling, 1 reply; 14+ messages in thread From: Phillip Susi @ 2006-02-17 22:20 UTC (permalink / raw) To: linux-os (Dick Johnson); +Cc: Jeff V. Merkey, Linux kernel linux-os (Dick Johnson) wrote: > Who is YOU??? I would certainly be requesting the right sectors > if I (or anybody else who knows what they are doing), wrote > the boot code. The boot loader knows about OFFSETS into the > device where it's going to get its data, which eventually > becomes a whole operating system. It doesn't give a *uck about > anything else. There is a table of OFFSETS, obtained from > the file-system, of the correct pieces of files (since there > will not be a file-system until the machine is booted). This > table of offsets needs to be read somewhere in the first 63 > sectors (32256 bytes). These offsets contain the junk to > be loaded into memory. > We weren't talking about a boot loader you would write, or lilo even, we were talking about windows's boot loader, which, to the best of my knowledge, directly passes the CHS address of the starting sector of the partition stored in the MBR to int 13. That CHS address is calculated by fdisk based on the geometry it believes the disk has and is written to the MBR when you partition the disk. The last time I checked a dos MBR, the boot code there didn't recompute the CHS address at runtime based on the LBA and current geometry according to the bios, so it has to be written correctly in the first place by fdisk, which requires that fdisk know the bios geometry. > The boot-code, the code that executes in the 16-bit environment, > converts those offsets (after getting data from the DPB) into > the respective junk to put into the registers as I explained > over and over and over again. Maybe I'm just dense, but that's not what I heard you explaining. Is it your position then, that the MS DOS/WIN MBR does actually recompute the CHS address at boot time based on the geometry the bios currently reports, and the LBA in the partition table, rather than use the CHS address stored in the partition table and precomputed by fdisk? If that is the case, then fdisk can use whatever geometry it chooses and everything will be fine, so why does the kernel have to carry around some geometry instead of just letting fdisk make one up when it is run? > > You refuse to learn. Please go away. > That is uncalled for. I don't understand why you have shown a bad attitude this whole time. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: C/H/S from user space 2006-02-17 22:20 ` Phillip Susi @ 2006-02-18 3:42 ` Marcin Dalecki 2006-02-18 16:20 ` Phillip Susi 0 siblings, 1 reply; 14+ messages in thread From: Marcin Dalecki @ 2006-02-18 3:42 UTC (permalink / raw) To: Phillip Susi; +Cc: linux-os (Dick Johnson), Jeff V. Merkey, Linux kernel On 2006-02-17, at 23:20, Phillip Susi wrote: > If that is the case, then fdisk can use whatever geometry it > chooses and everything will be fine, so why does the kernel have to > carry around some geometry instead of just letting fdisk make one > up when it is run? It has been already tried years ago to eliminate this ridicle. The answer to your question is put bluntly: It's like that, because some kernel "prima ballerinas", whose names "relate to alternating current", will get at you with mock up somke and mirror woodo examples where it's supposed to be sooo required. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: C/H/S from user space 2006-02-18 3:42 ` Marcin Dalecki @ 2006-02-18 16:20 ` Phillip Susi 0 siblings, 0 replies; 14+ messages in thread From: Phillip Susi @ 2006-02-18 16:20 UTC (permalink / raw) To: Marcin Dalecki; +Cc: linux-os (Dick Johnson), Jeff V. Merkey, Linux kernel Marcin Dalecki wrote: > It has been already tried years ago to eliminate this ridicle. The > answer to your > question is put bluntly: It's like that, because some kernel "prima > ballerinas", > whose names "relate to alternating current", will get at you with mock > up somke > and mirror woodo examples where it's supposed to be sooo required. I myself have been trying to show why it is required. Unless I am wrong about the msdos MBR code passing the CHS partition start values directly to int 13 rather than computing them based on the LBA in the MBR and the currently reported geometry from the bios, then fdisk does require the correct bios geometry to maintain compatibility with msdos/windows. My original point was that if it is required ( and since it is still in the kernel, that seems to be the case ) then at least make sure it is _correct_. Whether it is needed but wrong, or if it is simply not needed, then it is silly to keep geometry in the kernel. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: C/H/S from user space 2006-02-17 21:22 ` linux-os (Dick Johnson) 2006-02-17 22:20 ` Phillip Susi @ 2006-02-17 22:24 ` Jeff V. Merkey 1 sibling, 0 replies; 14+ messages in thread From: Jeff V. Merkey @ 2006-02-17 22:24 UTC (permalink / raw) To: linux-os (Dick Johnson); +Cc: Phillip Susi, Linux kernel And a very useful translation table for coversion to 63 head models. Jeff // Use the Phoenix method of drive translation // to translate drive geometry for those drives // that exceed 1024 cylinders in size. // // Phoenix Geometry Translation Table // ----------------------------------- // // Phys Cylinders Phys Heads Trans Cyl Trans Heads Max // -------------------------------------------------------- // 1 <C<= 1024 1 <H<= 16 C = C H = H 528 MB // 1024 <C<= 2048 1 <H<= 16 C = C/2 H = H*2 1.0 GB // 2048 <C<= 4096 1 <H<= 16 C = C/4 H = H*4 2.1 GB // 4096 <C<= 8192 1 <H<= 16 C = C/8 H = H*8 4.2 GB // 8192 <C<= 16384 1 <H<= 16 C = C/16 H = H*16 8.4 GB // 16384 <C<= 32768 1 <H<= 8 C = C/32 H = H*32 8.4 GB // 32768 <C<= 65536 1 <H<= 4 C = C/64 H = H*64 8.4 GB // // LBA Assisted Translation Table // ------------------------------ // // (NOTE: The method below is an alternate method for // translating large drives that does not place any limits // on reported drive geometry. It has the disadvantage // of always assuming 63 Sectors Per Track.) // // Range Sectors Heads Cylinders // ----------------------------------------------------- // 1 MB <X< 528 MB 63 16 X/(63 * 16 * 512) // 528 MB <X< 1.0 GB 63 32 X/(63 * 32 * 512) // 1.0 GB <X< 2.1 GB 63 64 X/(63 * 64 * 512) // 2.1 GB <X< 4.2 GB 63 128 X/(63 * 128 * 512) // 4.2 GB <X< 8.4 GB 63 255 X/(63 * 255 * 512) // // Adjust cylinder and head dimensions until this drive // presents a geometry with a cylinder count linux-os (Dick Johnson) wrote: >On Fri, 17 Feb 2006, Phillip Susi wrote: > > > >>linux-os (Dick Johnson) wrote: >> >> >>>Yes, it's a very good model, in fact what I've been talking about. >>>However, several people who refused to read or understand, insisted >>>upon obtaining the exact same C/H/S that the machine claimed to >>>use when it was booted. >>> >>> >>> >>That's because if you don't use the same geometry that the bios reports >>when calculating the CHS addresses of the sectors you intend to load, >>you won't be requesting the right sectors from int 13. >> >> > ^^^____ > >Who is YOU??? I would certainly be requesting the right sectors >if I (or anybody else who knows what they are doing), wrote >the boot code. The boot loader knows about OFFSETS into the >device where it's going to get its data, which eventually >becomes a whole operating system. It doesn't give a *uck about >anything else. There is a table of OFFSETS, obtained from >the file-system, of the correct pieces of files (since there >will not be a file-system until the machine is booted). This >table of offsets needs to be read somewhere in the first 63 >sectors (32256 bytes). These offsets contain the junk to >be loaded into memory. > >The boot-code, the code that executes in the 16-bit environment, >converts those offsets (after getting data from the DPB) into >the respective junk to put into the registers as I explained >over and over and over again. > >You refuse to learn. Please go away. > >[SNIPPED...] > >Cheers, >Dick Johnson >Penguin : Linux version 2.6.15.4 on an i686 machine (5589.53 BogoMips). >Warning : 98.36% of all statistics are fiction. >_ >\x1a\x04 > >**************************************************************** >The information transmitted in this message is confidential and may be privileged. Any review, retransmission, dissemination, or other use of this information by persons or entities other than the intended recipient is prohibited. If you are not the intended recipient, please notify Analogic Corporation immediately - by replying to this message or by sending an email to DeliveryErrors@analogic.com - and destroy all copies of this information, including any attachments, without reading or disclosing them. > >Thank you. >- >To unsubscribe from this list: send the line "unsubscribe linux-kernel" in >the body of a message to majordomo@vger.kernel.org >More majordomo info at http://vger.kernel.org/majordomo-info.html >Please read the FAQ at http://www.tux.org/lkml/ > > > ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: C/H/S from user space 2006-02-17 21:04 ` Phillip Susi 2006-02-17 21:22 ` linux-os (Dick Johnson) @ 2006-02-17 22:22 ` Jeff V. Merkey 1 sibling, 0 replies; 14+ messages in thread From: Jeff V. Merkey @ 2006-02-17 22:22 UTC (permalink / raw) To: Phillip Susi; +Cc: linux-os (Dick Johnson), Linux kernel Here's the code to calculate that as well -- from NetWare -- with int 13 IOCTL calls and from within Windows 98. This code builds on the djgcc DOS version og GNU tools. Jeff #if (DOS_UTIL) #define READ_DEVICE 0x02 #define WRITE_DEVICE 0x03 #define NO_VERIFY 0x00 #define WRITE_VERIFY 0x01 // convert cylinder/head/sector addressing to LBA ULONG CHStoLBA(ULONG disk, LONGLONG cyl, ULONG head, ULONG sector) { register ULONG lba; ULONG heads = SystemDisk[disk]->TracksPerCylinder; ULONG sectors = SystemDisk[disk]->SectorsPerTrack; lba = cyl * (heads * sectors); lba += (head * sectors); lba += sector; lba -= 1; // CHS is 1 relative so adjust LBA by subtracting 1 return lba; } // convert LBA to cylinder/head/sector addressing ULONG LBAtoCHS(ULONG disk, ULONG lba, LONGLONG *cyl, ULONG *head, ULONG *sector) { ULONG offset; ULONG heads = SystemDisk[disk]->TracksPerCylinder; ULONG sectors = SystemDisk[disk]->SectorsPerTrack; if (!cyl || !head || !sector) return -1; *cyl = (lba / (heads * sectors)); offset = lba % (heads * sectors); *head = (WORD)(offset / sectors); *sector = (WORD)(offset % sectors) + 1; // sector addressing is // 1 relative so add 1 return 0; } ULONG pReadDiskSectors(ULONG disk, ULONG StartingLBA, BYTE *Sector, ULONG sectors, ULONG readAhead) { register ULONG bps, ccode, bytes = 0; register NWDISK *NWDisk; LONGLONG cylinder; ULONG head, sector; static _go32_dpmi_registers r; #if (WINDOWS_98_UTIL) static union REGS rl; #endif NWFSSet(&r, 0, sizeof(_go32_dpmi_registers)); NWDisk = SystemDisk[disk]; bps = NWDisk->BytesPerSector; if ((sectors * bps) > IO_BLOCK_SIZE) return bytes; #if (WINDOWS_98_UTIL) rl.x.ax = 0x440D; // generic IOCTL rl.h.bh = 3; // locks levels 0, 1, 2 or 3 rl.h.bl = (0x80 | (disk & 0x7F)); // dos limit is 128 drives rl.h.ch = 0x08; // device category rl.h.cl = 0x4B; // lock physical volume rl.x.dx = 0; // permissions int86(0x21, &rl, &rl); #endif if (NWDisk->Int13Extensions) { EXT_REQUEST request; NWFSSet(&request, 0, sizeof(EXT_REQUEST)); request.Size = sizeof(EXT_REQUEST); request.Blocks = sectors; request.TransferBuffer = (ULONG)(NWDisk->DataSegment << 16) & 0xFFFF0000; request.LBA = StartingLBA; movedata(_my_ds(), (unsigned)&request, NWDisk->RequestSelector, 0, sizeof(EXT_REQUEST)); r.h.ah = 0x42; r.h.dl = (0x80 | (disk & 0x7F)); r.x.ds = NWDisk->RequestSegment; r.x.si = 0; r.x.ss = r.x.sp = r.x.flags = 0; ccode = _go32_dpmi_simulate_int(0x13, &r); if (ccode) goto ReadExit; // error if carry flag is set if (r.x.flags & 1) { // if the drive reported an ECC occurred, return success if (r.h.ah == 0x11) { movedata(NWDisk->DataSelector, 0, _my_ds(), (unsigned)Sector, (sectors * bps)); bytes = (sectors * bps); goto ReadExit; } else goto ReadExit; } movedata(NWDisk->DataSelector, 0, _my_ds(), (unsigned)Sector, (sectors * bps)); bytes = (sectors * bps); goto ReadExit; } else { ccode = LBAtoCHS(disk, StartingLBA, &cylinder, &head, §or); if (ccode) goto ReadExit; r.h.dh = (BYTE)head; r.h.dl = (0x80 | (disk & 0x7F)); r.h.ch = (BYTE)(cylinder & 0xFF); r.h.cl = (BYTE)((cylinder & 0x0300) >> 2); r.h.cl |= (BYTE)(sector & 0x3F); r.h.ah = READ_DEVICE; r.h.al = (BYTE)sectors; r.x.es = NWDisk->DataSegment; r.x.bx = 0; r.x.ss = r.x.sp = r.x.flags = 0; ccode = _go32_dpmi_simulate_int(0x13, &r); if (ccode) goto ReadExit; // error if carry flag is set if (r.x.flags & 1) { // if the drive reported an ECC occurred, return success if (r.h.ah == 0x11) { movedata(NWDisk->DataSelector, 0, _my_ds(), (unsigned)Sector, (sectors * bps)); bytes = (sectors * bps); goto ReadExit; } else goto ReadExit; } movedata(NWDisk->DataSelector, 0, _my_ds(), (unsigned)Sector, (sectors * bps)); bytes = (sectors * bps); } ReadExit:; #if (WINDOWS_98_UTIL) rl.x.ax = 0x440D; // generic IOCTL rl.h.bl = (0x80 | (disk & 0x7F)); // dos limit is 128 drives rl.h.ch = 0x08; // device category rl.h.cl = 0x6B; // unlock physical volume int86(0x21, &rl, &rl); #endif return bytes; } ULONG pWriteDiskSectors(ULONG disk, ULONG StartingLBA, BYTE *Sector, ULONG sectors, ULONG readAhead) { register ULONG bps, ccode, bytes = 0; register NWDISK *NWDisk; LONGLONG cylinder; ULONG head, sector; static _go32_dpmi_registers r; #if (WINDOWS_98_UTIL) static union REGS rl; #endif NWFSSet(&r, 0, sizeof(_go32_dpmi_registers)); NWDisk = SystemDisk[disk]; bps = NWDisk->BytesPerSector; if ((sectors * bps) > IO_BLOCK_SIZE) return bytes; #if (WINDOWS_98_UTIL) rl.x.ax = 0x440D; // generic IOCTL rl.h.bh = 3; // locks levels 0, 1, 2 or 3 rl.h.bl = (0x80 | (disk & 0x7F)); // dos limit is 128 drives rl.h.ch = 0x08; // device category rl.h.cl = 0x4B; // lock physical volume rl.x.dx = 0; // permissions int86(0x21, &rl, &rl); #endif if (NWDisk->Int13Extensions) { EXT_REQUEST request; NWFSSet(&request, 0, sizeof(EXT_REQUEST)); request.Size = sizeof(EXT_REQUEST); request.Blocks = sectors; request.TransferBuffer = (ULONG)(NWDisk->DataSegment << 16) & 0xFFFF0000; request.LBA = StartingLBA; movedata(_my_ds(), (unsigned)&request, NWDisk->RequestSelector, 0, sizeof(EXT_REQUEST)); movedata(_my_ds(), (unsigned)Sector, NWDisk->DataSelector, 0, (sectors * bps)); r.h.ah = 0x43; r.h.al = NO_VERIFY; r.h.dl = (0x80 | (disk & 0x7F)); r.x.ds = NWDisk->RequestSegment; r.x.si = 0; r.x.ss = r.x.sp = r.x.flags = 0; ccode = _go32_dpmi_simulate_int(0x13, &r); if (ccode) goto WriteExit; // error if carry flag is set if (r.x.flags & 1) { // if the drive reported an ECC occurred, return success if (r.h.ah == 0x11) { bytes = (sectors * bps); goto WriteExit; } else goto WriteExit; } bytes = (sectors * bps); goto WriteExit; } else { ccode = LBAtoCHS(disk, StartingLBA, &cylinder, &head, §or); if (ccode) goto WriteExit; movedata(_my_ds(), (unsigned)Sector, NWDisk->DataSelector, 0, (sectors * bps)); r.h.dh = (BYTE)head; r.h.dl = (0x80 | (disk & 0x7F)); r.h.ch = (BYTE)(cylinder & 0xFF); r.h.cl = (BYTE)((cylinder & 0x0300) >> 2); r.h.cl |= (BYTE)(sector & 0x3F); r.h.ah = WRITE_DEVICE; r.h.al = (BYTE)sectors; r.x.es = NWDisk->DataSegment; r.x.bx = 0; r.x.ds = r.x.ss = r.x.sp = r.x.flags = 0; ccode = _go32_dpmi_simulate_int(0x13, &r); if (ccode) goto WriteExit; // error if carry flag is set if (r.x.flags & 1) { // if the drive reported an ECC occurred, return success if (r.h.ah == 0x11) { bytes = (sectors * bps); goto WriteExit; } else goto WriteExit; } bytes = (sectors * bps); goto WriteExit; } WriteExit:; #if (WINDOWS_98_UTIL) rl.x.ax = 0x440D; // generic IOCTL rl.h.bl = (0x80 | (disk & 0x7F)); // dos limit is 128 drives rl.h.ch = 0x08; // device category rl.h.cl = 0x6B; // unlock physical volume int86(0x21, &rl, &rl); #endif return bytes; } ULONG pZeroFillDiskSectors(ULONG disk, ULONG StartingLBA, ULONG sectors, ULONG readAhead) { register ULONG bps, ccode, bytes = 0; register NWDISK *NWDisk; LONGLONG cylinder; ULONG head, sector; static _go32_dpmi_registers r; #if (WINDOWS_98_UTIL) static union REGS rl; #endif NWFSSet(&r, 0, sizeof(_go32_dpmi_registers)); NWDisk = SystemDisk[disk]; bps = NWDisk->BytesPerSector; if ((sectors * bps) > IO_BLOCK_SIZE) return bytes; movedata(_my_ds(), (unsigned)ZeroBuffer, NWDisk->DataSelector, 0, (sectors * bps)); #if (WINDOWS_98_UTIL) rl.x.ax = 0x440D; // generic IOCTL rl.h.bh = 3; // locks levels 0, 1, 2 or 3 rl.h.bl = (0x80 | (disk & 0x7F)); // dos limit is 128 drives rl.h.ch = 0x08; // device category rl.h.cl = 0x4B; // lock physical volume rl.x.dx = 0; // permissions int86(0x21, &rl, &rl); #endif if (NWDisk->Int13Extensions) { EXT_REQUEST request; NWFSSet(&request, 0, sizeof(EXT_REQUEST)); request.Size = sizeof(EXT_REQUEST); request.Blocks = sectors; request.TransferBuffer = (ULONG)(NWDisk->DataSegment << 16) & 0xFFFF0000; request.LBA = StartingLBA; movedata(_my_ds(), (unsigned)&request, NWDisk->RequestSelector, 0, sizeof(EXT_REQUEST)); r.h.ah = 0x43; r.h.al = NO_VERIFY; r.h.dl = (0x80 | (disk & 0x7F)); r.x.ds = NWDisk->RequestSegment; r.x.si = 0; r.x.ss = r.x.sp = r.x.flags = 0; ccode = _go32_dpmi_simulate_int(0x13, &r); if (ccode) goto FillExit; // error if carry flag is set if (r.x.flags & 1) { // if the drive reported an ECC occurred, return success if (r.h.ah == 0x11) { bytes = (sectors * bps); goto FillExit; } else goto FillExit; } bytes = (sectors * bps); goto FillExit; } else { ccode = LBAtoCHS(disk, StartingLBA, &cylinder, &head, §or); if (ccode) goto FillExit; r.h.dh = (BYTE)head; r.h.dl = (0x80 | (disk & 0x7F)); r.h.ch = (BYTE)(cylinder & 0xFF); r.h.cl = (BYTE)((cylinder & 0x0300) >> 2); r.h.cl |= (BYTE)(sector & 0x3F); r.h.ah = 0x03; r.h.al = (BYTE)sectors; r.x.es = NWDisk->DataSegment; r.x.bx = 0; r.x.ds = r.x.ss = r.x.sp = r.x.flags = 0; ccode = _go32_dpmi_simulate_int(0x13, &r); if (ccode) goto FillExit; // error if carry flag is set if (r.x.flags & 1) { // if the drive reported an ECC occurred, return success if (r.h.ah == 0x11) { bytes = (sectors * bps); goto FillExit; } else goto FillExit; } bytes = (sectors * bps); goto FillExit; } FillExit:; #if (WINDOWS_98_UTIL) rl.x.ax = 0x440D; // generic IOCTL rl.h.bl = (0x80 | (disk & 0x7F)); // dos limit is 128 drives rl.h.ch = 0x08; // device category rl.h.cl = 0x6B; // unlock physical volume int86(0x21, &rl, &rl); #endif return bytes; } void ScanDiskDevices(void) { register ULONG j, i, retCode; BYTE *Sector; static union REGS r; DRIVE_INFO dinfo; Sector = NWFSIOAlloc(IO_BLOCK_SIZE, DISKBUF_TAG); if (!Sector) { NWFSPrint("nwfs: allocation error in AddDiskDevices\n"); return; } for (FirstValidDisk = (ULONG)-1, j = 0; j < MAX_DOS_DISKS; j++) { #if (WINDOWS_98_UTIL) r.x.ax = 0x440D; // generic IOCTL r.h.bh = 1; // locks levels 0, 1, 2 or 3 r.h.bl = (0x80 | (j & 0x7F)); // dos limit is 128 drives r.h.ch = 0x08; // device category r.h.cl = 0x4B; // lock physical volume r.x.dx = 1; // permissions r.h.cflag = 0x0001; int86(0x21, &r, &r); #endif // test fixed disk status r.h.ah = 0x10; // test drive status r.h.dl = (0x80 | (j & 0x7F)); // dos limit is 128 drives int86(0x13, &r, &r); // if we got the drive status, and the drive is active, // assume the disk is valid. if ((!r.h.cflag) && (!r.h.ah)) { // now check if this device supports removable media. This // would indicate this device is a CDROM drive. If we detect // that this device supports removable meida, then do not // add it -- it's most likely a CDROM or tape device and // we should not add it. // see if a change line is available for this device. r.h.ah = 0x15; // test drive status r.h.dl = (0x80 | (j & 0x7F)); // dos limit is 128 drives int86(0x13, &r, &r); // 00-no drive, 01-diskette, 02-change line, 03-fixed disk if (r.h.ch == 0x02) { #if (WINDOWS_98_UTIL) r.x.ax = 0x440D; // generic IOCTL r.h.bl = (0x80 | (j & 0x7F)); // dos limit is 128 drives r.h.ch = 0x08; // device category r.h.cl = 0x6B; // unlock physical volume int86(0x21, &r, &r); #endif continue; } if (!SystemDisk[j]) { SystemDisk[j] = (NWDISK *) NWFSAlloc(sizeof(NWDISK), NWDISK_TAG); if (!SystemDisk[j]) { NWFSPrint("nwfs: memory allocation failure in AddDiskDevices\n"); #if (WINDOWS_98_UTIL) r.x.ax = 0x440D; // generic IOCTL r.h.bl = (0x80 | (j & 0x7F)); // dos limit is 128 drives r.h.ch = 0x08; // device category r.h.cl = 0x6B; // unlock physical volume int86(0x21, &r, &r); #endif continue; } NWFSSet(SystemDisk[j], 0, sizeof(NWDISK)); } SystemDisk[j]->PhysicalDiskHandle = (void *)(0x80 | (j & 0x7F)); SystemDisk[j]->DiskNumber = j; SystemDisk[j]->Int13Extensions = Int13ExtensionsPresent(j); SystemDisk[j]->DataSegment = __dpmi_allocate_dos_memory(PARAGRAPH_ALIGN(IO_BLOCK_SIZE), &SystemDisk[j]->DataSelector); if (SystemDisk[j]->DataSegment == (WORD) -1) { SystemDisk[j]->PhysicalDiskHandle = 0; NWFSFree(SystemDisk[j]); SystemDisk[j] = 0; #if (WINDOWS_98_UTIL) r.x.ax = 0x440D; // generic IOCTL r.h.bl = (0x80 | (j & 0x7F)); // dos limit is 128 drives r.h.ch = 0x08; // device category r.h.cl = 0x6B; // unlock physical volume int86(0x21, &r, &r); #endif continue; } SystemDisk[j]->DriveInfoSegment = __dpmi_allocate_dos_memory(PARAGRAPH_ALIGN(IO_BLOCK_SIZE), &SystemDisk[j]->DriveInfoSelector); if (SystemDisk[j]->DriveInfoSegment == (WORD) -1) { if (SystemDisk[j]->DataSelector) __dpmi_free_dos_memory(SystemDisk[j]->DataSelector); SystemDisk[j]->DataSelector = 0; SystemDisk[j]->PhysicalDiskHandle = 0; NWFSFree(SystemDisk[j]); SystemDisk[j] = 0; #if (WINDOWS_98_UTIL) r.x.ax = 0x440D; // generic IOCTL r.h.bl = (0x80 | (j & 0x7F)); // dos limit is 128 drives r.h.ch = 0x08; // device category r.h.cl = 0x6B; // unlock physical volume int86(0x21, &r, &r); #endif continue; } SystemDisk[j]->RequestSegment = __dpmi_allocate_dos_memory(PARAGRAPH_ALIGN(sizeof(EXT_REQUEST)), &SystemDisk[j]->RequestSelector); if (SystemDisk[j]->RequestSegment == (WORD) -1) { if (SystemDisk[j]->DataSelector) __dpmi_free_dos_memory(SystemDisk[j]->DataSelector); SystemDisk[j]->DataSelector = 0; if (SystemDisk[j]->DriveInfoSelector) __dpmi_free_dos_memory(SystemDisk[j]->DriveInfoSelector); SystemDisk[j]->DriveInfoSelector = 0; SystemDisk[j]->PhysicalDiskHandle = 0; NWFSFree(SystemDisk[j]); SystemDisk[j] = 0; #if (WINDOWS_98_UTIL) r.x.ax = 0x440D; // generic IOCTL r.h.bl = (0x80 | (j & 0x7F)); // dos limit is 128 drives r.h.ch = 0x08; // device category r.h.cl = 0x6B; // unlock physical volume int86(0x21, &r, &r); #endif continue; } // if int 13 extensions are present, then adjust drive geometry // based on reported drive info. if (SystemDisk[j]->Int13Extensions) { register ULONG cylinders, heads, sectors; _go32_dpmi_registers r32; NWFSSet(&r32, 0, sizeof(_go32_dpmi_registers)); NWFSSet(&dinfo, 0, sizeof(DRIVE_INFO)); dinfo.Size = sizeof(DRIVE_INFO); movedata(_my_ds(), (unsigned)&dinfo, SystemDisk[j]->DriveInfoSelector, 0, sizeof(DRIVE_INFO)); // get int 13 extension drive info r32.h.ah = 0x48; r32.h.dl = (0x80 | (j & 0x7F)); r32.x.si = 0; r32.x.ds = SystemDisk[j]->DriveInfoSegment; _go32_dpmi_simulate_int(0x13, &r32); movedata(SystemDisk[j]->DriveInfoSelector, 0, _my_ds(), (unsigned)&dinfo, sizeof(DRIVE_INFO)); // if TotalSectors is 0, then there are no drives // attached to this controller. if (!dinfo.TotalSectors) { if (SystemDisk[j]->RequestSelector) __dpmi_free_dos_memory(SystemDisk[j]->RequestSelector); SystemDisk[j]->RequestSelector = 0; if (SystemDisk[j]->DataSelector) __dpmi_free_dos_memory(SystemDisk[j]->DataSelector); SystemDisk[j]->DataSelector = 0; if (SystemDisk[j]->DriveInfoSelector) __dpmi_free_dos_memory(SystemDisk[j]->DriveInfoSelector); SystemDisk[j]->DriveInfoSelector = 0; SystemDisk[j]->PhysicalDiskHandle = 0; NWFSFree(SystemDisk[j]); SystemDisk[j] = 0; #if (WINDOWS_98_UTIL) r.x.ax = 0x440D; // generic IOCTL r.h.bl = (0x80 | (j & 0x7F)); // dos limit is 128 drives r.h.ch = 0x08; // device category r.h.cl = 0x6B; // unlock physical volume int86(0x21, &r, &r); #endif continue; } r.h.ah = 0x08; // read drive parameters r.h.dl = (0x80 | (j & 0x7F)); int86(0x13, &r, &r); if (r.h.cflag) { if (SystemDisk[j]->RequestSelector) __dpmi_free_dos_memory(SystemDisk[j]->RequestSelector); SystemDisk[j]->RequestSelector = 0; if (SystemDisk[j]->DataSelector) __dpmi_free_dos_memory(SystemDisk[j]->DataSelector); SystemDisk[j]->DataSelector = 0; if (SystemDisk[j]->DriveInfoSelector) __dpmi_free_dos_memory(SystemDisk[j]->DriveInfoSelector); SystemDisk[j]->DriveInfoSelector = 0; SystemDisk[j]->PhysicalDiskHandle = 0; NWFSFree(SystemDisk[j]); SystemDisk[j] = 0; #if (WINDOWS_98_UTIL) r.x.ax = 0x440D; // generic IOCTL r.h.bl = (0x80 | (j & 0x7F)); // dos limit is 128 drives r.h.ch = 0x08; // device category r.h.cl = 0x6B; // unlock physical volume int86(0x21, &r, &r); #endif continue; } // translate drive geometry based on the total sectors // reported by the Int 13 extension procedure. heads = r.h.dh + 1; sectors = ((WORD)r.h.cl & 0x003F); cylinders = (dinfo.TotalSectors / (heads * sectors)); // make sure that cylinders are within the maximum value // allowed by the Int 13 Extended Architecture. At present, // this limit is 16 mega-tera sectors (2^64). // assume the current IDE limits for cylinder count if (cylinders > (ULONG) 65536) { if (SystemDisk[j]->RequestSelector) __dpmi_free_dos_memory(SystemDisk[j]->RequestSelector); SystemDisk[j]->RequestSelector = 0; if (SystemDisk[j]->DataSelector) __dpmi_free_dos_memory(SystemDisk[j]->DataSelector); SystemDisk[j]->DataSelector = 0; if (SystemDisk[j]->DriveInfoSelector) __dpmi_free_dos_memory(SystemDisk[j]->DriveInfoSelector); SystemDisk[j]->DriveInfoSelector = 0; SystemDisk[j]->PhysicalDiskHandle = 0; NWFSFree(SystemDisk[j]); SystemDisk[j] = 0; #if (WINDOWS_98_UTIL) r.x.ax = 0x440D; // generic IOCTL r.h.bl = (0x80 | (j & 0x7F)); // dos limit is 128 drives r.h.ch = 0x08; // device category r.h.cl = 0x6B; // unlock physical volume int86(0x21, &r, &r); #endif continue; } // Use the Phoenix method of drive translation // to translate drive geometry for those drives // that exceed 1024 cylinders in size. // // Phoenix Geometry Translation Table // ----------------------------------- // // Phys Cylinders Phys Heads Trans Cyl Trans Heads Max // -------------------------------------------------------- // 1 <C<= 1024 1 <H<= 16 C = C H = H 528 MB // 1024 <C<= 2048 1 <H<= 16 C = C/2 H = H*2 1.0 GB // 2048 <C<= 4096 1 <H<= 16 C = C/4 H = H*4 2.1 GB // 4096 <C<= 8192 1 <H<= 16 C = C/8 H = H*8 4.2 GB // 8192 <C<= 16384 1 <H<= 16 C = C/16 H = H*16 8.4 GB // 16384 <C<= 32768 1 <H<= 8 C = C/32 H = H*32 8.4 GB // 32768 <C<= 65536 1 <H<= 4 C = C/64 H = H*64 8.4 GB // // LBA Assisted Translation Table // ------------------------------ // // (NOTE: The method below is an alternate method for // translating large drives that does not place any limits // on reported drive geometry. It has the disadvantage // of always assuming 63 Sectors Per Track.) // // Range Sectors Heads Cylinders // ----------------------------------------------------- // 1 MB <X< 528 MB 63 16 X/(63 * 16 * 512) // 528 MB <X< 1.0 GB 63 32 X/(63 * 32 * 512) // 1.0 GB <X< 2.1 GB 63 64 X/(63 * 64 * 512) // 2.1 GB <X< 4.2 GB 63 128 X/(63 * 128 * 512) // 4.2 GB <X< 8.4 GB 63 255 X/(63 * 255 * 512) // // Adjust cylinder and head dimensions until this drive // presents a geometry with a cylinder count that is less // than 1024 or Heads less than or equal to 255. if (cylinders >= 1024) { while ((heads * 2) <= 256) { heads *= 2; cylinders /= 2; if (cylinders < 1024) break; } } if (FirstValidDisk == (ULONG)-1) FirstValidDisk = j; SystemDisk[j]->BytesPerSector = 512; SystemDisk[j]->Cylinders = (LONGLONG) cylinders; SystemDisk[j]->TracksPerCylinder = heads; SystemDisk[j]->SectorsPerTrack = sectors; SystemDisk[j]->driveSize = (LONGLONG) (SystemDisk[j]->Cylinders * SystemDisk[j]->TracksPerCylinder * SystemDisk[j]->SectorsPerTrack * SystemDisk[j]->BytesPerSector); #if (VERBOSE) NWFSPrint("disk-%d cyl-%d head-%d sector-%d (Int 13)\n", (int)j, (int)SystemDisk[j]->Cylinders, (int)SystemDisk[j]->TracksPerCylinder, (int)SystemDisk[j]->SectorsPerTrack); #endif } else { // query the drive parameters with standard bios r.h.ah = 0x08; r.h.dl = (0x80 | (j & 0x7F)); int86(0x13, &r, &r); if (r.h.cflag) { if (SystemDisk[j]->RequestSelector) __dpmi_free_dos_memory(SystemDisk[j]->RequestSelector); SystemDisk[j]->RequestSelector = 0; if (SystemDisk[j]->DataSelector) __dpmi_free_dos_memory(SystemDisk[j]->DataSelector); SystemDisk[j]->DataSelector = 0; if (SystemDisk[j]->DriveInfoSelector) __dpmi_free_dos_memory(SystemDisk[j]->DriveInfoSelector); SystemDisk[j]->DriveInfoSelector = 0; SystemDisk[j]->PhysicalDiskHandle = 0; NWFSFree(SystemDisk[j]); SystemDisk[j] = 0; #if (WINDOWS_98_UTIL) r.x.ax = 0x440D; // generic IOCTL r.h.bl = (0x80 | (j & 0x7F)); // dos limit is 128 drives r.h.ch = 0x08; // device category r.h.cl = 0x6B; // unlock physical volume int86(0x21, &r, &r); #endif continue; } if (FirstValidDisk == (ULONG)-1) FirstValidDisk = j; SystemDisk[j]->BytesPerSector = 512; SystemDisk[j]->Cylinders = (LONGLONG)(((WORD)((WORD)r.h.cl << 2) & 0x0300) | (WORD)r.h.ch) + 1; SystemDisk[j]->TracksPerCylinder = (r.h.dh + 1); SystemDisk[j]->SectorsPerTrack = ((WORD)r.h.cl & 0x003F); SystemDisk[j]->driveSize = (LONGLONG) (SystemDisk[j]->Cylinders * SystemDisk[j]->TracksPerCylinder * SystemDisk[j]->SectorsPerTrack * SystemDisk[j]->BytesPerSector); #if (VERBOSE) NWFSPrint("disk-%d cyl-%d head-%d sector-%d\n", (int)j, (int)SystemDisk[j]->Cylinders, (int)SystemDisk[j]->TracksPerCylinder, (int)SystemDisk[j]->SectorsPerTrack); #endif } #if (WINDOWS_98_UTIL) r.x.ax = 0x440D; // generic IOCTL r.h.bl = (0x80 | (j & 0x7F)); // dos limit is 128 drives r.h.ch = 0x08; // device category r.h.cl = 0x6B; // unlock physical volume int86(0x21, &r, &r); #endif TotalDisks++; if (TotalDisks > MaximumDisks) MaximumDisks = TotalDisks; retCode = ReadDiskSectors(j, 0, Sector, IO_BLOCK_SIZE / SystemDisk[j]->BytesPerSector, IO_BLOCK_SIZE / SystemDisk[j]->BytesPerSector); if (!retCode) { NWFSPrint("nwfs: disk-%d read error in ScanDiskDevices\n", (int)j); continue; } NWFSCopy(&SystemDisk[j]->partitionSignature, &Sector[0x01FE], 2); if (SystemDisk[j]->partitionSignature != 0xAA55) { #if (VERBOSE) NWFSPrint("nwfs: partition signature 0xAA55 not found disk(%d)\n", (int)j); #endif NWFSSet(&SystemDisk[j]->PartitionTable[0].fBootable, 0, 64); continue; } else { NWFSCopy(&SystemDisk[j]->PartitionTable[0].fBootable, &Sector[0x01BE], 64); } // scan for Netware Partitions and detect 3.x and 4.x/5.x partition types for (i=0, SystemDisk[j]->NumberOfPartitions = 0; i < 4; i++) { if (SystemDisk[j]->PartitionTable[i].nSectorsTotal) SystemDisk[j]->NumberOfPartitions++; if (SystemDisk[j]->PartitionTable[i].SysFlag == NETWARE_386_ID) { retCode = ReadDiskSectors(j, SystemDisk[j]->PartitionTable[i].StartLBA, Sector, IO_BLOCK_SIZE / SystemDisk[j]->BytesPerSector, IO_BLOCK_SIZE / SystemDisk[j]->BytesPerSector); if (!retCode) { NWFSPrint("nwfs: disk-%d read error in ScanDiskDevices (part)\n", (int)j); continue; } if (!NWFSCompare(Sector, NwPartSignature, 16)) SystemDisk[j]->PartitionVersion[i] = NW4X_PARTITION; else SystemDisk[j]->PartitionVersion[i] = NW3X_PARTITION; } } } } NWFSFree(Sector); return; } Phillip Susi wrote: > linux-os (Dick Johnson) wrote: > >> >> Yes, it's a very good model, in fact what I've been talking about. >> However, several people who refused to read or understand, insisted >> upon obtaining the exact same C/H/S that the machine claimed to >> use when it was booted. >> > > That's because if you don't use the same geometry that the bios > reports when calculating the CHS addresses of the sectors you intend > to load, you won't be requesting the right sectors from int 13. > >> So, since Linux doesn't destroy that information remaining in >> the BIOS tables, I show how to make it available to a 'root' user. >> Observation over several machines will show that the BIOS always >> uses the same stuff for large media and, in fact, it has no choice. >> Basically, this means that the first part of the boot-code, the >> stuff that needs to be translated to fit into the int 0x13 registers, >> needs to be below 1024 cylinders, 63 sectors-track, and 256 heads. >> Trivial... even LILO was able to do that! Once the machine boots >> past the requirement to use the BIOS services, it's a CHS=NOP. >> > > Generally yes, modern large disks will get clamped at 1024 cylinders, > 255 heads, and 63 sectors. You seem to be arguing that this will > always be the case. If that is so, then the kernel doesn't need to > store these values since it is known a priori does it? But it isn't > always going to be 255/63, there are some bioses ( I forget which ) > that cap the number of heads at 240, and disks that are smaller than 8 > gigs also will have less than 255 heads. > > > ^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2006-02-18 16:21 UTC | newest] Thread overview: 14+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2006-02-17 20:30 C/H/S from user space Seewer Philippe -- strict thread matches above, loose matches on Subject: below -- 2006-02-17 17:01 linux-os (Dick Johnson) 2006-02-17 18:37 ` Jeff V. Merkey 2006-02-17 19:59 ` Phillip Susi 2006-02-17 20:04 ` linux-os (Dick Johnson) 2006-02-17 20:24 ` Nick Warne 2006-02-17 20:39 ` linux-os (Dick Johnson) 2006-02-17 21:04 ` Phillip Susi 2006-02-17 21:22 ` linux-os (Dick Johnson) 2006-02-17 22:20 ` Phillip Susi 2006-02-18 3:42 ` Marcin Dalecki 2006-02-18 16:20 ` Phillip Susi 2006-02-17 22:24 ` Jeff V. Merkey 2006-02-17 22:22 ` Jeff V. Merkey
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox