FreeBSD Bugzilla – Attachment 201423 Details for
Bug 235206
[loader] add patch to fix starting with a damaged GPT scheme under legacy BIOS
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch to add an automatic GPT recovery feature to gptzfsboot
patch-zgptrecover_stand_i386_zfsboot_zfsboot.c.patch (text/plain), 3.88 KB, created by
Emrion
on 2019-01-26 20:49:10 UTC
(
hide
)
Description:
Patch to add an automatic GPT recovery feature to gptzfsboot
Filename:
MIME Type:
Creator:
Emrion
Created:
2019-01-26 20:49:10 UTC
Size:
3.88 KB
patch
obsolete
>--- zfsboot.c.ori 2019-01-26 14:04:23.570240000 +0100 >+++ zfsboot.c 2019-01-26 20:45:26.031322000 +0100 >@@ -23,6 +23,7 @@ > #include <sys/diskmbr.h> > #ifdef GPT > #include <sys/gpt.h> >+#include "crc32.h" > #endif > #include <sys/reboot.h> > #include <sys/queue.h> >@@ -529,11 +530,97 @@ > return (size * DEV_BSIZE); > } > >+#ifdef GPT >+static int >+zgptread(struct dsk *dskp, uint64_t lba, struct gpt_hdr *hdr) >+{ >+ /* Most of this code comes from gpt.c */ >+ >+ /* Don't want to include "gpt.h" just for MAXTBLENTS */ >+ const uint32_t maxtbents = 128; >+ >+ /* Extract and verify the header */ >+ char* secbuf = dmadat->secbuf; >+ uint32_t crc; >+ if (drvread(dskp, secbuf, lba, 1)) return (-1); >+ bcopy(secbuf, hdr, sizeof(*hdr)); >+ if (bcmp(hdr->hdr_sig, GPT_HDR_SIG, sizeof(hdr->hdr_sig)) != 0 || >+ hdr->hdr_lba_self != lba || hdr->hdr_revision < 0x00010000 || >+ hdr->hdr_entsz < sizeof(struct gpt_ent) || >+ hdr->hdr_entries > maxtbents || DEV_BSIZE % hdr->hdr_entsz != 0) >+ return (-1); >+ >+ crc = hdr->hdr_crc_self; >+ hdr->hdr_crc_self = 0; >+ if (crc32(hdr, hdr->hdr_size) != crc) return (-1); >+ hdr->hdr_crc_self = crc; >+ >+ /* Check the partition table */ >+ char *table = malloc(hdr->hdr_entries * hdr->hdr_entsz); >+ if (!table) return (-1); >+ int n_sect = DEV_BSIZE / hdr->hdr_entsz; >+ n_sect = hdr->hdr_entries / n_sect; >+ for (int i = 0; i < n_sect; i++) { >+ if (drvread(dskp, secbuf, hdr->hdr_lba_table + i, 1)) { >+ free(table); >+ return (-1); >+ } >+ bcopy(secbuf, table + i * DEV_BSIZE, DEV_BSIZE); >+ } >+ if (crc32(table, hdr->hdr_entries * hdr->hdr_entsz) != hdr->hdr_crc_table) { >+ free(table); >+ return (-1); >+ } >+ free(table); >+ return (0); >+} >+ >+static int >+zgpt_recover(struct dsk *dskp, struct gpt_hdr *hdr_prim, >+ const struct gpt_hdr *hdr_back) >+{ >+ printf("%s: trying to recover GPT...\n", BOOTPROG); >+ char* secbuf = dmadat->secbuf; >+ const uint64_t head_prim_lba = 1; >+ const uint64_t table_prim_lba = 2; >+ >+ /* Copy partition table backup -> primary */ >+ int n_sect = DEV_BSIZE / hdr_back->hdr_entsz; >+ n_sect = hdr_back->hdr_entries / n_sect; >+ for (int i = 0; i < n_sect; i++) { >+ if (drvread(dskp, secbuf, hdr_back->hdr_lba_table + i, 1)) >+ goto zrecover_failed; >+ if (drvwrite(dskp, secbuf, table_prim_lba + i, 1)) >+ goto zrecover_failed; >+ } >+ >+ /* Set GPT primary header with backup header */ >+ *hdr_prim = *hdr_back; >+ hdr_prim->hdr_crc_self = 0; >+ hdr_prim->hdr_lba_self = head_prim_lba; >+ hdr_prim->hdr_lba_alt = hdr_back->hdr_lba_self; >+ hdr_prim->hdr_lba_table = table_prim_lba; >+ hdr_prim->hdr_crc_self = crc32(hdr_prim, hdr_prim->hdr_size); >+ bzero(secbuf, DEV_BSIZE); >+ bcopy(hdr_prim, secbuf, hdr_prim->hdr_size); >+ if (drvwrite(dskp, secbuf, hdr_prim->hdr_lba_self, 1)) >+ goto zrecover_failed; >+ >+ printf("%s: GPT recovering -> SUCCESS\n", BOOTPROG); >+ return (0); >+ >+zrecover_failed: >+ printf("%s: GPT recovering -> FAILED\n", BOOTPROG); >+ return (-1); >+} >+ >+#endif /* GPT */ >+ > static void > probe_drive(struct zfsdsk *zdsk) > { > #ifdef GPT >- struct gpt_hdr hdr; >+ struct gpt_hdr hdr, hdr_back; > struct gpt_ent *ent; > unsigned part, entries_per_sec; > daddr_t slba; >@@ -581,7 +668,15 @@ > /* > * First check for GPT. > */ >- if (drvread(&zdsk->dsk, sec, 1, 1)) { >+ const uint64_t head_prim_lba = 1; >+ if (zgptread(&zdsk->dsk, head_prim_lba, &hdr)) { >+ uint64_t altlba = drvsize(&zdsk->dsk); >+ if (altlba > 0 && !zgptread(&zdsk->dsk, altlba-1, &hdr_back)) { >+ if (zgpt_recover(&zdsk->dsk, &hdr, &hdr_back)) >+ goto trymbr; >+ } else goto trymbr; >+ } >+/* if (drvread(&zdsk->dsk, sec, 1, 1)) { > return; > } > memcpy(&hdr, sec, sizeof(hdr)); >@@ -589,7 +684,7 @@ > hdr.hdr_lba_self != 1 || hdr.hdr_revision < 0x00010000 || > hdr.hdr_entsz < sizeof(*ent) || DEV_BSIZE % hdr.hdr_entsz != 0) { > goto trymbr; >- } >+ }*/ > > /* > * Probe all GPT partitions for the presence of ZFS pools. We
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 235206
:
201403
| 201423