static int gpt_check_hdr_crc(const struct disk_info * const diskinfo, struct disk_gpt_header **_gh) { struct disk_gpt_header *gh = *_gh; uint64_t lba_alt; uint32_t hold_crc32; hold_crc32 = gh->chksum; gh->chksum = 0; if (!valid_crc(hold_crc32, (const uint8_t *)gh, gh->hdr_size)) { warn("Primary GPT header checksum invalid."); /* retry with backup */ lba_alt = gh->lba_alt; free(gh); if (!(gh = *_gh = disk_read_sectors(diskinfo, lba_alt, 1))) { error("Couldn't read backup GPT header."); return -1; } hold_crc32 = gh->chksum; gh->chksum = 0; if (!valid_crc(hold_crc32, (const uint8_t *)gh, gh->hdr_size)) { error("Secondary GPT header checksum invalid."); return -1; } } /* restore old checksum */ gh->chksum = hold_crc32; return 0; }
bool hdlc16::valid_frame( void ) { size_t bitcnt = bitbuf.size(); //this can be extended to work for odd HDLC bitframes later if( bitcnt % 8 != 0 ) { return false; } if( bitcnt < 32 ) { return false; } if( last_8_bits != HDLC_FRAMER ) { return false; } if( !valid_crc() ) { return false; } return true; }
static struct disk_gpt_part_entry *try_gpt_list(const struct disk_info *di, const struct disk_gpt_header *gpth, int alt) { int pri = gpth->lba_cur < gpth->lba_alt; const char *desc = alt ? "alternative" : "main"; struct disk_gpt_part_entry *gptl; char errbuf[64]; uint64_t gpt_lsiz; /* size of GPT partition list in bytes */ uint64_t gpt_lcnt; /* size of GPT partition in sectors */ uint64_t gpt_loff; /* offset to GPT partition list in sectors */ gpt_lsiz = (uint64_t)gpth->part_size * gpth->part_count; gpt_lcnt = (gpt_lsiz + di->bps - 1) / di->bps; if (!alt) { /* prefer header value for partition table if not asking for alternative */ gpt_loff = gpth->lba_table; } else { /* try to read alternative, we have to calculate its position */ if (!pri) gpt_loff = gpth->lba_alt + 1; else gpt_loff = gpth->lba_alt - gpt_lcnt; } gptl = disk_read_sectors(di, gpt_loff, gpt_lcnt); if (!gptl) { sprintf(errbuf, "Unable to read %s GPT partition list.", desc); try_gpt_we(errbuf, alt); return NULL; } if (!valid_crc(gpth->table_chksum, (const uint8_t *)gptl, gpt_lsiz)) { sprintf(errbuf, "Invalid checksum of %s GPT partition list.", desc); try_gpt_we(errbuf, alt); free(gptl); return NULL; } return gptl; }
/* pi_begin() - validate and and get proper iterator for a disk described by di */ struct part_iter *pi_begin(const struct disk_info *di, int flags) { int gptprot, ret = -1; struct part_iter *iter; struct disk_dos_mbr *mbr = NULL; struct disk_gpt_header *gpth = NULL; struct disk_gpt_part_entry *gptl = NULL; /* Preallocate iterator */ if (!(iter = pi_alloc())) goto bail; /* Read MBR */ if (!(mbr = disk_read_sectors(di, 0, 1))) { error("Couldn't read the first disk sector."); goto bail; } /* Check for MBR magic */ if (mbr->sig != disk_mbr_sig_magic) { warn("No MBR magic, treating disk as raw."); /* looks like RAW */ ret = pi_ctor(iter, di, flags); goto bail; } /* Check for GPT protective MBR */ gptprot = 0; for (size_t i = 0; i < 4; i++) gptprot |= (mbr->table[i].ostype == 0xEE); if (gptprot && !(flags & PIF_PREFMBR)) { if (!(gpth = disk_read_sectors(di, 1, 1))) { error("Couldn't read potential GPT header."); goto bail; } } if (gpth && gpth->rev.uint32 == 0x00010000 && !memcmp(gpth->sig, disk_gpt_sig_magic, sizeof gpth->sig)) { /* looks like GPT v1.0 */ uint64_t gpt_loff; /* offset to GPT partition list in sectors */ uint64_t gpt_lsiz; /* size of GPT partition list in bytes */ uint64_t gpt_lcnt; /* size of GPT partition in sectors */ #ifdef DEBUG dprintf("Looks like a GPT v1.0 disk.\n"); disk_gpt_header_dump(gpth); #endif /* Verify checksum, fallback to backup, then bail if invalid */ if (gpt_check_hdr_crc(di, &gpth)) goto bail; gpt_loff = gpth->lba_table; gpt_lsiz = (uint64_t)gpth->part_size * gpth->part_count; gpt_lcnt = (gpt_lsiz + di->bps - 1) / di->bps; /* * disk_read_sectors allows reading of max 255 sectors, so we use * it as a sanity check base. EFI doesn't specify max (AFAIK). * Apart from that, some extensive sanity checks. */ if (!(flags & PIF_RELAX) && ( !gpt_loff || !gpt_lsiz || gpt_lcnt > 255u || gpth->lba_first_usable > gpth->lba_last_usable || !sane(gpt_loff, gpt_lcnt) || gpt_loff + gpt_lcnt > gpth->lba_first_usable || !sane(gpth->lba_last_usable, gpt_lcnt) || gpth->lba_last_usable + gpt_lcnt >= gpth->lba_alt || gpth->lba_alt >= di->lbacnt || gpth->part_size < sizeof *gptl)) { error("Invalid GPT header's values."); goto bail; } if (!(gptl = disk_read_sectors(di, gpt_loff, gpt_lcnt))) { error("Couldn't read GPT partition list."); goto bail; } /* Check array checksum(s). */ if (!valid_crc(gpth->table_chksum, (const uint8_t *)gptl, (unsigned int)gpt_lsiz)) { warn("Checksum of the main GPT partition list is invalid, trying backup."); free(gptl); /* secondary array directly precedes secondary header */ if (!(gptl = disk_read_sectors(di, gpth->lba_alt - gpt_lcnt, gpt_lcnt))) { error("Couldn't read backup GPT partition list."); goto bail; } if (!valid_crc(gpth->table_chksum, (const uint8_t *)gptl, gpt_lsiz)) { error("Checksum of the backup GPT partition list is invalid, giving up."); goto bail; } } /* looks like GPT */ ret = pi_gpt_ctor(iter, di, flags, gpth, gptl); } else { /* looks like MBR */ ret = pi_dos_ctor(iter, di, flags, mbr); } bail: if (ret < 0) free(iter); free(mbr); free(gpth); free(gptl); return iter; }