|
Lines 23-28
Link Here
|
| 23 |
#include <sys/diskmbr.h> |
23 |
#include <sys/diskmbr.h> |
| 24 |
#ifdef GPT |
24 |
#ifdef GPT |
| 25 |
#include <sys/gpt.h> |
25 |
#include <sys/gpt.h> |
|
|
26 |
#include "crc32.h" |
| 26 |
#endif |
27 |
#endif |
| 27 |
#include <sys/reboot.h> |
28 |
#include <sys/reboot.h> |
| 28 |
#include <sys/queue.h> |
29 |
#include <sys/queue.h> |
|
Lines 529-539
Link Here
|
| 529 |
return (size * DEV_BSIZE); |
530 |
return (size * DEV_BSIZE); |
| 530 |
} |
531 |
} |
| 531 |
|
532 |
|
|
|
533 |
#ifdef GPT |
| 534 |
static int |
| 535 |
zgptread(struct dsk *dskp, uint64_t lba, struct gpt_hdr *hdr) |
| 536 |
{ |
| 537 |
/* Most of this code comes from gpt.c */ |
| 538 |
|
| 539 |
/* Don't want to include "gpt.h" just for MAXTBLENTS */ |
| 540 |
const uint32_t maxtbents = 128; |
| 541 |
|
| 542 |
/* Extract and verify the header */ |
| 543 |
char* secbuf = dmadat->secbuf; |
| 544 |
uint32_t crc; |
| 545 |
if (drvread(dskp, secbuf, lba, 1)) return (-1); |
| 546 |
bcopy(secbuf, hdr, sizeof(*hdr)); |
| 547 |
if (bcmp(hdr->hdr_sig, GPT_HDR_SIG, sizeof(hdr->hdr_sig)) != 0 || |
| 548 |
hdr->hdr_lba_self != lba || hdr->hdr_revision < 0x00010000 || |
| 549 |
hdr->hdr_entsz < sizeof(struct gpt_ent) || |
| 550 |
hdr->hdr_entries > maxtbents || DEV_BSIZE % hdr->hdr_entsz != 0) |
| 551 |
return (-1); |
| 552 |
|
| 553 |
crc = hdr->hdr_crc_self; |
| 554 |
hdr->hdr_crc_self = 0; |
| 555 |
if (crc32(hdr, hdr->hdr_size) != crc) return (-1); |
| 556 |
hdr->hdr_crc_self = crc; |
| 557 |
|
| 558 |
/* Check the partition table */ |
| 559 |
char *table = malloc(hdr->hdr_entries * hdr->hdr_entsz); |
| 560 |
if (!table) return (-1); |
| 561 |
int n_sect = DEV_BSIZE / hdr->hdr_entsz; |
| 562 |
n_sect = hdr->hdr_entries / n_sect; |
| 563 |
for (int i = 0; i < n_sect; i++) { |
| 564 |
if (drvread(dskp, secbuf, hdr->hdr_lba_table + i, 1)) { |
| 565 |
free(table); |
| 566 |
return (-1); |
| 567 |
} |
| 568 |
bcopy(secbuf, table + i * DEV_BSIZE, DEV_BSIZE); |
| 569 |
} |
| 570 |
if (crc32(table, hdr->hdr_entries * hdr->hdr_entsz) != hdr->hdr_crc_table) { |
| 571 |
free(table); |
| 572 |
return (-1); |
| 573 |
} |
| 574 |
free(table); |
| 575 |
return (0); |
| 576 |
} |
| 577 |
|
| 578 |
static int |
| 579 |
zgpt_recover(struct dsk *dskp, struct gpt_hdr *hdr_prim, |
| 580 |
const struct gpt_hdr *hdr_back) |
| 581 |
{ |
| 582 |
printf("%s: trying to recover GPT...\n", BOOTPROG); |
| 583 |
char* secbuf = dmadat->secbuf; |
| 584 |
const uint64_t head_prim_lba = 1; |
| 585 |
const uint64_t table_prim_lba = 2; |
| 586 |
|
| 587 |
/* Copy partition table backup -> primary */ |
| 588 |
int n_sect = DEV_BSIZE / hdr_back->hdr_entsz; |
| 589 |
n_sect = hdr_back->hdr_entries / n_sect; |
| 590 |
for (int i = 0; i < n_sect; i++) { |
| 591 |
if (drvread(dskp, secbuf, hdr_back->hdr_lba_table + i, 1)) |
| 592 |
goto zrecover_failed; |
| 593 |
if (drvwrite(dskp, secbuf, table_prim_lba + i, 1)) |
| 594 |
goto zrecover_failed; |
| 595 |
} |
| 596 |
|
| 597 |
/* Set GPT primary header with backup header */ |
| 598 |
*hdr_prim = *hdr_back; |
| 599 |
hdr_prim->hdr_crc_self = 0; |
| 600 |
hdr_prim->hdr_lba_self = head_prim_lba; |
| 601 |
hdr_prim->hdr_lba_alt = hdr_back->hdr_lba_self; |
| 602 |
hdr_prim->hdr_lba_table = table_prim_lba; |
| 603 |
hdr_prim->hdr_crc_self = crc32(hdr_prim, hdr_prim->hdr_size); |
| 604 |
bzero(secbuf, DEV_BSIZE); |
| 605 |
bcopy(hdr_prim, secbuf, hdr_prim->hdr_size); |
| 606 |
if (drvwrite(dskp, secbuf, hdr_prim->hdr_lba_self, 1)) |
| 607 |
goto zrecover_failed; |
| 608 |
|
| 609 |
printf("%s: GPT recovering -> SUCCESS\n", BOOTPROG); |
| 610 |
return (0); |
| 611 |
|
| 612 |
zrecover_failed: |
| 613 |
printf("%s: GPT recovering -> FAILED\n", BOOTPROG); |
| 614 |
return (-1); |
| 615 |
} |
| 616 |
|
| 617 |
#endif /* GPT */ |
| 618 |
|
| 532 |
static void |
619 |
static void |
| 533 |
probe_drive(struct zfsdsk *zdsk) |
620 |
probe_drive(struct zfsdsk *zdsk) |
| 534 |
{ |
621 |
{ |
| 535 |
#ifdef GPT |
622 |
#ifdef GPT |
| 536 |
struct gpt_hdr hdr; |
623 |
struct gpt_hdr hdr, hdr_back; |
| 537 |
struct gpt_ent *ent; |
624 |
struct gpt_ent *ent; |
| 538 |
unsigned part, entries_per_sec; |
625 |
unsigned part, entries_per_sec; |
| 539 |
daddr_t slba; |
626 |
daddr_t slba; |
|
Lines 581-587
Link Here
|
| 581 |
/* |
668 |
/* |
| 582 |
* First check for GPT. |
669 |
* First check for GPT. |
| 583 |
*/ |
670 |
*/ |
| 584 |
if (drvread(&zdsk->dsk, sec, 1, 1)) { |
671 |
const uint64_t head_prim_lba = 1; |
|
|
672 |
if (zgptread(&zdsk->dsk, head_prim_lba, &hdr)) { |
| 673 |
uint64_t altlba = drvsize(&zdsk->dsk); |
| 674 |
if (altlba > 0 && !zgptread(&zdsk->dsk, altlba-1, &hdr_back)) { |
| 675 |
if (zgpt_recover(&zdsk->dsk, &hdr, &hdr_back)) |
| 676 |
goto trymbr; |
| 677 |
} else goto trymbr; |
| 678 |
} |
| 679 |
/* if (drvread(&zdsk->dsk, sec, 1, 1)) { |
| 585 |
return; |
680 |
return; |
| 586 |
} |
681 |
} |
| 587 |
memcpy(&hdr, sec, sizeof(hdr)); |
682 |
memcpy(&hdr, sec, sizeof(hdr)); |
|
Lines 589-595
Link Here
|
| 589 |
hdr.hdr_lba_self != 1 || hdr.hdr_revision < 0x00010000 || |
684 |
hdr.hdr_lba_self != 1 || hdr.hdr_revision < 0x00010000 || |
| 590 |
hdr.hdr_entsz < sizeof(*ent) || DEV_BSIZE % hdr.hdr_entsz != 0) { |
685 |
hdr.hdr_entsz < sizeof(*ent) || DEV_BSIZE % hdr.hdr_entsz != 0) { |
| 591 |
goto trymbr; |
686 |
goto trymbr; |
| 592 |
} |
687 |
}*/ |
| 593 |
|
688 |
|
| 594 |
/* |
689 |
/* |
| 595 |
* Probe all GPT partitions for the presence of ZFS pools. We |
690 |
* Probe all GPT partitions for the presence of ZFS pools. We |