소스 검색

[int13] Improve geometry guessing for unaligned partitions

Some partition tables have partitions that are not aligned to a
cylinder boundary, which confuses the current geometry guessing logic.

Enhance the existing logic to ensure that we never reduce our guesses
for the number of heads or sectors per track, and add extra logic to
calculate the exact number of sectors per track if we find a partition
that starts within cylinder zero.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 7 년 전
부모
커밋
ebceb8ad8a
1개의 변경된 파일45개의 추가작업 그리고 11개의 파일을 삭제
  1. 45
    11
      src/arch/x86/interface/pcbios/int13.c

+ 45
- 11
src/arch/x86/interface/pcbios/int13.c 파일 보기

219
 	struct master_boot_record *mbr = scratch;
219
 	struct master_boot_record *mbr = scratch;
220
 	struct partition_table_entry *partition;
220
 	struct partition_table_entry *partition;
221
 	unsigned int i;
221
 	unsigned int i;
222
+	unsigned int start_cylinder;
223
+	unsigned int start_head;
224
+	unsigned int start_sector;
222
 	unsigned int end_head;
225
 	unsigned int end_head;
223
 	unsigned int end_sector;
226
 	unsigned int end_sector;
224
 	int rc;
227
 	int rc;
225
 
228
 
226
-	/* Default guess is xx/255/63 */
227
-	*heads = 255;
228
-	*sectors = 63;
229
-
230
 	/* Read partition table */
229
 	/* Read partition table */
231
 	if ( ( rc = sandev_rw ( sandev, 0, 1, virt_to_user ( mbr ),
230
 	if ( ( rc = sandev_rw ( sandev, 0, 1, virt_to_user ( mbr ),
232
 				block_read ) ) != 0 ) {
231
 				block_read ) ) != 0 ) {
244
 	 * heads and sectors_per_track if we find any used
243
 	 * heads and sectors_per_track if we find any used
245
 	 * partitions.
244
 	 * partitions.
246
 	 */
245
 	 */
246
+	*heads = 0;
247
+	*sectors = 0;
247
 	for ( i = 0 ; i < 4 ; i++ ) {
248
 	for ( i = 0 ; i < 4 ; i++ ) {
249
+
250
+		/* Skip empty partitions */
248
 		partition = &mbr->partitions[i];
251
 		partition = &mbr->partitions[i];
252
+		if ( ! partition->type )
253
+			continue;
254
+
255
+		/* If partition starts on cylinder 0 then we can
256
+		 * unambiguously determine the number of sectors.
257
+		 */
258
+		start_cylinder = PART_CYLINDER ( partition->chs_start );
259
+		start_head = PART_HEAD ( partition->chs_start );
260
+		start_sector = PART_SECTOR ( partition->chs_start );
261
+		if ( ( start_cylinder == 0 ) && ( start_head != 0 ) ) {
262
+			*sectors = ( ( partition->start + 1 - start_sector ) /
263
+				     start_head );
264
+			DBGC ( sandev, "INT13 drive %02x guessing C/H/S "
265
+			       "xx/xx/%d based on partition %d\n",
266
+			       sandev->drive, *sectors, ( i + 1 ) );
267
+		}
268
+
269
+		/* If partition ends on a higher head or sector number
270
+		 * than our current guess, then increase the guess.
271
+		 */
249
 		end_head = PART_HEAD ( partition->chs_end );
272
 		end_head = PART_HEAD ( partition->chs_end );
250
 		end_sector = PART_SECTOR ( partition->chs_end );
273
 		end_sector = PART_SECTOR ( partition->chs_end );
251
-		if ( ! ( partition->type && end_head && end_sector ) )
252
-			continue;
253
-		*heads = ( end_head + 1 );
254
-		*sectors = end_sector;
255
-		DBGC ( sandev, "INT13 drive %02x guessing C/H/S xx/%d/%d based "
256
-		       "on partition %d\n",
257
-		       sandev->drive, *heads, *sectors, ( i + 1 ) );
274
+		if ( ( end_head + 1 ) > *heads ) {
275
+			*heads = ( end_head + 1 );
276
+			DBGC ( sandev, "INT13 drive %02x guessing C/H/S "
277
+			       "xx/%d/xx based on partition %d\n",
278
+			       sandev->drive, *heads, ( i + 1 ) );
279
+		}
280
+		if ( end_sector > *sectors ) {
281
+			*sectors = end_sector;
282
+			DBGC ( sandev, "INT13 drive %02x guessing C/H/S "
283
+			       "xx/xx/%d based on partition %d\n",
284
+			       sandev->drive, *sectors, ( i + 1 ) );
285
+		}
258
 	}
286
 	}
259
 
287
 
288
+	/* Default guess is xx/255/63 */
289
+	if ( ! *heads )
290
+		*heads = 255;
291
+	if ( ! *sectors )
292
+		*sectors = 63;
293
+
260
 	return 0;
294
 	return 0;
261
 }
295
 }
262
 
296
 

Loading…
취소
저장