int main(int argc, char *argv[]) { // basic assertions assert(sizeof(gpt_partition_t) == 128); assert(sizeof(gpt_header_t) == 512); // require root privilege if (geteuid() != 0) { printf("Must run as root user.\n"); exit(4); } // get disk size uint64_t size = get_disk_size("/dev/sdb"); // create partitions entry gpt_partition_t partitions[2]; createPartitions(&partitions[0]); // create the header gpt_header_t gpt; initGPTHeader(&gpt, size, &partitions[0]); // save in disk partition_write("/dev/sdb", &gpt, &partitions[0]); return 0; }
ULONGLONG EndlessISO::GetExtractedSize(const CString & image, const BOOL isInstallerImage) { auto extractor = SevenZip::SevenZipExtractor(pImpl->sevenZip, image.GetString()); extractor.SetCompressionFormat(SevenZip::CompressionFormat::SquashFS); auto n = extractor.GetNumberOfItems(); IFFALSE_RETURN_VALUE(n == 1, "not exactly 1 item in squashfs image", 0); UINT32 i = 0; auto name = extractor.GetItemsNames()[i]; IFFALSE_RETURN_VALUE(name == ENDLESS_IMG_FILE_NAME, "squashfs item has wrong name", 0); struct ptable pt; auto gotPt = extractor.ExtractBytes(i, &pt, sizeof(pt)); IFFALSE_RETURN_VALUE(gotPt, "Failed to read partition table", 0); if (!is_eos_gpt_valid(&pt, isInstallerImage)) { return 0; } return get_disk_size(&pt); }
// compression_type: an element of bled_compression_type uint64_t get_eos_archive_disk_image_size(const char *filepath, int compression_type, BOOL isInstallerImage) { int64_t bytes_read = 0; int64_t result = 0; struct ptable pt; const int size = sizeof(pt); // should be 2048 if (NULL == filepath) return 0; if (compression_type == BLED_COMPRESSION_NONE) { FILE *file = NULL; errno_t err = fopen_s(&file, filepath, "rb"); if (err == 0) { // The 'size' and 'count' arguments are "backwards" because this // function returns the number of items read; by making the item // size 1 we get the number of bytes bytes_read = fread((void *)&pt, 1, size, file); fclose(file); } else { uprintf("Error opening %s: %d", filepath, err); } } else { bled_init(_uprintf, NULL, NULL); bytes_read = bled_uncompress_to_buffer(filepath, (char*)&pt, size, compression_type); bled_exit(); } if (bytes_read < size) { // not enough bytes read return 0; } if (!is_eos_gpt_valid(&pt, isInstallerImage)) { return 0; } return get_disk_size(&pt); }
/* * Gets a dmgt_disk_t for the given disk dm_descriptor_t. * * Results: * * 1. Success: error is set to 0 and a dmgt_disk_t is returned * * 2. Failure: error is set to -1 and NULL is returned */ static dmgt_disk_t * get_disk(dm_descriptor_t disk, int *error) { dmgt_disk_t *dp; *error = 0; dp = (dmgt_disk_t *)calloc(1, sizeof (dmgt_disk_t)); if (dp == NULL) { handle_error("out of memory"); *error = -1; } else { /* Get name */ dp->name = get_device_name(disk, error); if (!*error) { /* Get aliases */ dp->aliases = get_disk_aliases(disk, dp->name, error); if (!*error) { /* Get media */ dm_descriptor_t *media = dm_get_associated_descriptors(disk, DM_MEDIA, error); if (*error != 0 || media == NULL || *media == NULL) { handle_error( "could not get media from disk %s", dp->name); *error = -1; } else { /* Get size */ get_disk_size(media[0], dp->name, &(dp->size), &(dp->blocksize), error); if (!*error) { /* Get free slices */ dp->slices = get_disk_usable_slices( media[0], dp->name, dp->blocksize, &(dp->in_use), error); } dm_free_descriptors(media); } } } } if (*error) { /* Normalize error */ *error = -1; if (dp != NULL) { dmgt_free_disk(dp); dp = NULL; } } return (dp); }
disk_info_t *create_disk(const char *device_name, disk_info_t **new_disk_info) { disk_info_t *follow_disk_info; u32 major, minor; u64 size_in_kilobytes = 0; int len; char buf[128], *vendor, *model, *ptr; partition_info_t *new_partition_info, **follow_partition_list; if(!new_disk_info) return NULL; *new_disk_info = NULL; // initial value. vendor = NULL; model = NULL; if(!device_name || !is_disk_name(device_name)) return NULL; if(!initial_disk_data(&follow_disk_info)) return NULL; len = strlen(device_name); follow_disk_info->device = (char *)malloc(len+1); if (!follow_disk_info->device){ free_disk_data(follow_disk_info); return NULL; } strcpy(follow_disk_info->device, device_name); if(!get_disk_major_minor(device_name, &major, &minor)){ free_disk_data(follow_disk_info); return NULL; } follow_disk_info->major = major; follow_disk_info->minor = minor; if(!get_disk_size(device_name, &size_in_kilobytes)){ free_disk_data(follow_disk_info); return NULL; } follow_disk_info->size_in_kilobytes = size_in_kilobytes; if(!strncmp(device_name, "sd", 2)){ if(!get_usb_root_port_by_device(device_name, buf, sizeof(buf))){ free_disk_data(follow_disk_info); return NULL; } len = strlen(buf); if(len > 0){ int port_num = get_usb_root_port_number(buf); if (port_num < 0) port_num = 0; follow_disk_info->port_root = port_num; } // start get vendor. if(!get_disk_vendor(device_name, buf, sizeof(buf))){ free_disk_data(follow_disk_info); return NULL; } len = strlen(buf); if(len > 0){ vendor = (char *)malloc(len+1); if(!vendor){ free_disk_data(follow_disk_info); return NULL; } strcpy(vendor, buf); strntrim(vendor); sanity_name(vendor); follow_disk_info->vendor = vendor; } // start get model. if(get_disk_model(device_name, buf, sizeof(buf)) == NULL){ free_disk_data(follow_disk_info); return NULL; } len = strlen(buf); if(len > 0){ model = (char *)malloc(len+1); if(!model){ free_disk_data(follow_disk_info); return NULL; } strcpy(model, buf); strntrim(model); sanity_name(model); follow_disk_info->model = model; } // get USB's tag memset(buf, 0, sizeof(buf)); len = 0; ptr = buf; if(vendor){ len += strlen(vendor); strcpy(ptr, vendor); ptr += len; } if(model){ if(len > 0){ ++len; // Add a space between vendor and model. strcpy(ptr, " "); ++ptr; } len += strlen(model); strcpy(ptr, model); ptr += len; } if(len > 0){ follow_disk_info->tag = (char *)malloc(len+1); if(!follow_disk_info->tag){ free_disk_data(follow_disk_info); return NULL; } strcpy(follow_disk_info->tag, buf); } else{ len = strlen(DEFAULT_USB_TAG); follow_disk_info->tag = (char *)malloc(len+1); if(!follow_disk_info->tag){ free_disk_data(follow_disk_info); return NULL; } strcpy(follow_disk_info->tag, DEFAULT_USB_TAG); } follow_partition_list = &(follow_disk_info->partitions); while(*follow_partition_list) follow_partition_list = &((*follow_partition_list)->next); new_partition_info = create_partition(device_name, follow_partition_list); if(new_partition_info){ new_partition_info->disk = follow_disk_info; ++(follow_disk_info->partition_number); ++(follow_disk_info->mounted_number); } } if(follow_disk_info->partition_number == 0) get_disk_partitionnumber(device_name, &(follow_disk_info->partition_number), &(follow_disk_info->mounted_number)); *new_disk_info = follow_disk_info; return *new_disk_info; }
disk_info_t *create_disk(const char *device_name, disk_info_t **new_disk_info){ disk_info_t *follow_disk_info; u32 major, minor; u64 size_in_kilobytes = 0; int len; char usb_node[32], port_path[8]; char buf[64], *port, *vendor = NULL, *model = NULL, *ptr; partition_info_t *new_partition_info, **follow_partition_list; if(new_disk_info == NULL){ usb_dbg("Bad input!!\n"); return NULL; } *new_disk_info = NULL; // initial value. if(device_name == NULL || !is_disk_name(device_name)) return NULL; if(initial_disk_data(&follow_disk_info) == NULL){ usb_dbg("No memory!!(follow_disk_info)\n"); return NULL; } len = strlen(device_name); follow_disk_info->device = (char *)malloc(len+1); if(follow_disk_info->device == NULL){ usb_dbg("No memory!!(follow_disk_info->device)\n"); free_disk_data(&follow_disk_info); return NULL; } strcpy(follow_disk_info->device, device_name); follow_disk_info->device[len] = 0; if(!get_disk_major_minor(device_name, &major, &minor)){ usb_dbg("Fail to get disk's major and minor: %s.\n", device_name); free_disk_data(&follow_disk_info); return NULL; } follow_disk_info->major = major; follow_disk_info->minor = minor; if(!get_disk_size(device_name, &size_in_kilobytes)){ usb_dbg("Fail to get disk's size_in_kilobytes: %s.\n", device_name); free_disk_data(&follow_disk_info); return NULL; } follow_disk_info->size_in_kilobytes = size_in_kilobytes; if(!strncmp(device_name, "sd", 2)){ // Get USB node. if(get_usb_node_by_device(device_name, usb_node, 32) == NULL){ usb_dbg("(%s): Fail to get usb node.\n", device_name); free_disk_data(&follow_disk_info); return NULL; } if(get_path_by_node(usb_node, port_path, 8) == NULL){ usb_dbg("(%s): Fail to get usb path.\n", usb_node); free_disk_data(&follow_disk_info); return NULL; } // Get USB port. if(get_usb_port_by_string(usb_node, buf, 64) == NULL){ usb_dbg("Fail to get usb port: %s.\n", usb_node); free_disk_data(&follow_disk_info); return NULL; } len = strlen(buf); if(len > 0){ port = (char *)malloc(8); if(port == NULL){ usb_dbg("No memory!!(port)\n"); free_disk_data(&follow_disk_info); return NULL; } memset(port, 0, 8); strncpy(port, port_path, 8); follow_disk_info->port = port; } // start get vendor. if(get_disk_vendor(device_name, buf, 64) == NULL){ usb_dbg("Fail to get disk's vendor: %s.\n", device_name); free_disk_data(&follow_disk_info); return NULL; } len = strlen(buf); if(len > 0){ vendor = (char *)malloc(len+1); if(vendor == NULL){ usb_dbg("No memory!!(vendor)\n"); free_disk_data(&follow_disk_info); return NULL; } strncpy(vendor, buf, len); vendor[len] = 0; strntrim(vendor); follow_disk_info->vendor = vendor; } // start get model. if(get_disk_model(device_name, buf, 64) == NULL){ usb_dbg("Fail to get disk's model: %s.\n", device_name); free_disk_data(&follow_disk_info); return NULL; } len = strlen(buf); if(len > 0){ model = (char *)malloc(len+1); if(model == NULL){ usb_dbg("No memory!!(model)\n"); free_disk_data(&follow_disk_info); return NULL; } strncpy(model, buf, len); model[len] = 0; strntrim(model); follow_disk_info->model = model; } // get USB's tag memset(buf, 0, 64); len = 0; ptr = buf; if(vendor != NULL){ len += strlen(vendor); strcpy(ptr, vendor); ptr += len; } if(model != NULL){ if(len > 0){ ++len; // Add a space between vendor and model. strcpy(ptr, " "); ++ptr; } len += strlen(model); strcpy(ptr, model); ptr += len; } if(len > 0){ follow_disk_info->tag = (char *)malloc(len+1); if(follow_disk_info->tag == NULL){ usb_dbg("No memory!!(follow_disk_info->tag)\n"); free_disk_data(&follow_disk_info); return NULL; } strcpy(follow_disk_info->tag, buf); follow_disk_info->tag[len] = 0; } else{ len = strlen(DEFAULT_USB_TAG); follow_disk_info->tag = (char *)malloc(len+1); if(follow_disk_info->tag == NULL){ usb_dbg("No memory!!(follow_disk_info->tag)\n"); free_disk_data(&follow_disk_info); return NULL; } strcpy(follow_disk_info->tag, DEFAULT_USB_TAG); follow_disk_info->tag[len] = 0; } follow_partition_list = &(follow_disk_info->partitions); while(*follow_partition_list != NULL) follow_partition_list = &((*follow_partition_list)->next); new_partition_info = create_partition(device_name, follow_partition_list); if(new_partition_info != NULL){ new_partition_info->disk = follow_disk_info; ++(follow_disk_info->partition_number); ++(follow_disk_info->mounted_number); if(!strcmp(new_partition_info->device, follow_disk_info->device)) new_partition_info->size_in_kilobytes = follow_disk_info->size_in_kilobytes-4; } } if(!strcmp(follow_disk_info->device, follow_disk_info->partitions->device)) get_disk_partitionnumber(device_name, &(follow_disk_info->partition_number), &(follow_disk_info->mounted_number)); *new_disk_info = follow_disk_info; return *new_disk_info; }
static UINTN analyze(int optind, int argc, char **argv) { UINTN action; UINTN i, k, count_active, detected_parttype; CHARN *fsname; UINT64 min_start_lba, max_end_lba, block_count, last_disk_lba; UINTN status; BOOLEAN have_esp; new_mbr_part_count = 0; block_count = get_disk_size(); last_disk_lba = block_count - 1; if (block_count == 0) { error("can't retrieve disk size"); return 1; } // determine correct MBR types for GPT partitions if (gpt_part_count == 0) { Print(L"Status: No GPT partitions defined, nothing to sync.\n"); return 1; } have_esp = FALSE; for (i = 0; i < gpt_part_count; i++) { gpt_parts[i].mbr_type = gpt_parts[i].gpt_parttype->mbr_type; if (gpt_parts[i].gpt_parttype->kind == GPT_KIND_BASIC_DATA) { // Basic Data: need to look at data in the partition status = detect_mbrtype_fs(gpt_parts[i].start_lba, &detected_parttype, &fsname); if (detected_parttype) gpt_parts[i].mbr_type = detected_parttype; else gpt_parts[i].mbr_type = 0x0b; // fallback: FAT32 } else if (gpt_parts[i].mbr_type == 0xef) { // EFI System Partition: GNU parted can put this on any partition, // need to detect file systems status = detect_mbrtype_fs(gpt_parts[i].start_lba, &detected_parttype, &fsname); if (!have_esp && (detected_parttype == 0x01 || detected_parttype == 0x0e || detected_parttype == 0x0c)) ; // seems to be a legitimate ESP, don't change else if (detected_parttype) gpt_parts[i].mbr_type = detected_parttype; else if (have_esp) // make sure there's no more than one ESP per disk gpt_parts[i].mbr_type = 0x83; // fallback: Linux } // NOTE: mbr_type may still be 0 if content detection fails for exotic GPT types or file systems if (gpt_parts[i].mbr_type == 0xef) have_esp = TRUE; } // generate the new table new_mbr_part_count = 1; count_active = 0; if (! create_empty_mbr) { if (optind < argc) { for (i = optind; i < argc; i++) { char *separator, csep = 0; BOOLEAN active = FALSE; UINT8 force_type = 0; separator = strchr (argv[i], '+'); if (! separator) separator = strchr (argv[i], '-'); if (separator) { csep = *separator; *separator = 0; } int part = atoi(argv[i]); if (part < 1 || part > gpt_part_count) { error("invalid argument '%s', partition number must be between 1-%d !", argv[i], gpt_part_count); return 1; } part--; // 0 base partition number if (csep == '+') { active = TRUE; count_active ++; if (count_active == 2) { error("only one partition can be active !"); return 1; } } if (separator && *(separator + 1)) { char *str_type = separator + 1; if(xtoi (str_type, &force_type) != 0) { error("invalid hex type: %s !", str_type); return 1; } } // Check that a partition has not already enter for (k = 1; k < new_mbr_part_count; k++) { if (new_mbr_parts[k].start_lba == gpt_parts[part].start_lba || new_mbr_parts[k].end_lba == gpt_parts[part].end_lba ) { error("you already add partition %d !",part+1); return 1; } } add_gpt_partition_to_mbr(new_mbr_part_count, part, force_type, active); new_mbr_part_count++; } } else { // add other GPT partitions until the table is full // TODO: in the future, prioritize partitions by kind if (gpt_parts[0].mbr_type == 0xef) i = 1; else i = 0; for (; i < gpt_part_count && new_mbr_part_count < 4; i++) { add_gpt_partition_to_mbr(new_mbr_part_count, i, 0, FALSE); new_mbr_part_count++; } } } // get the first and last used lba if ( new_mbr_part_count == 1) { // Only one EFI Protective partition min_start_lba = max_end_lba = last_disk_lba + 1; // Take whole disk } else { min_start_lba = new_mbr_parts[1].start_lba; max_end_lba = new_mbr_parts[1].end_lba; for (k = 2; k < new_mbr_part_count; k++) { if (max_end_lba < new_mbr_parts[k].end_lba) max_end_lba = new_mbr_parts[k].end_lba; if (min_start_lba > new_mbr_parts[k].start_lba) min_start_lba = new_mbr_parts[k].start_lba; } } // Reserved last part if not used if (new_mbr_part_count < 4 && max_end_lba < last_disk_lba && fill_mbr) { new_mbr_parts[new_mbr_part_count].index = new_mbr_part_count; new_mbr_parts[new_mbr_part_count].start_lba = max_end_lba + 1; new_mbr_parts[new_mbr_part_count].end_lba = last_disk_lba; new_mbr_parts[new_mbr_part_count].mbr_type = 0xee; // another protective area new_mbr_parts[new_mbr_part_count].active = FALSE; new_mbr_part_count ++; } // first entry: EFI Protective new_mbr_parts[0].index = 0; new_mbr_parts[0].start_lba = 1; new_mbr_parts[0].end_lba = min_start_lba - 1; new_mbr_parts[0].mbr_type = 0xee; action = ACTION_NOP; // Check if we need to rewrite MBR for (i = 0; i < 4; i ++) { if (new_mbr_parts[i].index != mbr_parts[i].index || new_mbr_parts[i].start_lba != mbr_parts[i].start_lba || new_mbr_parts[i].end_lba != mbr_parts[i].end_lba || new_mbr_parts[i].mbr_type != mbr_parts[i].mbr_type || new_mbr_parts[i].active != mbr_parts[i].active) { action = ACTION_REWRITE; break; } } if (action == ACTION_NOP) { Print(L"Status: Tables are synchronized, no need to sync.\n"); return 1; } else { Print(L"Status: MBR table must be updated.\n"); } // dump table Print(L"\nProposed new MBR partition table:\n"); Print(L" # A Start LBA End LBA Type\n"); for (i = 0; i < new_mbr_part_count; i++) { Print(L" %d %s %12lld %12lld %02x %s\n", new_mbr_parts[i].index + 1, new_mbr_parts[i].active ? STR("*") : STR(" "), new_mbr_parts[i].start_lba, new_mbr_parts[i].end_lba, new_mbr_parts[i].mbr_type, mbr_parttype_name(new_mbr_parts[i].mbr_type)); } return 0; }
int main(int argc, char** argv) { if (argc < 3) { usage(); } unsigned i = 1; const char* path = argv[i++]; // Output path const char* command = argv[i++]; // Command size_t length = 0; size_t offset = 0; size_t slice_size = DEFAULT_SLICE_SIZE; size_t disk_size = 0; bool should_unlink = true; uint32_t flags = 0; while (i < argc) { if (!strcmp(argv[i], "--slice") && i + 1 < argc) { if (parse_size(argv[++i], &slice_size) < 0) { return -1; } if (!slice_size || slice_size % blobfs::kBlobfsBlockSize || slice_size % minfs::kMinfsBlockSize) { fprintf(stderr, "Invalid slice size - must be a multiple of %u and %u\n", blobfs::kBlobfsBlockSize, minfs::kMinfsBlockSize); return -1; } } else if (!strcmp(argv[i], "--offset") && i + 1 < argc) { should_unlink = false; if (parse_size(argv[++i], &offset) < 0) { return -1; } } else if (!strcmp(argv[i], "--length") && i + 1 < argc) { if (parse_size(argv[++i], &length) < 0) { return -1; } } else if (!strcmp(argv[i], "--compress")) { if (!strcmp(argv[++i], "lz4")) { flags |= fvm::kSparseFlagLz4; } else { fprintf(stderr, "Invalid compression type\n"); return -1; } } else if (!strcmp(argv[i], "--disk")) { if (parse_size(argv[++i], &disk_size) < 0) { return -1; } } else { break; } ++i; } if (!strcmp(command, "create") && should_unlink) { unlink(path); } // If length was not specified, use remainder of file after offset if (length == 0) { length = get_disk_size(path, offset); } if (!strcmp(command, "create")) { // If length was specified, an offset was not, we were asked to create a // file, and the file does not exist, truncate it to the given length. if (length != 0 && offset == 0) { fbl::unique_fd fd(open(path, O_CREAT | O_EXCL | O_WRONLY, 0644)); if (fd) { ftruncate(fd.get(), length); } } fbl::unique_ptr<FvmContainer> fvmContainer; if (FvmContainer::Create(path, slice_size, offset, length, &fvmContainer) != ZX_OK) { return -1; } if (add_partitions(fvmContainer.get(), argc - i, argv + i) < 0) { return -1; } if (fvmContainer->Commit() != ZX_OK) { return -1; } } else if (!strcmp(command, "add")) { fbl::unique_ptr<FvmContainer> fvmContainer(new FvmContainer(path, slice_size, offset, length)); if (add_partitions(fvmContainer.get(), argc - i, argv + i) < 0) { return -1; } if (fvmContainer->Commit() != ZX_OK) { return -1; } } else if (!strcmp(command, "extend")) { if (length == 0 || offset > 0) { usage(); } size_t disk_size = get_disk_size(path, 0); if (length <= disk_size) { fprintf(stderr, "Cannot extend to a value %zu less than current size %zu\n", length, disk_size); usage(); } fbl::unique_ptr<FvmContainer> fvmContainer(new FvmContainer(path, slice_size, offset, disk_size)); if (fvmContainer->Extend(length) != ZX_OK) { return -1; } } else if (!strcmp(command, "sparse")) { if (offset) { fprintf(stderr, "Invalid sparse flags\n"); return -1; } fbl::unique_ptr<SparseContainer> sparseContainer; if (SparseContainer::Create(path, slice_size, flags, &sparseContainer) != ZX_OK) { return -1; } if (add_partitions(sparseContainer.get(), argc - i, argv + i) < 0) { return -1; } if (sparseContainer->Commit() != ZX_OK) { return -1; } } else if (!strcmp(command, "verify")) { fbl::unique_ptr<Container> containerData; if (Container::Create(path, offset, length, flags, &containerData) != ZX_OK) { return -1; } if (containerData->Verify() != ZX_OK) { return -1; } } else if (!strcmp(command, "decompress")) { if (argc - i != 2) { usage(); return -1; } char* input_type = argv[i]; char* input_path = argv[i + 1]; if (strcmp(input_type, "--sparse")) { usage(); return -1; } SparseContainer compressedContainer(input_path, slice_size, flags); if (compressedContainer.Decompress(path) != ZX_OK) { return -1; } SparseContainer sparseContainer(path, slice_size, flags); if (sparseContainer.Verify() != ZX_OK) { return -1; } } else if (!strcmp(command, "size")) { SparseContainer sparseContainer(path, slice_size, flags); if (disk_size == 0) { printf("%" PRIu64 "\n", sparseContainer.CalculateDiskSize()); } else if (sparseContainer.CheckDiskSize(disk_size) != ZX_OK) { fprintf(stderr, "Sparse container will not fit in target disk size\n"); return -1; } } else if (!strcmp(command, "pave")) { char* input_type = argv[i]; char* input_path = argv[i + 1]; if (strcmp(input_type, "--sparse")) { fprintf(stderr, "pave command only accepts --sparse input option\n"); usage(); return -1; } SparseContainer sparseData(input_path, slice_size, flags); if (sparseData.Pave(path, offset, length) != ZX_OK) { return -1; } } else { usage(); } return 0; }