void dos_init(struct fdisk_context *cxt) { int i; cxt->disklabel = FDISK_DISKLABEL_DOS; partitions = 4; ext_index = 0; extended_offset = 0; for (i = 0; i < 4; i++) { struct pte *pe = &ptes[i]; pe->part_table = pt_offset(cxt->firstsector, i); pe->ext_pointer = NULL; pe->offset = 0; pe->sectorbuffer = cxt->firstsector; pe->changed = 0; } warn_geometry(cxt); warn_limits(cxt); warn_alignment(cxt); }
void dos_add_partition(struct fdisk_context *cxt, int n, int sys) { char mesg[256]; /* 48 does not suffice in Japanese */ int i, read = 0; struct partition *p = ptes[n].part_table; struct partition *q = ptes[ext_index].part_table; sector_t start, stop = 0, limit, temp, first[partitions], last[partitions]; if (p && p->sys_ind) { printf(_("Partition %d is already defined. Delete " "it before re-adding it.\n"), n + 1); return; } fill_bounds(first, last); if (n < 4) { start = sector_offset; if (display_in_cyl_units || !cxt->total_sectors) limit = cxt->geom.heads * cxt->geom.sectors * cxt->geom.cylinders - 1; else limit = cxt->total_sectors - 1; if (limit > UINT_MAX) limit = UINT_MAX; if (extended_offset) { first[ext_index] = extended_offset; last[ext_index] = get_start_sect(q) + get_nr_sects(q) - 1; } } else { start = extended_offset + sector_offset; limit = get_start_sect(q) + get_nr_sects(q) - 1; } if (display_in_cyl_units) for (i = 0; i < partitions; i++) first[i] = (cround(first[i]) - 1) * units_per_sector; snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR)); do { sector_t dflt, aligned; temp = start; dflt = start = get_unused_start(n, start, first, last); /* the default sector should be aligned and unused */ do { aligned = align_lba_in_range(cxt, dflt, dflt, limit); dflt = get_unused_start(n, aligned, first, last); } while (dflt != aligned && dflt > aligned && dflt < limit); if (dflt >= limit) dflt = start; if (start > limit) break; if (start >= temp+units_per_sector && read) { printf(_("Sector %llu is already allocated\n"), temp); temp = start; read = 0; } if (!read && start == temp) { sector_t i = start; start = read_int(cxt, cround(i), cround(dflt), cround(limit), 0, mesg); if (display_in_cyl_units) { start = (start - 1) * units_per_sector; if (start < i) start = i; } read = 1; } } while (start != temp || !read); if (n > 4) { /* NOT for fifth partition */ struct pte *pe = &ptes[n]; pe->offset = start - sector_offset; if (pe->offset == extended_offset) { /* must be corrected */ pe->offset++; if (sector_offset == 1) start++; } } for (i = 0; i < partitions; i++) { struct pte *pe = &ptes[i]; if (start < pe->offset && limit >= pe->offset) limit = pe->offset - 1; if (start < first[i] && limit >= first[i]) limit = first[i] - 1; } if (start > limit) { printf(_("No free sectors available\n")); if (n > 4) partitions--; return; } if (cround(start) == cround(limit)) { stop = limit; } else { int is_suffix_used = 0; snprintf(mesg, sizeof(mesg), _("Last %1$s, +%2$s or +size{K,M,G}"), str_units(SINGULAR), str_units(PLURAL)); stop = read_int_with_suffix(cxt, cround(start), cround(limit), cround(limit), cround(start), mesg, &is_suffix_used); if (display_in_cyl_units) { stop = stop * units_per_sector - 1; if (stop >limit) stop = limit; } if (is_suffix_used && alignment_required) { /* the last sector has not been exactly requested (but * defined by +size{K,M,G} convention), so be smart * and align the end of the partition. The next * partition will start at phy.block boundary. */ stop = align_lba_in_range(cxt, stop, start, limit) - 1; if (stop > limit) stop = limit; } } set_partition(cxt, n, 0, start, stop, sys); if (n > 4) set_partition(cxt, n - 1, 1, ptes[n].offset, stop, EXTENDED); if (IS_EXTENDED (sys)) { struct pte *pe4 = &ptes[4]; struct pte *pen = &ptes[n]; ext_index = n; pen->ext_pointer = p; pe4->offset = extended_offset = start; pe4->sectorbuffer = xcalloc(1, cxt->sector_size); pe4->part_table = pt_offset(pe4->sectorbuffer, 0); pe4->ext_pointer = pe4->part_table + 1; pe4->changed = 1; partitions = 5; } }
static void read_extended(struct fdisk_context *cxt, int ext) { int i; struct pte *pex; struct partition *p, *q; ext_index = ext; pex = &ptes[ext]; pex->ext_pointer = pex->part_table; p = pex->part_table; if (!get_start_sect(p)) { fprintf(stderr, _("Bad offset in primary extended partition\n")); return; } while (IS_EXTENDED (p->sys_ind)) { struct pte *pe = &ptes[partitions]; if (partitions >= MAXIMUM_PARTS) { /* This is not a Linux restriction, but this program uses arrays of size MAXIMUM_PARTS. Do not try to `improve' this test. */ struct pte *pre = &ptes[partitions-1]; fprintf(stderr, _("Warning: omitting partitions after #%d.\n" "They will be deleted " "if you save this partition table.\n"), partitions); clear_partition(pre->ext_pointer); pre->changed = 1; return; } read_pte(cxt, partitions, extended_offset + get_start_sect(p)); if (!extended_offset) extended_offset = get_start_sect(p); q = p = pt_offset(pe->sectorbuffer, 0); for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) { if (IS_EXTENDED (p->sys_ind)) { if (pe->ext_pointer) fprintf(stderr, _("Warning: extra link " "pointer in partition table" " %d\n"), partitions + 1); else pe->ext_pointer = p; } else if (p->sys_ind) { if (pe->part_table) fprintf(stderr, _("Warning: ignoring extra " "data in partition table" " %d\n"), partitions + 1); else pe->part_table = p; } } /* very strange code here... */ if (!pe->part_table) { if (q != pe->ext_pointer) pe->part_table = q; else pe->part_table = q + 1; } if (!pe->ext_pointer) { if (q != pe->part_table) pe->ext_pointer = q; else pe->ext_pointer = q + 1; } p = pe->ext_pointer; partitions++; } /* remove empty links */ remove: for (i = 4; i < partitions; i++) { struct pte *pe = &ptes[i]; if (!get_nr_sects(pe->part_table) && (partitions > 5 || ptes[4].part_table->sys_ind)) { printf(_("omitting empty partition (%d)\n"), i+1); dos_delete_partition(i); goto remove; /* numbering changed */ } } }
void pagetable_walk_64(const maddr_t & cr3, const vaddr_t & vaddr, maddr_t & maddr, vaddr_t * page_end) { // cr3 has the pml4 physical address between bits 51 and 12 // each page entry contain the next physical address between the same bits static const uint64_t addr_mask = 0x000FFFFFFFFFF000ULL; maddr_t pml4_entry; maddr_t pdpt_base; maddr_t pdpt_entry; maddr_t pd_base; maddr_t pd_entry; maddr_t pt_base; maddr_t pt_entry; maddr_t page; /* While this could technically be valid under x86 architecture, it is * certainly invalid under a sensible Xen setup, and implies a failure to * parse a {P,V}CPU correctly. */ if ( ! cr3 ) throw pagefault(vaddr, cr3, 5); memory.read64((cr3 & addr_mask) + pm4l_offset(vaddr), pml4_entry); // PDPT present? if ( ! present(pml4_entry) ) throw pagefault(vaddr, cr3, 4); pdpt_base = pml4_entry & addr_mask; // Page Size bit set? (512G superpage) if ( page_size(pml4_entry) ) { maddr = offset_512G(pdpt_base, vaddr); if ( page_end ) *page_end = roundup_512G(vaddr); return; } memory.read64(pdpt_base + pdpt_offset(vaddr), pdpt_entry); // PD present? if ( ! present(pdpt_entry) ) throw pagefault(vaddr, cr3, 3); pd_base = pdpt_entry & addr_mask; // Page Size bit set? (1G superpage) if ( page_size(pdpt_entry) ) { maddr = offset_1G(pd_base, vaddr); if ( page_end ) *page_end = roundup_1G(vaddr); return; } memory.read64(pd_base + pd_offset(vaddr), pd_entry); // PT present? if ( ! present(pd_entry) ) throw pagefault(vaddr, cr3, 2); pt_base = pd_entry & addr_mask; // Page Size bit set? (2M superpage) if ( page_size(pd_entry) ) { maddr = offset_2M(pt_base, vaddr); if ( page_end ) *page_end = roundup_2M(vaddr); return; } memory.read64(pt_base + pt_offset(vaddr), pt_entry); // Page present? if ( ! present(pt_entry) ) throw pagefault(vaddr, cr3, 1); page = pt_entry & addr_mask; maddr = offset_4K(page, vaddr); if ( page_end ) *page_end = roundup_4K(vaddr); }
static int check_gpt_label(void) { struct partition *first = pt_offset(MBRbuffer, 0); struct pte pe; uint32_t crc; /* LBA 0 contains the legacy MBR */ if (!valid_part_table_flag(MBRbuffer) || first->sys_ind != LEGACY_GPT_TYPE ) { current_label_type = 0; return 0; } /* LBA 1 contains the GPT header */ read_pte(&pe, 1); gpt_hdr = (void *)pe.sectorbuffer; if (gpt_hdr->magic != SWAP_LE64(GPT_MAGIC)) { current_label_type = 0; return 0; } if (!global_crc32_table) { global_crc32_table = crc32_filltable(NULL, 0); } crc = SWAP_LE32(gpt_hdr->hdr_crc32); gpt_hdr->hdr_crc32 = 0; if (gpt_crc32(gpt_hdr, SWAP_LE32(gpt_hdr->hdr_size)) != crc) { /* FIXME: read the backup table */ puts("\nwarning: GPT header CRC is invalid\n"); } n_parts = SWAP_LE32(gpt_hdr->n_parts); part_entry_len = SWAP_LE32(gpt_hdr->part_entry_len); if (n_parts > GPT_MAX_PARTS || part_entry_len > GPT_MAX_PART_ENTRY_LEN || SWAP_LE32(gpt_hdr->hdr_size) > sector_size ) { puts("\nwarning: unable to parse GPT disklabel\n"); current_label_type = 0; return 0; } part_array_len = n_parts * part_entry_len; part_array = xmalloc(part_array_len); seek_sector(SWAP_LE64(gpt_hdr->first_part_lba)); if (full_read(dev_fd, part_array, part_array_len) != part_array_len) { fdisk_fatal(unable_to_read); } if (gpt_crc32(part_array, part_array_len) != gpt_hdr->part_array_crc32) { /* FIXME: read the backup table */ puts("\nwarning: GPT array CRC is invalid\n"); } puts("Found valid GPT with protective MBR; using GPT\n"); current_label_type = LABEL_GPT; return 1; }