View | Details | Raw Unified | Return to bug 235206 | Differences between
and this patch

Collapse All | Expand All

(-)zfsboot.c (-3 / +98 lines)
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

Return to bug 235206