@@ -320,6 +320,173 @@ int is_valid_dos_buf(void *buf)
320
320
return test_block_type (buf ) == DOS_MBR ? 0 : -1 ;
321
321
}
322
322
323
+ #if CONFIG_IS_ENABLED (CMD_MBR )
324
+ static void lba_to_chs (lbaint_t lba , unsigned char * rc , unsigned char * rh ,
325
+ unsigned char * rs )
326
+ {
327
+ unsigned int c , h , s ;
328
+ /* use fixed CHS geometry */
329
+ unsigned int sectpertrack = 63 ;
330
+ unsigned int heads = 255 ;
331
+
332
+ c = (lba + 1 ) / sectpertrack / heads ;
333
+ h = (lba + 1 ) / sectpertrack - c * heads ;
334
+ s = (lba + 1 ) - (c * heads + h ) * sectpertrack ;
335
+
336
+ if (c > 1023 ) {
337
+ c = 1023 ;
338
+ h = 254 ;
339
+ s = 63 ;
340
+ }
341
+
342
+ * rc = c & 0xff ;
343
+ * rh = h ;
344
+ * rs = s + ((c & 0x300 ) >> 2 );
345
+ }
346
+
347
+ static void mbr_fill_pt_entry (dos_partition_t * pt , lbaint_t start ,
348
+ lbaint_t relative , lbaint_t size , uchar sys_ind , bool bootable )
349
+ {
350
+ pt -> boot_ind = bootable ? 0x80 : 0x00 ;
351
+ pt -> sys_ind = sys_ind ;
352
+ lba_to_chs (start , & pt -> cyl , & pt -> head , & pt -> sector );
353
+ lba_to_chs (start + size - 1 , & pt -> end_cyl , & pt -> end_head , & pt -> end_sector );
354
+ put_unaligned_le32 (relative , & pt -> start4 );
355
+ put_unaligned_le32 (size , & pt -> size4 );
356
+ }
357
+
358
+ int write_mbr_partitions (struct blk_desc * dev ,
359
+ struct disk_partition * p , int count , unsigned int disksig )
360
+ {
361
+ ALLOC_CACHE_ALIGN_BUFFER (unsigned char , buffer , dev -> blksz );
362
+ lbaint_t ext_part_start = 0 , ext_part_size = 0 , ext_part_sect = 0 ;
363
+ dos_partition_t * pt ;
364
+ int i ;
365
+
366
+ memset (buffer , 0 , dev -> blksz );
367
+ buffer [DOS_PART_MAGIC_OFFSET ] = 0x55 ;
368
+ buffer [DOS_PART_MAGIC_OFFSET + 1 ] = 0xaa ;
369
+ put_unaligned_le32 (disksig , & buffer [DOS_PART_DISKSIG_OFFSET ]);
370
+ pt = (dos_partition_t * ) (buffer + DOS_PART_TBL_OFFSET );
371
+
372
+ /* create all primary partitions */
373
+ for (i = 0 ; i < 4 && i < count ; i ++ , pt ++ ) {
374
+ mbr_fill_pt_entry (pt , p [i ].start , p [i ].start , p [i ].size ,
375
+ p [i ].sys_ind , p [i ].bootable );
376
+ if (is_extended (p [i ].sys_ind )) {
377
+ ext_part_start = p [i ].start ;
378
+ ext_part_size = p [i ].size ;
379
+ ext_part_sect = p [i ].start ;
380
+ }
381
+ }
382
+
383
+ if (i < count && !ext_part_start ) {
384
+ printf ("%s: extended partition is needed for more than 4 partitions\n" ,
385
+ __func__ );
386
+ return -1 ;
387
+ }
388
+
389
+ /* write MBR */
390
+ if (blk_dwrite (dev , 0 , 1 , buffer ) != 1 ) {
391
+ printf ("%s: failed writing 'MBR' (1 blks at 0x0)\n" ,
392
+ __func__ );
393
+ return -1 ;
394
+ }
395
+
396
+ /* create extended volumes */
397
+ for (; i < count ; i ++ ) {
398
+ lbaint_t next_ebr = 0 ;
399
+
400
+ memset (buffer , 0 , dev -> blksz );
401
+ buffer [DOS_PART_MAGIC_OFFSET ] = 0x55 ;
402
+ buffer [DOS_PART_MAGIC_OFFSET + 1 ] = 0xaa ;
403
+ pt = (dos_partition_t * ) (buffer + DOS_PART_TBL_OFFSET );
404
+
405
+ mbr_fill_pt_entry (pt , p [i ].start , p [i ].start - ext_part_sect ,
406
+ p [i ].size , p [i ].sys_ind , p [i ].bootable );
407
+
408
+ if (i + 1 < count ) {
409
+ pt ++ ;
410
+ next_ebr = p [i ].start + p [i ].size ;
411
+ mbr_fill_pt_entry (pt , next_ebr ,
412
+ next_ebr - ext_part_start ,
413
+ p [i + 1 ].start + p [i + 1 ].size - next_ebr ,
414
+ DOS_PART_TYPE_EXTENDED , 0 );
415
+ }
416
+
417
+ /* write EBR */
418
+ if (blk_dwrite (dev , ext_part_sect , 1 , buffer ) != 1 ) {
419
+ printf ("%s: failed writing 'EBR' (1 blks at 0x%lx)\n" ,
420
+ __func__ , ext_part_sect );
421
+ return -1 ;
422
+ }
423
+ ext_part_sect = next_ebr ;
424
+ }
425
+
426
+ return 0 ;
427
+ }
428
+
429
+ int layout_mbr_partitions (struct disk_partition * p , int count ,
430
+ lbaint_t total_sectors )
431
+ {
432
+ struct disk_partition * ext = NULL ;
433
+ int i , j ;
434
+ lbaint_t ext_vol_start ;
435
+
436
+ /* calculate primary partitions start and size if needed */
437
+ if (!p [0 ].start )
438
+ p [0 ].start = DOS_PART_DEFAULT_GAP ;
439
+ for (i = 0 ; i < 4 && i < count ; i ++ ) {
440
+ if (!p [i ].start )
441
+ p [i ].start = p [i - 1 ].start + p [i - 1 ].size ;
442
+ if (!p [i ].size ) {
443
+ lbaint_t end = total_sectors ;
444
+ lbaint_t allocated = 0 ;
445
+
446
+ for (j = i + 1 ; j < 4 && j < count ; j ++ ) {
447
+ if (p [j ].start ) {
448
+ end = p [j ].start ;
449
+ break ;
450
+ }
451
+ allocated += p [j ].size ;
452
+ }
453
+ p [i ].size = end - allocated - p [i ].start ;
454
+ }
455
+ if (p [i ].sys_ind == 0x05 )
456
+ ext = & p [i ];
457
+ }
458
+
459
+ if (i >= 4 && !ext ) {
460
+ printf ("%s: extended partition is needed for more than 4 partitions\n" ,
461
+ __func__ );
462
+ return -1 ;
463
+ }
464
+
465
+ /* calculate extended volumes start and size if needed */
466
+ ext_vol_start = ext -> start ;
467
+ for (i = 4 ; i < count ; i ++ ) {
468
+ if (!p [i ].start )
469
+ p [i ].start = ext_vol_start + DOS_PART_DEFAULT_GAP ;
470
+ if (!p [i ].size ) {
471
+ lbaint_t end = ext -> start + ext -> size ;
472
+ lbaint_t allocated = 0 ;
473
+
474
+ for (j = i + 1 ; j < count ; j ++ ) {
475
+ if (p [j ].start ) {
476
+ end = p [j ].start - DOS_PART_DEFAULT_GAP ;
477
+ break ;
478
+ }
479
+ allocated += p [j ].size + DOS_PART_DEFAULT_GAP ;
480
+ }
481
+ p [i ].size = end - allocated - p [i ].start ;
482
+ }
483
+ ext_vol_start = p [i ].start + p [i ].size ;
484
+ }
485
+
486
+ return 0 ;
487
+ }
488
+ #endif
489
+
323
490
int write_mbr_sector (struct blk_desc * dev_desc , void * buf )
324
491
{
325
492
if (is_valid_dos_buf (buf ))
0 commit comments