[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: "partnew" Command Writes Wrong Ending Cylinder in MPT
From: |
adrian15 |
Subject: |
Re: "partnew" Command Writes Wrong Ending Cylinder in MPT |
Date: |
Sun, 19 Nov 2006 20:56:49 +0100 |
User-agent: |
Mozilla Thunderbird 1.0.7 (Windows/20050923) |
sburtchin escribió:
sburtchin wrote:
partnew 0x05 2071440 10508400
I tried with (hd1,0) and with different filesystem types but the result is
always same: "830" instead of "831" is written to the ending cylinder
field {(hd1) has CHS 833/240/63.}
I've done some additional testing. Here are a few more unexpected results:
For example: "partnew (hd0,0) 0x0F 2056320 158019120" writes "1021" for end
cylinder
For example: "partnew (hd0,2) 0x0C 116575200 36136800" writes "1021" for
begin & end cylinder
For example: "partnew (hd0,3) 0x00 0 0" writes C/H/S 0/0/1 thru 1021/164/4
For example: "partnew (hd1,2) 0x00 0 0" writes C/H/S 0/0/1 thru 830/164/4
{(hd0) has CHS 10587/240/63.}
Just a hunch, but it seems that partnew cannot write a begin or end cylinder
larger than the largest allowed for that drive minus 2.
I don't know if it matters in actual practice, but "partnew (hd0,3) 0x00 0
0" should write C/H/S 0/0/0 thru 0/0/0.
Hi Sburtchin.
I have been looking at the partnew code and I am not very sure what it
does :) .
What is the algorigthm that partnew should do in your opinnion.
I mean given a partition type, its start and its length how do you
calculate the ending cylinder field ?
I am going to explain more or less how I understand that the end
cylinder is calculated.
new_start + new_len - 1, &end_cl, &end_ch, &end_dh
lba_to_chs function modifies end_cl thanks to:
bbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaahhhhhhhhhhhhhhhhhhhhhh
I am tired. Here is the important source code:
partnew_func (char *arg, int flags)
{
int new_type, new_start, new_len;
int start_cl, start_ch, start_dh;
int end_cl, end_ch, end_dh;
int entry;
char mbr[512];
/* Convert a LBA address to a CHS address in the INT 13 format. */
auto void lba_to_chs (int lba, int *cl, int *ch, int *dh);
void lba_to_chs (int lba, int *cl, int *ch, int *dh)
{
int cylinder, head, sector;
sector = lba % buf_geom.sectors + 1;
head = (lba / buf_geom.sectors) % buf_geom.heads;
cylinder = lba / (buf_geom.sectors * buf_geom.heads);
if (cylinder >= buf_geom.cylinders)
cylinder = buf_geom.cylinders - 1;
*cl = sector | ((cylinder & 0x300) >> 2);
*ch = cylinder & 0xFF;
*dh = head;
}
/* Get the drive and the partition. */
if (! set_device (arg))
return 1;
/* The drive must be a hard disk. */
if (! (current_drive & 0x80))
{
errnum = ERR_BAD_ARGUMENT;
return 1;
}
/* The partition must a primary partition. */
if ((current_partition >> 16) > 3
|| (current_partition & 0xFFFF) != 0xFFFF)
{
errnum = ERR_BAD_ARGUMENT;
return 1;
}
entry = current_partition >> 16;
/* Get the new partition type. */
arg = skip_to (0, arg);
if (! safe_parse_maxint (&arg, &new_type))
return 1;
/* The partition type is unsigned char. */
if (new_type > 0xFF)
{
errnum = ERR_BAD_ARGUMENT;
return 1;
}
/* Get the new partition start. */
arg = skip_to (0, arg);
if (! safe_parse_maxint (&arg, &new_start))
return 1;
/* Get the new partition length. */
arg = skip_to (0, arg);
if (! safe_parse_maxint (&arg, &new_len))
return 1;
/* Read the MBR. */
if (! rawread (current_drive, 0, 0, SECTOR_SIZE, mbr))
return 1;
/* Check if the new partition will fit in the disk. */
if (new_start + new_len > buf_geom.total_sectors)
{
errnum = ERR_GEOM;
return 1;
}
/* Store the partition information in the MBR. */
lba_to_chs (new_start, &start_cl, &start_ch, &start_dh);
lba_to_chs (new_start + new_len - 1, &end_cl, &end_ch, &end_dh);
Maybe you may find the error better than me as long as you have more
knowledge than me on how this C/H/S stuff should work.
Maybe is it only a matter of switching on / off the lba addressing on
the bios ? I do not know.
adrian15