"Das U-Boot" Source Tree
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

disk: dos: add code for creating MBR partition layout

Add a code for creating and writing MBR partition layout. The code generates
similar layout of EBRs (Exteneded Block Records) and logical volumes as
Linux's fdisk utility.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>

authored by

Marek Szyprowski and committed by
Tom Rini
20bd5ac6 cb571f91

+174
+167
disk/part_dos.c
··· 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))
+2
disk/part_dos.h
··· 19 19 #define DOS_PART_TYPE_EXTENDED_LBA 0x0F 20 20 #define DOS_PART_TYPE_EXTENDED_LINUX 0x85 21 21 22 + #define DOS_PART_DEFAULT_GAP 2048 23 + 22 24 typedef struct dos_partition { 23 25 unsigned char boot_ind; /* 0x80 - active */ 24 26 unsigned char head; /* starting head */
+5
include/part.h
··· 474 474 */ 475 475 int write_mbr_sector(struct blk_desc *dev_desc, void *buf); 476 476 477 + int write_mbr_partitions(struct blk_desc *dev, 478 + struct disk_partition *p, int count, unsigned int disksig); 479 + int layout_mbr_partitions(struct disk_partition *p, int count, 480 + lbaint_t total_sectors); 481 + 477 482 #endif 478 483 479 484