diff options
Diffstat (limited to 'cgpt')
-rw-r--r-- | cgpt/cgpt.c | 58 | ||||
-rw-r--r-- | cgpt/cgpt.h | 17 | ||||
-rw-r--r-- | cgpt/cgpt_add.c | 108 | ||||
-rw-r--r-- | cgpt/cgpt_boot.c | 9 | ||||
-rw-r--r-- | cgpt/cgpt_common.c | 403 | ||||
-rw-r--r-- | cgpt/cgpt_create.c | 34 | ||||
-rw-r--r-- | cgpt/cgpt_find.c | 83 | ||||
-rw-r--r-- | cgpt/cgpt_legacy.c | 7 | ||||
-rw-r--r-- | cgpt/cgpt_prioritize.c | 15 | ||||
-rw-r--r-- | cgpt/cgpt_repair.c | 6 | ||||
-rw-r--r-- | cgpt/cgpt_show.c | 155 | ||||
-rw-r--r-- | cgpt/cmd_create.c | 6 | ||||
-rw-r--r-- | cgpt/flash_ts.c | 423 | ||||
-rw-r--r-- | cgpt/flash_ts.h | 35 | ||||
-rw-r--r-- | cgpt/flash_ts_api.h | 25 | ||||
-rw-r--r-- | cgpt/flash_ts_drv.c | 72 |
16 files changed, 94 insertions, 1362 deletions
diff --git a/cgpt/cgpt.c b/cgpt/cgpt.c index ccf73184..38092006 100644 --- a/cgpt/cgpt.c +++ b/cgpt/cgpt.c @@ -52,45 +52,6 @@ void Usage(void) { printf("\nFor more detailed usage, use %s COMMAND -h\n\n", progname); } -static int is_pow2(size_t v) { - return v && (v & (v - 1)) == 0; -} - -static int parse_nand_option(const char *arg) { - int bytes_per_page, pages_per_block, fts_block_offset, fts_block_size; - - if ('=' != arg[0]) - return -1; - - arg++; - bytes_per_page = atoi(arg); - arg = strchr(arg, ','); - if (!arg) - return -1; - - arg++; - pages_per_block = atoi(arg); - arg = strchr(arg, ','); - if (!arg) - return -1; - - arg++; - fts_block_offset = atoi(arg); - arg = strchr(arg, ','); - if (!arg) - return -1; - - arg++; - fts_block_size = atoi(arg); - if (fts_block_size == 0 || !is_pow2(pages_per_block) || - !is_pow2(bytes_per_page) || bytes_per_page < 512) { - return -1; - } - EnableNandImage(bytes_per_page, pages_per_block, fts_block_offset, - fts_block_size); - return 0; -} - int main(int argc, char *argv[]) { int i; int match_count = 0; @@ -103,25 +64,6 @@ int main(int argc, char *argv[]) { else progname = argv[0]; - - for (i = 1; i < argc; ++i) { - if (0 == strncmp(argv[i], "-N", 2)) { - if (!parse_nand_option(argv[i] + 2)) { - int j; - - // Remove it form the list. - for (j = i; j < argc - 1; j++) - argv[j] = argv[j + 1]; - argc--; - break; - } - // Bad nand config. - printf("Nand option must fit: -N=<bytes_per_page>,<pages_per_block>," - "<block_offset_of_partition>,<block_size_of_partition>\n"); - return CGPT_FAILED; - } - } - if (argc < 2) { Usage(); return CGPT_FAILED; diff --git a/cgpt/cgpt.h b/cgpt/cgpt.h index bb3438a0..ff9e1064 100644 --- a/cgpt/cgpt.h +++ b/cgpt/cgpt.h @@ -13,7 +13,6 @@ #include "cgpt_endian.h" #include "cgptlib.h" #include "gpt.h" -#include "mtdlib.h" struct legacy_partition { uint8_t status; @@ -43,23 +42,11 @@ void PMBRToStr(struct pmbr *pmbr, char *str, unsigned int buflen); // Handle to the drive storing the GPT. struct drive { uint64_t size; /* total size (in bytes) */ - int is_mtd; GptData gpt; - MtdData mtd; struct pmbr pmbr; int fd; /* file descriptor */ }; -struct nand_layout { - int enabled; - int use_host_ioctl; /* Use ioctl() on /dev/fts to read/write. */ - int bytes_per_page, pages_per_block, fts_block_offset, fts_block_size; -}; - -/* Write a NAND/MTD image instead of GPT. */ -void EnableNandImage(int bytes_per_page, int pages_per_block, - int fts_block_offset, int fts_block_size); - // Opens a block device or file, loads raw GPT data from it. // 'mode' should be O_RDONLY or O_RDWR. // If 'drive_size' is 0, both the partitions and GPT structs reside on the same @@ -156,11 +143,9 @@ int ResolveType(const Guid *type, char *buf); int SupportedType(const char *name, Guid *type); void PrintTypes(void); void EntryDetails(GptEntry *entry, uint32_t index, int raw); -void MtdEntryDetails(MtdDiskPartition *entry, uint32_t index, int raw); uint32_t GetNumberOfEntries(const struct drive *drive); GptEntry *GetEntry(GptData *gpt, int secondary, uint32_t entry_index); -MtdDiskPartition *MtdGetEntry(MtdData *mtd, int secondary, uint32_t index); void SetPriority(struct drive *drive, int secondary, uint32_t entry_index, int priority); @@ -184,8 +169,6 @@ int IsSynonymous(const GptHeader* a, const GptHeader* b); int IsUnused(struct drive *drive, int secondary, uint32_t index); int IsKernel(struct drive *drive, int secondary, uint32_t index); -int LookupMtdTypeForGuid(const Guid *type); -const Guid *LookupGuidForMtdType(int type); // Optional. Applications that need this must provide an implementation. // diff --git a/cgpt/cgpt_add.c b/cgpt/cgpt_add.c index 9bbc3fb5..d6b3cabd 100644 --- a/cgpt/cgpt_add.c +++ b/cgpt/cgpt_add.c @@ -95,32 +95,6 @@ static int GptSetEntryAttributes(struct drive *drive, return 0; } -static int MtdSetEntryAttributes(struct drive *drive, - uint32_t index, - CgptAddParams *params) { - MtdDiskPartition *entry; - - entry = MtdGetEntry(&drive->mtd, PRIMARY, index); - if (params->set_begin) { - uint64_t start = params->begin * drive->mtd.sector_bytes; - memcpy(&entry->starting_offset, &start, sizeof(params->begin)); - } - if (params->set_size) { - uint64_t start; - uint64_t end; - MtdGetPartitionSize(entry, &start, NULL, NULL); - end = start + params->size * drive->mtd.sector_bytes - 1; - memcpy(&entry->ending_offset, &end, sizeof(end)); - } - if (params->set_type) - MtdSetEntryType(entry, LookupMtdTypeForGuid(¶ms->type_guid)); - if (params->label) { - strncpy(entry->label, params->label, sizeof(entry->label)); - } - - return 0; -} - // This is an internal helper function which assumes no NULL args are passed. // It sets the given attribute values for a single entry at the given index. static int SetEntryAttributes(struct drive *drive, @@ -153,26 +127,20 @@ static int SetEntryAttributes(struct drive *drive, } static int CgptCheckAddValidity(struct drive *drive) { - if (drive->is_mtd) { - if (drive->mtd.primary.crc32 != MtdHeaderCrc(&drive->mtd.primary)) { - Error("MTD header CRC is invalid\n"); - return -1; - } - } else { - int gpt_retval; - if (GPT_SUCCESS != (gpt_retval = GptSanityCheck(&drive->gpt))) { - Error("GptSanityCheck() returned %d: %s\n", - gpt_retval, GptError(gpt_retval)); - return -1; - } + int gpt_retval; + if (GPT_SUCCESS != (gpt_retval = GptSanityCheck(&drive->gpt))) { + Error("GptSanityCheck() returned %d: %s\n", + gpt_retval, GptError(gpt_retval)); + return -1; + } - if (((drive->gpt.valid_headers & MASK_BOTH) != MASK_BOTH) || - ((drive->gpt.valid_entries & MASK_BOTH) != MASK_BOTH)) { - Error("one of the GPT header/entries is invalid.\n" - "please run 'cgpt repair' before adding anything.\n"); - return -1; - } + if (((drive->gpt.valid_headers & MASK_BOTH) != MASK_BOTH) || + ((drive->gpt.valid_entries & MASK_BOTH) != MASK_BOTH)) { + Error("one of the GPT header/entries is invalid.\n" + "please run 'cgpt repair' before adding anything.\n"); + return -1; } + return 0; } @@ -264,10 +232,6 @@ int CgptGetPartitionDetails(CgptAddParams *params) { Error("either partition or unique_id must be specified\n"); goto bad; } - if (drive.is_mtd) { - Error("MTD partitions cannot be specified by unique_id\n"); - goto bad; - } for (index = 0; index < max_part; index++) { GptEntry *entry = GetEntry(&drive.gpt, PRIMARY, index); if (GuidEqual(&entry->unique, ¶ms->unique_guid)) { @@ -282,22 +246,13 @@ int CgptGetPartitionDetails(CgptAddParams *params) { } index = params->partition - 1; - if(drive.is_mtd) { - MtdDiskPartition *entry = MtdGetEntry(&drive.mtd, PRIMARY, index); - const Guid *guid = LookupGuidForMtdType(MtdGetEntryType(entry)); - memcpy(¶ms->type_guid, guid, sizeof(params->type_guid)); - memset(¶ms->unique_guid, 0, sizeof(params->unique_guid)); - MtdGetPartitionSizeInSectors(entry, ¶ms->begin, NULL, ¶ms->size); - params->raw_value = entry->flags; - } else { - // GPT-specific code - GptEntry *entry = GetEntry(&drive.gpt, PRIMARY, index); - params->begin = entry->starting_lba; - params->size = entry->ending_lba - entry->starting_lba + 1; - memcpy(¶ms->type_guid, &entry->type, sizeof(Guid)); - memcpy(¶ms->unique_guid, &entry->unique, sizeof(Guid)); - params->raw_value = entry->attrs.fields.gpt_att; - } + // GPT-specific code + GptEntry *entry = GetEntry(&drive.gpt, PRIMARY, index); + params->begin = entry->starting_lba; + params->size = entry->ending_lba - entry->starting_lba + 1; + memcpy(¶ms->type_guid, &entry->type, sizeof(Guid)); + memcpy(¶ms->unique_guid, &entry->unique, sizeof(Guid)); + params->raw_value = entry->attrs.fields.gpt_att; params->successful = GetSuccessful(&drive, PRIMARY, index); params->tries = GetTries(&drive, PRIMARY, index); @@ -338,22 +293,6 @@ static int GptAdd(struct drive *drive, CgptAddParams *params, uint32_t index) { return 0; } -static int MtdAdd(struct drive *drive, CgptAddParams *params, uint32_t index) { - MtdDiskPartition *entry, backup; - entry = MtdGetEntry(&drive->mtd, PRIMARY, index); - memcpy(&backup, entry, sizeof(backup)); - - if (SetEntryAttributes(drive, index, params) || - MtdSetEntryAttributes(drive, index, params)) { - memcpy(entry, &backup, sizeof(*entry)); - return -1; - } - - UpdateAllEntries(drive); - - return 0; -} - int CgptAdd(CgptAddParams *params) { struct drive drive; uint32_t index; @@ -373,13 +312,8 @@ int CgptAdd(CgptAddParams *params) { goto bad; } - if (drive.is_mtd) { - if (MtdAdd(&drive, params, index)) - goto bad; - } else { - if (GptAdd(&drive, params, index)) - goto bad; - } + if (GptAdd(&drive, params, index)) + goto bad; // Write it all out. return DriveClose(&drive, 1); diff --git a/cgpt/cgpt_boot.c b/cgpt/cgpt_boot.c index 928210b5..f4323962 100644 --- a/cgpt/cgpt_boot.c +++ b/cgpt/cgpt_boot.c @@ -79,15 +79,6 @@ int CgptBoot(CgptBootParams *params) { return CGPT_FAILED; } - if (drive.is_mtd) { - /* This command manipulates the legacy MBR sector present at the beginning - * of the GPT structures, and so doesn't apply to MTD drives. - */ - Error("'boot' command unsupported in MTD mode\n"); - retval = CGPT_FAILED; - goto done; - } - if (CGPT_OK != ReadPMBR(&drive)) { Error("Unable to read PMBR\n"); goto done; diff --git a/cgpt/cgpt_common.c b/cgpt/cgpt_common.c index 1e7b5ab4..1438dfb3 100644 --- a/cgpt/cgpt_common.c +++ b/cgpt/cgpt_common.c @@ -25,24 +25,11 @@ #include "cgpt.h" #include "cgptlib_internal.h" #include "crc32.h" -#include "flash_ts.h" -#include "flash_ts_api.h" #include "vboot_host.h" static const char kErrorTag[] = "ERROR"; static const char kWarningTag[] = "WARNING"; -struct nand_layout nand; - -void EnableNandImage(int bytes_per_page, int pages_per_block, - int fts_block_offset, int fts_block_size) { - nand.enabled = 1; - nand.bytes_per_page = bytes_per_page; - nand.pages_per_block = pages_per_block; - nand.fts_block_offset = fts_block_offset; - nand.fts_block_size = fts_block_size; -} - static void LogToStderr(const char *tag, const char *format, va_list ap) { fprintf(stderr, "%s: ", tag); vfprintf(stderr, format, ap); @@ -156,161 +143,6 @@ int Save(struct drive *drive, const uint8_t *buf, return CGPT_OK; } -static int get_hex_char_value(char ch) { - if (ch >= '0' && ch <= '9') { - return ch - '0'; - } - if (ch >= 'a' && ch <= 'f') { - return ch - 'a' + 10; - } - if (ch >= 'A' && ch <= 'F') { - return ch - 'A' + 10; - } - return -1; -} - -static int TryInitMtd(const char *dev) { - static int already_inited = 0; - if (already_inited) - return nand.use_host_ioctl; - - already_inited = 1; - - /* If we're running on the live system, we can just use /dev/fts and not - * actually need the specific parameters. This needs to be accessed via - * ioctl and not normal I/O. - */ - if (!strcmp(dev, FTS_DEVICE) && !access(FTS_DEVICE, R_OK | W_OK)) { - nand.enabled = 1; - nand.use_host_ioctl = 1; - return 1; - } - return 0; -} - -int FlashGet(const char *key, uint8_t *data, uint32_t *bufsz) { - char *hex = (char*)malloc(*bufsz * 2); - char *read; - uint32_t written = 0; - - if (nand.use_host_ioctl) { - struct flash_ts_io_req req; - strncpy(req.key, key, sizeof(req.key)); - int fd = open(FTS_DEVICE, O_RDWR); - if (fd < 0) - return -1; - if (ioctl(fd, FLASH_TS_IO_GET, &req)) - return -1; - strncpy(hex, req.val, *bufsz * 2); - close(fd); - } else { - flash_ts_get(key, hex, *bufsz * 2); - } - - /* Hex -> binary */ - for (read = hex; read < hex + *bufsz * 2 && *read != '\0'; read += 2) { - int c0, c1; - c0 = get_hex_char_value(read[0]); - c1 = get_hex_char_value(read[1]); - if (c0 < 0 || c1 < 0) { - free(hex); - return -1; - } - - data[written++] = (c0 << 4) + c1; - } - *bufsz = written; - free(hex); - return 0; -} - -int FlashSet(const char *key, const uint8_t *data, uint32_t bufsz) { - char *hex = (char*)malloc(bufsz * 2 + 1); - const char *hex_chars = "0123456789ABCDEF"; - int ret; - uint32_t i; - - /* Binary -> hex, we need some encoding because FTS only stores C strings */ - for (i = 0; i < bufsz; i++) { - hex[i * 2] = hex_chars[data[i] >> 4]; - hex[i * 2 + 1] = hex_chars[data[i] & 0xF]; - } - /* Buffer must be NUL-terminated. */ - hex[bufsz * 2] = '\0'; - if (nand.use_host_ioctl) { - struct flash_ts_io_req req; - strncpy(req.key, key, sizeof(req.key)); - strncpy(req.val, hex, sizeof(req.val)); - free(hex); - int fd = open(FTS_DEVICE, O_RDWR); - if (fd < 0) - return -1; - if (ioctl(fd, FLASH_TS_IO_SET, &req)) - return -1; - close(fd); - return 0; - } - ret = flash_ts_set(key, hex); - free(hex); - return ret; -} - -int MtdLoad(struct drive *drive, int sector_bytes) { - int ret; - uint32_t sz; - MtdData *mtd = &drive->mtd; - - mtd->sector_bytes = sector_bytes; - mtd->drive_sectors = drive->size / mtd->sector_bytes; - - if (!nand.use_host_ioctl) { - ret = flash_ts_init(mtd->fts_block_offset, - mtd->fts_block_size, - mtd->flash_page_bytes, - mtd->flash_block_bytes, - mtd->sector_bytes, /* Needed for Load() and Save() */ - drive); - if (ret) - return ret; - } - - memset(&mtd->primary, 0, sizeof(mtd->primary)); - sz = sizeof(mtd->primary); - ret = FlashGet(MTD_DRIVE_SIGNATURE, (uint8_t *)&mtd->primary, &sz); - if (ret) - return ret; - - /* Read less than expected */ - if (sz < MTD_DRIVE_V1_SIZE) - memset(&mtd->primary, 0, sizeof(mtd->primary)); - - if (nand.use_host_ioctl) { - /* If we are using /dev/fts, we can't stat() the size, so re-use - * our internal value to set it. - */ - drive->size = mtd->primary.last_offset + 1; - mtd->drive_sectors = drive->size / mtd->sector_bytes; - } - - mtd->current_kernel = -1; - mtd->current_priority = 0; - mtd->modified = 0; - return 0; -} - -int MtdSave(struct drive *drive) { - MtdData *mtd = &drive->mtd; - - if (!mtd->modified) - return 0; - - mtd->primary.crc32 = 0; - mtd->primary.crc32 = Crc32(&mtd->primary, MTD_DRIVE_V1_SIZE); - - return FlashSet(MTD_DRIVE_SIGNATURE, (uint8_t *)&mtd->primary, - sizeof(mtd->primary)); -} - static int GptLoad(struct drive *drive, uint32_t sector_bytes) { drive->gpt.sector_bytes = sector_bytes; if (drive->size % drive->gpt.sector_bytes) { @@ -446,7 +278,6 @@ static int ObtainDriveSize(int fd, uint64_t* size, uint32_t* sector_bytes) { int DriveOpen(const char *drive_path, struct drive *drive, int mode, uint64_t drive_size) { uint32_t sector_bytes; - int is_mtd = nand.enabled; require(drive_path); require(drive); @@ -455,47 +286,32 @@ int DriveOpen(const char *drive_path, struct drive *drive, int mode, memset(drive, 0, sizeof(struct drive)); drive->gpt.stored_on_device = GPT_STORED_ON_DEVICE; - if (TryInitMtd(drive_path)) { - is_mtd = 1; - sector_bytes = 512; /* bytes */ - } else { - drive->fd = open(drive_path, mode | O_LARGEFILE | O_NOFOLLOW); - if (drive->fd == -1) { - Error("Can't open %s: %s\n", drive_path, strerror(errno)); - return CGPT_FAILED; - } - - sector_bytes = 512; - uint64_t gpt_drive_size; - if (ObtainDriveSize(drive->fd, &gpt_drive_size, §or_bytes) != 0) { - Error("Can't get drive size and bytes per sector for %s: %s\n", - drive_path, strerror(errno)); - goto error_close; - } + drive->fd = open(drive_path, mode | O_LARGEFILE | O_NOFOLLOW); + if (drive->fd == -1) { + Error("Can't open %s: %s\n", drive_path, strerror(errno)); + return CGPT_FAILED; + } - drive->gpt.gpt_drive_sectors = gpt_drive_size / sector_bytes; - if (drive_size == 0) { - drive->size = gpt_drive_size; - drive->gpt.stored_on_device = GPT_STORED_ON_DEVICE; - } else { - drive->size = drive_size; - drive->gpt.stored_on_device = GPT_STORED_OFF_DEVICE; - } + sector_bytes = 512; + uint64_t gpt_drive_size; + if (ObtainDriveSize(drive->fd, &gpt_drive_size, §or_bytes) != 0) { + Error("Can't get drive size and bytes per sector for %s: %s\n", + drive_path, strerror(errno)); + goto error_close; } - drive->is_mtd = is_mtd; - - if (is_mtd) { - drive->mtd.fts_block_offset = nand.fts_block_offset; - drive->mtd.fts_block_size = nand.fts_block_size; - drive->mtd.flash_page_bytes = nand.bytes_per_page; - drive->mtd.flash_block_bytes = nand.pages_per_block * nand.bytes_per_page; - if (MtdLoad(drive, sector_bytes)) { - goto error_close; - } + + drive->gpt.gpt_drive_sectors = gpt_drive_size / sector_bytes; + if (drive_size == 0) { + drive->size = gpt_drive_size; + drive->gpt.stored_on_device = GPT_STORED_ON_DEVICE; } else { - if (GptLoad(drive, sector_bytes)) { - goto error_close; - } + drive->size = drive_size; + drive->gpt.stored_on_device = GPT_STORED_OFF_DEVICE; + } + + + if (GptLoad(drive, sector_bytes)) { + goto error_close; } // We just load the data. Caller must validate it. @@ -511,14 +327,8 @@ int DriveClose(struct drive *drive, int update_as_needed) { int errors = 0; if (update_as_needed) { - if (drive->is_mtd) { - if (MtdSave(drive)) { - errors++; - } - } else { - if (GptSave(drive)) { + if (GptSave(drive)) { errors++; - } } } @@ -816,44 +626,16 @@ const static struct { const Guid *type; char *name; char *description; - int mtd_type; } supported_types[] = { - {&guid_chromeos_firmware, "firmware", "ChromeOS firmware", - MTD_PARTITION_TYPE_CHROMEOS_FIRMWARE}, - {&guid_chromeos_kernel, "kernel", "ChromeOS kernel", - MTD_PARTITION_TYPE_CHROMEOS_KERNEL}, - {&guid_chromeos_rootfs, "rootfs", "ChromeOS rootfs", - MTD_PARTITION_TYPE_CHROMEOS_ROOTFS}, - {&guid_linux_data, "data", "Linux data", - MTD_PARTITION_TYPE_LINUX_DATA}, - {&guid_chromeos_reserved, "reserved", "ChromeOS reserved", - MTD_PARTITION_TYPE_CHROMEOS_RESERVED}, - {&guid_efi, "efi", "EFI System Partition", - MTD_PARTITION_TYPE_EFI}, - {&guid_unused, "unused", "Unused (nonexistent) partition", - MTD_PARTITION_TYPE_UNUSED}, + {&guid_chromeos_firmware, "firmware", "ChromeOS firmware"}, + {&guid_chromeos_kernel, "kernel", "ChromeOS kernel"}, + {&guid_chromeos_rootfs, "rootfs", "ChromeOS rootfs"}, + {&guid_linux_data, "data", "Linux data"}, + {&guid_chromeos_reserved, "reserved", "ChromeOS reserved"}, + {&guid_efi, "efi", "EFI System Partition"}, + {&guid_unused, "unused", "Unused (nonexistent) partition"}, }; -int LookupMtdTypeForGuid(const Guid *type) { - int i; - for (i = 0; i < ARRAY_COUNT(supported_types); ++i) { - if (!memcmp(type, supported_types[i].type, sizeof(Guid))) { - return supported_types[i].mtd_type; - } - } - return MTD_PARTITION_TYPE_OTHER; -} - -const Guid *LookupGuidForMtdType(int type) { - int i; - for (i = 0; i < ARRAY_COUNT(supported_types); ++i) { - if (supported_types[i].mtd_type == type) { - return supported_types[i].type; - } - } - return NULL; -} - /* Resolves human-readable GPT type. * Returns CGPT_OK if found. * Returns CGPT_FAILED if no known type found. */ @@ -899,9 +681,6 @@ static GptHeader* GetGptHeader(const GptData *gpt) { } uint32_t GetNumberOfEntries(const struct drive *drive) { - if (drive->is_mtd) - return MTD_MAX_PARTITIONS; - GptHeader *header = GetGptHeader(&drive->gpt); if (!header) return 0; @@ -933,130 +712,74 @@ GptEntry *GetEntry(GptData *gpt, int secondary, uint32_t entry_index) { return (GptEntry*)(&entries[stride * entry_index]); } -MtdDiskPartition* MtdGetEntry(MtdData *mtd, int secondary, uint32_t index) { - if (index >= MTD_MAX_PARTITIONS) - return NULL; - return &mtd->primary.partitions[index]; -} - void SetPriority(struct drive *drive, int secondary, uint32_t entry_index, int priority) { require(priority >= 0 && priority <= CGPT_ATTRIBUTE_MAX_PRIORITY); - if (drive->is_mtd) { - MtdDiskPartition *e = MtdGetEntry(&drive->mtd, secondary, entry_index); - MtdSetEntryPriority(e, priority); - } else { - GptEntry *entry; - entry = GetEntry(&drive->gpt, secondary, entry_index); - SetEntryPriority(entry, priority); - } + GptEntry *entry; + entry = GetEntry(&drive->gpt, secondary, entry_index); + SetEntryPriority(entry, priority); } int GetPriority(struct drive *drive, int secondary, uint32_t entry_index) { - if (drive->is_mtd) { - MtdDiskPartition *e = MtdGetEntry(&drive->mtd, secondary, entry_index); - return MtdGetEntryPriority(e); - } else { - GptEntry *entry; - entry = GetEntry(&drive->gpt, secondary, entry_index); - return GetEntryPriority(entry); - } + GptEntry *entry; + entry = GetEntry(&drive->gpt, secondary, entry_index); + return GetEntryPriority(entry); } void SetTries(struct drive *drive, int secondary, uint32_t entry_index, int tries) { require(tries >= 0 && tries <= CGPT_ATTRIBUTE_MAX_TRIES); - if (drive->is_mtd) { - MtdDiskPartition *e = MtdGetEntry(&drive->mtd, secondary, entry_index); - MtdSetEntryTries(e, tries); - } else { - GptEntry *entry; - entry = GetEntry(&drive->gpt, secondary, entry_index); - SetEntryTries(entry, tries); - } + GptEntry *entry; + entry = GetEntry(&drive->gpt, secondary, entry_index); + SetEntryTries(entry, tries); } int GetTries(struct drive *drive, int secondary, uint32_t entry_index) { - if (drive->is_mtd) { - MtdDiskPartition *e = MtdGetEntry(&drive->mtd, secondary, entry_index); - return MtdGetEntryTries(e); - } else { - GptEntry *entry; - entry = GetEntry(&drive->gpt, secondary, entry_index); - return GetEntryTries(entry); - } + GptEntry *entry; + entry = GetEntry(&drive->gpt, secondary, entry_index); + return GetEntryTries(entry); } void SetSuccessful(struct drive *drive, int secondary, uint32_t entry_index, int success) { require(success >= 0 && success <= CGPT_ATTRIBUTE_MAX_SUCCESSFUL); - if (drive->is_mtd) { - MtdDiskPartition *e = MtdGetEntry(&drive->mtd, secondary, entry_index); - MtdSetEntrySuccessful(e, success); - } else { - GptEntry *entry; - entry = GetEntry(&drive->gpt, secondary, entry_index); - SetEntrySuccessful(entry, success); - } + GptEntry *entry; + entry = GetEntry(&drive->gpt, secondary, entry_index); + SetEntrySuccessful(entry, success); } int GetSuccessful(struct drive *drive, int secondary, uint32_t entry_index) { - if (drive->is_mtd) { - MtdDiskPartition *e = MtdGetEntry(&drive->mtd, secondary, entry_index); - return MtdGetEntrySuccessful(e); - } else { - GptEntry *entry; - entry = GetEntry(&drive->gpt, secondary, entry_index); - return GetEntrySuccessful(entry); - } + GptEntry *entry; + entry = GetEntry(&drive->gpt, secondary, entry_index); + return GetEntrySuccessful(entry); } void SetRaw(struct drive *drive, int secondary, uint32_t entry_index, uint32_t raw) { - if (drive->is_mtd) { - MtdDiskPartition *e = MtdGetEntry(&drive->mtd, secondary, entry_index); - e->flags = raw; - } else { - GptEntry *entry; - entry = GetEntry(&drive->gpt, secondary, entry_index); - entry->attrs.fields.gpt_att = (uint16_t)raw; - } + GptEntry *entry; + entry = GetEntry(&drive->gpt, secondary, entry_index); + entry->attrs.fields.gpt_att = (uint16_t)raw; } void UpdateAllEntries(struct drive *drive) { - if (drive->is_mtd) { - drive->mtd.modified = 1; - drive->mtd.primary.crc32 = MtdHeaderCrc(&drive->mtd.primary); - } else { - RepairEntries(&drive->gpt, MASK_PRIMARY); - RepairHeader(&drive->gpt, MASK_PRIMARY); + RepairEntries(&drive->gpt, MASK_PRIMARY); + RepairHeader(&drive->gpt, MASK_PRIMARY); - drive->gpt.modified |= (GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1 | - GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2); - UpdateCrc(&drive->gpt); - } + drive->gpt.modified |= (GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1 | + GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2); + UpdateCrc(&drive->gpt); } int IsUnused(struct drive *drive, int secondary, uint32_t index) { - if (drive->is_mtd) { - MtdDiskPartition *e = MtdGetEntry(&drive->mtd, secondary, index); - return MtdGetEntryType(e) == MTD_PARTITION_TYPE_UNUSED; - } else { - GptEntry *entry; - entry = GetEntry(&drive->gpt, secondary, index); - return GuidIsZero(&entry->type); - } + GptEntry *entry; + entry = GetEntry(&drive->gpt, secondary, index); + return GuidIsZero(&entry->type); } int IsKernel(struct drive *drive, int secondary, uint32_t index) { - if (drive->is_mtd) { - MtdDiskPartition *e = MtdGetEntry(&drive->mtd, secondary, index); - return MtdGetEntryType(e) == MTD_PARTITION_TYPE_CHROMEOS_KERNEL; - } else { - GptEntry *entry; - entry = GetEntry(&drive->gpt, secondary, index); - return GuidEqual(&entry->type, &guid_chromeos_kernel); - } + GptEntry *entry; + entry = GetEntry(&drive->gpt, secondary, index); + return GuidEqual(&entry->type, &guid_chromeos_kernel); } diff --git a/cgpt/cgpt_create.c b/cgpt/cgpt_create.c index 18e2f51b..298e2ae5 100644 --- a/cgpt/cgpt_create.c +++ b/cgpt/cgpt_create.c @@ -88,31 +88,6 @@ static int GptCreate(struct drive *drive, CgptCreateParams *params) { return 0; } -static int MtdCreate(struct drive *drive, CgptCreateParams *params) { - MtdDiskLayout *h = &drive->mtd.primary; - memset(h, 0, sizeof(*h)); - drive->mtd.modified = 1; - - if (!params->zap) { - // Prep basic parameters - memcpy(h->signature, MTD_DRIVE_SIGNATURE, sizeof(h->signature)); - h->size = sizeof(*h); - h->first_offset = 0; - h->last_offset = (drive->mtd.drive_sectors * drive->mtd.sector_bytes) - 1; - h->crc32 = MtdHeaderCrc(h); - } - if (params->size) { - h->last_offset = params->size - 1; - drive->size = params->size; - drive->mtd.drive_sectors = drive->size / drive->mtd.sector_bytes; - } else if (!drive->mtd.drive_sectors) { - Error("MTD create with params->size == 0 && drive->mtd.drive_sectors == 0"); - return -1; - } - - return 0; -} - int CgptCreate(CgptCreateParams *params) { struct drive drive; @@ -123,13 +98,8 @@ int CgptCreate(CgptCreateParams *params) { params->drive_size)) return CGPT_FAILED; - if (drive.is_mtd) { - if (MtdCreate(&drive, params)) - goto bad; - } else { - if (GptCreate(&drive, params)) - goto bad; - } + if (GptCreate(&drive, params)) + goto bad; // Write it all out return DriveClose(&drive, 1); diff --git a/cgpt/cgpt_find.c b/cgpt/cgpt_find.c index 7d9ec8df..c3193040 100644 --- a/cgpt/cgpt_find.c +++ b/cgpt/cgpt_find.c @@ -83,20 +83,6 @@ static void showmatch(CgptFindParams *params, char *filename, EntryDetails(entry, partnum - 1, params->numeric); } -// This needs to handle /dev/mmcblk0 -> /dev/mmcblk0p3, /dev/sda -> /dev/sda3 -static void mtd_showmatch(CgptFindParams *params, char *filename, - int partnum, MtdDiskPartition *entry) { - char * format = "%s%d\n"; - if (strncmp("/dev/mmcblk", filename, 11) == 0) - format = "%sp%d\n"; - if (params->numeric) - printf("%d\n", partnum); - else - printf(format, filename, partnum); - if (params->verbose > 0) - MtdEntryDetails(entry, partnum - 1, params->numeric); -} - // This returns true if a GPT partition matches the search criteria. If a match // isn't found (or if the file doesn't contain a GPT), it returns false. The // filename and partition number that matched is left in a global, since we @@ -144,69 +130,6 @@ static int gpt_search(CgptFindParams *params, struct drive *drive, return retval; } -static int mtd_match_type_to_guid(const MtdDiskPartition *e, const Guid *guid) { - return LookupMtdTypeForGuid(guid) == MtdGetEntryType(e); -} - -static int mtd_match_content(CgptFindParams *params, struct drive *drive, - MtdDiskPartition *entry) { - uint64_t start, part_size; - - if (!params->matchlen) - return 1; - - // Ensure that the region we want to match against is inside the partition. - MtdGetPartitionSize(entry, &start, NULL, &part_size); - if (params->matchoffset + params->matchlen > part_size) { - return 0; - } - - // Read the partition data. - if (!FillBuffer(params, - drive->fd, - start + params->matchoffset, - params->matchlen)) { - Error("unable to read partition data\n"); - return 0; - } - - // Compare it - if (0 == memcmp(params->matchbuf, params->comparebuf, params->matchlen)) { - return 1; - } - - // Nope. - return 0; -} - -static int mtd_search(CgptFindParams *params, struct drive *drive, - char *filename) { - int i; - int retval = 0; - for (i = 0; i < GetNumberOfEntries(drive); ++i) { - MtdDiskPartition *e = MtdGetEntry(&drive->mtd, ANY_VALID, i); - - if (IsUnused(drive, ANY_VALID, i)) - continue; - - int found = 0; - - // Only searches by type are possible right now - if (params->set_type && mtd_match_type_to_guid(e, ¶ms->type_guid)) { - found = 1; - } - - if (found && mtd_match_content(params, drive, e)) { - params->hits++; - retval++; - mtd_showmatch(params, filename, i+1, e); - if (!params->match_partnum) - params->match_partnum = i+1; - } - } - return retval; -} - static int do_search(CgptFindParams *params, char *fileName) { int retval; struct drive drive; @@ -214,11 +137,7 @@ static int do_search(CgptFindParams *params, char *fileName) { if (CGPT_OK != DriveOpen(fileName, &drive, O_RDONLY, params->drive_size)) return 0; - if (drive.is_mtd) { - retval = mtd_search(params, &drive, fileName); - } else { - retval = gpt_search(params, &drive, fileName); - } + retval = gpt_search(params, &drive, fileName); (void) DriveClose(&drive, 0); diff --git a/cgpt/cgpt_legacy.c b/cgpt/cgpt_legacy.c index 07607690..b7582123 100644 --- a/cgpt/cgpt_legacy.c +++ b/cgpt/cgpt_legacy.c @@ -19,13 +19,6 @@ int CgptLegacy(CgptLegacyParams *params) { params->drive_size)) return CGPT_FAILED; - if (drive.is_mtd) { - // This command requires GPT mode. - Error("'legacy' command unsupported in MTD mode\n"); - DriveClose(&drive, 0); - return CGPT_FAILED; - } - h1 = (GptHeader *)drive.gpt.primary_header; h2 = (GptHeader *)drive.gpt.secondary_header; if (params->efipart) { diff --git a/cgpt/cgpt_prioritize.c b/cgpt/cgpt_prioritize.c index 019638d2..2bfc4843 100644 --- a/cgpt/cgpt_prioritize.c +++ b/cgpt/cgpt_prioritize.c @@ -110,17 +110,10 @@ int CgptPrioritize(CgptPrioritizeParams *params) { params->drive_size)) return CGPT_FAILED; - if (drive.is_mtd) { - if (drive.mtd.primary.crc32 != MtdHeaderCrc(&drive.mtd.primary)) { - Error("MTD header crc failure\n"); - return CGPT_FAILED; - } - } else { - if (GPT_SUCCESS != (gpt_retval = GptSanityCheck(&drive.gpt))) { - Error("GptSanityCheck() returned %d: %s\n", - gpt_retval, GptError(gpt_retval)); - return CGPT_FAILED; - } + if (GPT_SUCCESS != (gpt_retval = GptSanityCheck(&drive.gpt))) { + Error("GptSanityCheck() returned %d: %s\n", + gpt_retval, GptError(gpt_retval)); + return CGPT_FAILED; } max_part = GetNumberOfEntries(&drive); diff --git a/cgpt/cgpt_repair.c b/cgpt/cgpt_repair.c index 98899026..1880ea5b 100644 --- a/cgpt/cgpt_repair.c +++ b/cgpt/cgpt_repair.c @@ -19,12 +19,6 @@ int CgptRepair(CgptRepairParams *params) { params->drive_size)) return CGPT_FAILED; - if (drive.is_mtd) { - // Nothing to do - DriveClose(&drive, 0); - return 0; - } - int gpt_retval = GptSanityCheck(&drive.gpt); if (params->verbose) printf("GptSanityCheck() returned %d: %s\n", diff --git a/cgpt/cgpt_show.c b/cgpt/cgpt_show.c index 32d62d38..68a185cb 100644 --- a/cgpt/cgpt_show.c +++ b/cgpt/cgpt_show.c @@ -66,20 +66,6 @@ void PrintSignature(const char *indent, const char *sig, size_t n, int raw) { printf("\n"); } -static void MtdHeaderDetails(MtdDiskLayout *header, const char *indent, - int raw) { - PrintSignature(indent, (char*)header->signature, sizeof(header->signature), - raw); - - printf("%sSize: %d\n", indent, header->size); - printf("%sCRC: 0x%08x %s\n", indent, header->crc32, - (MtdHeaderCrc(header) != header->crc32) ? "(INVALID)" : ""); - printf("%sFirst offset: %llu\n", indent, - (unsigned long long)header->first_offset); - printf("%sLast offset: %llu\n", indent, - (unsigned long long)header->last_offset); -} - static void HeaderDetails(GptHeader *header, GptEntry *entries, const char *indent, int raw) { PrintSignature(indent, header->signature, sizeof(header->signature), raw); @@ -110,45 +96,6 @@ static void HeaderDetails(GptHeader *header, GptEntry *entries, ); } -void MtdEntryDetails(MtdDiskPartition *entry, uint32_t index, int raw) { - const Guid *guid = LookupGuidForMtdType(MtdGetEntryType(entry)); - char type[256]; - char contents[256]; - char name[sizeof(entry->label) + 1]; - uint64_t start, size; - if (guid) { - ResolveType(guid, type); - } else { - snprintf(type, sizeof(type), "MTD partition type %d", - MtdGetEntryType(entry)); - } - - MtdGetPartitionSizeInSectors(entry, &start, NULL, &size); - - // Provide a NUL if we are at maximum size. - name[sizeof(name)-1] = '\0'; - memcpy(name, entry->label, sizeof(entry->label)); - require(snprintf(contents, sizeof(contents), - "Label: \"%s\"", name) < sizeof(contents)); - - printf(PARTITION_FMT, (int)start, (int)size, index+1, contents); - printf(PARTITION_MORE, "Type: ", type); - - if (raw && MtdGetEntryType(entry) == MTD_PARTITION_TYPE_CHROMEOS_KERNEL) { - int tries = MtdGetEntryTries(entry); - int successful = MtdGetEntrySuccessful(entry); - int priority = MtdGetEntryPriority(entry); - require(snprintf(contents, sizeof(contents), - "priority=%d tries=%d successful=%d", - priority, tries, successful) < sizeof(contents)); - printf(PARTITION_MORE, "Attr: ", contents); - } else { - require(snprintf(contents, sizeof(contents), - "[%x]", entry->flags) < sizeof(contents)); - printf(PARTITION_MORE, "Attr: ", contents); - } -} - void EntryDetails(GptEntry *entry, uint32_t index, int raw) { char contents[256]; // scratch buffer for formatting output uint8_t label[GPT_PARTNAME_LEN]; @@ -194,18 +141,6 @@ void EntryDetails(GptEntry *entry, uint32_t index, int raw) { } } -void MtdEntriesDetails(struct drive *drive, int secondary, int raw) { - uint32_t i; - - for (i = 0; i < GetNumberOfEntries(drive); ++i) { - MtdDiskPartition *entry; - entry = MtdGetEntry(&drive->mtd, secondary, i); - if (IsUnused(drive, secondary, i)) - continue; - MtdEntryDetails(entry, i, raw); - } -} - void EntriesDetails(struct drive *drive, const int secondary, int raw) { uint32_t i; @@ -220,87 +155,6 @@ void EntriesDetails(struct drive *drive, const int secondary, int raw) { } } -int MtdShow(struct drive *drive, CgptShowParams *params) { - if (params->partition) { // show single partition - if (params->partition > GetNumberOfEntries(drive)) { - Error("invalid partition number: %d\n", params->partition); - return CGPT_FAILED; - } - - uint32_t index = params->partition - 1; - MtdDiskPartition *entry = MtdGetEntry(&drive->mtd, ANY_VALID, index); - char buf[256]; // scratch buffer for string conversion - const Guid *guid; - uint64_t start, size; - - MtdGetPartitionSizeInSectors(entry, &start, NULL, &size); - - if (params->single_item) { - switch(params->single_item) { - case 'b': - printf("%u\n", (int)start); - break; - case 's': - printf("%u\n", (int)size); - break; - case 't': - guid = LookupGuidForMtdType(MtdGetEntryType(entry)); - GuidToStr(guid, buf, sizeof(buf)); - printf("%s\n", buf); - break; - case 'S': - printf("%d\n", GetSuccessful(drive, ANY_VALID, index)); - break; - case 'T': - printf("%d\n", GetTries(drive, ANY_VALID, index)); - break; - case 'P': - printf("%d\n", GetPriority(drive, ANY_VALID, index)); - break; - case 'A': - printf("0x%x\n", entry->flags); - break; - } - } else { - printf(TITLE_FMT, "start", "size", "part", "contents"); - MtdEntryDetails(entry, index, params->numeric); - } - } else if (params->quick) { // show all partitions, quickly - uint32_t i; - char type[GUID_STRLEN]; - - for (i = 0; i < GetNumberOfEntries(drive); ++i) { - MtdDiskPartition *entry = MtdGetEntry(&drive->mtd, ANY_VALID, i); - const Guid *guid = LookupGuidForMtdType(MtdGetEntryType(entry)); - uint64_t start, size; - - MtdGetPartitionSizeInSectors(entry, &start, NULL, &size); - - if (IsUnused(drive, ANY_VALID, i)) - continue; - - if (!params->numeric && guid) { - ResolveType(guid, type); - } else { - snprintf(type, sizeof(type), "MTD partition type %d", - MtdGetEntryType(entry)); - } - printf(PARTITION_FMT, (int)start, (int)size, i+1, type); - } - } else { // show all partitions - if (params->debug || params->verbose) { - char indent[64]; - - require(snprintf(indent, sizeof(indent), GPT_MORE) < sizeof(indent)); - MtdHeaderDetails(&drive->mtd.primary, indent, 0); - } - printf(TITLE_FMT, "start", "size", "part", "contents"); - MtdEntriesDetails(drive, PRIMARY, params->numeric); - } - - return CGPT_OK; -} - static int GptShow(struct drive *drive, CgptShowParams *params) { int gpt_retval; if (GPT_SUCCESS != (gpt_retval = GptSanityCheck(&drive->gpt))) { @@ -486,13 +340,8 @@ int CgptShow(CgptShowParams *params) { params->drive_size)) return CGPT_FAILED; - if (drive.is_mtd) { - if (MtdShow(&drive, params)) - return CGPT_FAILED; - } else { - if (GptShow(&drive, params)) - return CGPT_FAILED; - } + if (GptShow(&drive, params)) + return CGPT_FAILED; DriveClose(&drive, 0); return CGPT_OK; diff --git a/cgpt/cmd_create.c b/cgpt/cmd_create.c index 47137bdc..34f59cbc 100644 --- a/cgpt/cmd_create.c +++ b/cgpt/cmd_create.c @@ -19,7 +19,6 @@ static void Usage(void) " default 0, meaning partitions and GPT structs are\n" " both on DRIVE\n" " -z Zero the sectors of the GPT table and entries\n" - " -s NUM Size (in bytes) of the disk (MTD only)\n" " -p NUM Size (in blocks) of the disk to pad between the\n" " primary GPT header and its entries, default 0\n" "\n", progname); @@ -34,7 +33,7 @@ int cmd_create(int argc, char *argv[]) { char *e = 0; opterr = 0; // quiet, you - while ((c=getopt(argc, argv, ":hzs:p:D:")) != -1) + while ((c=getopt(argc, argv, ":hzp:D:")) != -1) { switch (c) { @@ -49,9 +48,6 @@ int cmd_create(int argc, char *argv[]) { case 'z': params.zap = 1; break; - case 's': - params.size = strtoull(optarg, &e, 0); - break; case 'p': params.padding = strtoull(optarg, &e, 0); if (!*optarg || (e && *e)) diff --git a/cgpt/flash_ts.c b/cgpt/flash_ts.c deleted file mode 100644 index f37c4acc..00000000 --- a/cgpt/flash_ts.c +++ /dev/null @@ -1,423 +0,0 @@ -/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* *** THIS CODE HAS NOT BEEN SECURITY REVIEWED *** - * It lives in the firmware directory because that's where it needs to go - * eventually, but at the moment it is used only by usermode tools. - * Security review must be completed before this code is used in the - * firmware. - * See issue 246680 - */ - -#include "flash_ts.h" - -#include <errno.h> -#include <stdio.h> -#include <string.h> - -#include "utility.h" - -// These match the linux driver -#define FLASH_TS_MAGIC 0x53542a46 - -#define FLASH_TS_HEADER_SIZE 16 -#define FLASH_TS_MAX_SIZE 16384 -#define FLASH_TS_MAX_ELEMENT_SIZE (FLASH_TS_MAX_SIZE - FLASH_TS_HEADER_SIZE) - -typedef struct { - uint32_t magic; - uint32_t crc; - uint32_t length; - uint32_t version; - char data[FLASH_TS_MAX_ELEMENT_SIZE]; -} __attribute__((packed)) flash_ts; - -typedef struct { - size_t start_block; // Partition start offset (in erase blocks) - size_t end_block; // Partition end offset (in erase blocks) - size_t chunk_size; // Minimum element size - size_t pages_per_block, chunks_per_block, pages_per_chunk; - nand_geom nand; - - size_t cached_block; - size_t current_block; - - flash_ts current; - flash_ts temp; -} flash_ts_state; - - -static flash_ts_state state; - -size_t pow2(size_t x) { - size_t v = 1; - while (v < x) - v <<= 1; - return v; -} - -static inline uint32_t flash_ts_crc(const flash_ts *cache) -{ - const unsigned char *p; - uint32_t crc = 0; - size_t len; - - /* skip magic and crc fields */ - len = cache->length + 2 * sizeof(uint32_t); - p = (const unsigned char*)&cache->length; - - while (len--) { - int i; - - crc ^= *p++; - for (i = 0; i < 8; i++) - crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320 : 0); - } - return crc ^ ~0; -} - -static inline int flash_ts_check_crc(const flash_ts *ts) { - return ts->crc == flash_ts_crc(ts); -} - -static int is_blank(const void *ptr, size_t sz) { - const unsigned char *p = (const unsigned char*)ptr; - const unsigned char *end = p + sz; - while (p < end) - if (*p++ != 0xff) - return 0; - return 1; -} - -static int is_pow2(size_t v) { - return v && (v & (v - 1)) == 0; -} - -/* Scan the entire partition to find the latest version */ -static void flash_ts_scan_partition(flash_ts_state *ts) { - size_t block; - - for (block = ts->start_block; block < ts->end_block; block++) { - if (!nand_is_bad_block(&ts->nand, block)) { - size_t chunk; - size_t page_base = block * ts->pages_per_block; - - for (chunk = 0; chunk < ts->chunks_per_block; - chunk++, page_base += ts->pages_per_chunk) { - if (nand_read_page(&ts->nand, page_base, - &ts->temp, sizeof(ts->temp))) { - continue; - } - if (ts->temp.magic != FLASH_TS_MAGIC || - ts->temp.version <= ts->current.version || - !flash_ts_check_crc(&ts->temp)) { - if (is_blank(&ts->temp, sizeof(ts->temp))) { - // Since we only write sequentially, a blank chunk means no more - // data in this block. - break; - } - continue; - } - - // It's good & newer than our current version - VBDEBUG(("Found good version %d\n", ts->temp.version)); - ts->current_block = block; - Memcpy(&ts->current, &ts->temp, sizeof(ts->current)); - } - } - } -} - -static char *flash_ts_search(flash_ts *ts, const char *key) { - char *str = &ts->data[0]; - size_t keylen = strlen(key); - - while(*str && str + keylen < &ts->data[ts->length]) { - // Format: name=value\0name2=value2\0 ... keyn=valuen\0\0 - if (!Memcmp(str, key, keylen) && str[keylen] == '=') { - return &str[keylen + 1]; - } else { - str += strlen(str) + 1; // Skip to next key - } - } - return NULL; -} - -static int flash_ts_find_writeable_chunk(flash_ts_state *ts, uint32_t block) { - uint32_t page_base = block * ts->pages_per_block; - uint32_t page_end = (block + 1) * ts->pages_per_block; - - for(; page_base < page_end; page_base += ts->pages_per_chunk) { - if(!nand_read_page(&ts->nand, page_base, - &ts->temp, sizeof(ts->temp))) { - if (is_blank(&ts->temp, sizeof(ts->temp))) - return page_base; - } - } - - return -1; -} - -static int in_range(const flash_ts_state *ts, uint32_t block) { - return block >= ts->start_block && block < ts->end_block; -} - -static int flash_try_write(flash_ts_state *ts, uint32_t page) { - return nand_write_page(&ts->nand, page, &ts->current, sizeof(ts->current)) || - nand_read_page(&ts->nand, page, &ts->temp, sizeof(ts->temp)) || - Memcmp(&ts->current, &ts->temp, sizeof(ts->current)); -} - - -static int flash_ts_find_writeable_spot(flash_ts_state *ts, - uint32_t *page_ofs) { - uint32_t block; - if (in_range(ts, ts->cached_block)) { - // We have a starting position to scan from - block = ts->cached_block; - } else { - block = ts->start_block; - VBDEBUG(("Cached block not in range - starting from %u\n", block)); - } - for (; block < ts->end_block; block++) { - int chunk; - if (nand_is_bad_block(&ts->nand, block)) { - VBDEBUG(("Skipping bad block %u\n", block)); - continue; - } - - chunk = flash_ts_find_writeable_chunk(ts, block); - if (chunk < 0) { - VBDEBUG(("No free chunks in block %u\n", block)); - continue; - } - - VBDEBUG(("Free chunk %d in block %u\n", chunk, block)); - *page_ofs = chunk; - ts->cached_block = block; - return 0; - } - return -1; -} - -static int flash_try_erase(flash_ts_state *ts, int block) { - return nand_is_bad_block(&ts->nand, block) || - nand_erase_block(&ts->nand, block); -} - -static int flash_erase_any_block(flash_ts_state *ts, uint32_t hint) { - uint32_t block; - for (block = hint; block < ts->end_block; block++) { - if (!flash_try_erase(ts, block)) { - ts->cached_block = block; - VBDEBUG(("Erased block %u\n", block)); - return 0; - } - } - - if (hint > ts->end_block) - hint = ts->end_block; - - for (block = ts->start_block; block < hint; block++) { - if (!flash_try_erase(ts, block)) { - ts->cached_block = block; - VBDEBUG(("Erased block %u\n", block)); - return 0; - } - } - return -1; -} - -static int flash_ts_write(flash_ts_state *ts) { - int passes = 3; - uint32_t page; - - - ts->cached_block = ts->current_block; - ts->current.version++; - ts->current.crc = flash_ts_crc(&ts->current); - VBDEBUG(("flash_ts_write() - %u bytes, crc %08X\n", - ts->current.length, ts->current.crc)); - - while(passes--) { - if (flash_ts_find_writeable_spot(ts, &page)) { - if (ts->cached_block == ts->end_block) { - uint32_t block; - - // Partition full! - // Erase a block to get some space - if (in_range(ts, ts->current_block) && - ts->current_block != ts->end_block - 1) { - // We don't want to overwrite our good copy if we can avoid it. - block = ts->current_block + 1; - } else { - block = ts->start_block; - } - VBDEBUG(("Partition full - begin erasing from block %u\n", block)); - - // Erase block, and try again. - if (flash_erase_any_block(ts, block)) { - // Failed to erase anything, so abort. - VBDEBUG(("All erases failed, aborting\n")); - return -ENOMEM; - } - continue; - } else { - // Try again, re-scan everything. - ts->cached_block = ts->end_block; - continue; - } - } - - if (flash_try_write(ts, page)) { - // Write failure, or read-back failure, try again with the next block. - VBDEBUG(("Write failure, retry\n")); - ts->cached_block++; - continue; - } - - VBDEBUG(("Successfully written v%u @ %u\n", ts->current.version, page)); - ts->current_block = ts->cached_block; - return 0; - } - - VBDEBUG(("Out of tries\n")); - return -EAGAIN; -} - -// Set value, returns 0 on success -int flash_ts_set(const char *key, const char *value) { - flash_ts *ts = &state.current; - char *at; - size_t keylen = strlen(key); - size_t value_len = strlen(value); - - if (keylen == 0) { - VBDEBUG(("0-length key - illegal\n")); - return -1; - } - - if (strchr(key, '=')) { - VBDEBUG(("key contains '=' - illegal\n")); - return -1; - } - - Memcpy(&state.temp, &state.current, sizeof(state.temp)); - - at = flash_ts_search(ts, key); - if (at) { - size_t old_value_len; - - // Already exists - if (!strcmp(at, value)) { - // No change - VBDEBUG(("Values are the same, not writing\n")); - return 0; - } - - old_value_len = strlen(at); - if (value_len == old_value_len) { - // Overwrite it - Memcpy(at, value, value_len); - VBDEBUG(("Values are the same length, overwrite\n")); - } else { - // Remove it - // if value_len == 0, then we're done - // if value_len != old_value_len, then we do the append below - char *src = at - (keylen + 1); - char *end = &ts->data[ts->length]; - char *from = at + old_value_len + 1; - - VBDEBUG(("Delete old value\n")); - memmove(src, from, end - from); - ts->length -= (from-src); - ts->data[ts->length - 1] = '\0'; - at = NULL; // Enter the append branch below - } - } else if (value_len == 0) { - // Removing non-existent entry - return 0; - } - - if (!at && value_len > 0) { - // Append it - - if (ts->length + keylen + 1 + value_len + 1 > FLASH_TS_MAX_ELEMENT_SIZE) { - // Not enough space, restore previous - VBDEBUG(("Not enough space to write %d data bytes\n", (int)value_len)); - Memcpy(&state.current, &state.temp, sizeof(state.temp)); - return -1; - } - - VBDEBUG(("Append new value\n")); - at = &ts->data[ts->length - 1]; - strcpy(at, key); - at[keylen] = '='; - strcpy(at + keylen + 1, value); - ts->length += keylen + 1 + value_len + 1; - ts->data[ts->length-1] = '\0'; - } - - return flash_ts_write(&state); -} - -void flash_ts_get(const char *key, char *value, unsigned int size) { - flash_ts_state *ts = &state; - const char *at; - - at = flash_ts_search(&ts->current, key); - if (at) { - strncpy(value, at, size); - } else { - *value = '\0'; - } -} - -int flash_ts_init(unsigned int start_block, unsigned int blocks, - unsigned int szofpg, unsigned int szofblk, - unsigned int szofsector, void *user) { - flash_ts_state *ts = &state; - - if (!is_pow2(szofpg) || !is_pow2(szofblk) || !is_pow2(szofsector) || - szofsector > szofpg || szofpg > szofblk || blocks == 0) - return -ENODEV; - - Memset(ts, 0, sizeof(*ts)); - - // Page <= chunk <= block - // Page is minimum writable unit - // Chunk is actual write unit - // Block is erase unit - ts->start_block = start_block; - ts->end_block = start_block + blocks; - ts->pages_per_block = szofblk / szofpg; - - ts->nand.user = user; - ts->nand.szofpg = szofpg; - ts->nand.szofblk = szofblk; - ts->nand.szofsector = szofsector; - - // Calculate our write size, this mirrors the linux driver's logic - ts->chunk_size = pow2((sizeof(flash_ts) + szofpg - 1) & ~(szofpg - 1)); - if (!is_pow2(ts->chunk_size)) - return -ENODEV; - - ts->pages_per_chunk = ts->chunk_size / szofpg; - if (ts->pages_per_chunk == 0 || ts->chunk_size > szofblk) - return -ENODEV; - - ts->chunks_per_block = szofblk / ts->chunk_size; - - ts->current.version = 0; - ts->current.length = 1; - ts->current.magic = FLASH_TS_MAGIC; - ts->current.crc = flash_ts_crc(&ts->current); - ts->current.data[0] = '\0'; - ts->current_block = ts->end_block; - - flash_ts_scan_partition(ts); - - return 0; -} diff --git a/cgpt/flash_ts.h b/cgpt/flash_ts.h deleted file mode 100644 index e5771bb1..00000000 --- a/cgpt/flash_ts.h +++ /dev/null @@ -1,35 +0,0 @@ -/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ -#ifndef _FLASH_TS_H -#define _FLASH_TS_H - -typedef struct { - unsigned int szofpg; /* Erase unit */ - unsigned int szofblk; /* Write unit */ - unsigned int szofsector; /* Sector size used by the rest of cgpt */ - void *user; -} nand_geom; - -int flash_ts_init(unsigned int start_block, unsigned int blocks, - unsigned int szofpg, unsigned int szofblk, - unsigned int szofsector, void *user); - -/* Get/set value, returns 0 on success */ -int flash_ts_set(const char *key, const char *value); -void flash_ts_get(const char *key, char *value, unsigned int size); - -/* Get value as an integer, if missing/invalid return 'default_value' */ -int flash_ts_get_int(const char *key, int default_value); - - -/* These must be implemented outside the driver. */ -int nand_read_page(const nand_geom *nand, int page, void *buf, int size); -int nand_write_page(const nand_geom *nand, int page, const void *buf, int size); -int nand_erase_block(const nand_geom *nand, int block); -int nand_is_bad_block(const nand_geom *nand, int block); - - - -#endif /* _FLASH_TS_H */ diff --git a/cgpt/flash_ts_api.h b/cgpt/flash_ts_api.h deleted file mode 100644 index 47264a4d..00000000 --- a/cgpt/flash_ts_api.h +++ /dev/null @@ -1,25 +0,0 @@ -/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ -#ifndef _LINUX_FLASH_TS_H_ -#define _LINUX_FLASH_TS_H_ - -#include <asm/ioctl.h> -#include <asm/types.h> - -#define FLASH_TS_MAX_KEY_SIZE 64 -#define FLASH_TS_MAX_VAL_SIZE 2048 - -struct flash_ts_io_req { - char key[FLASH_TS_MAX_KEY_SIZE]; - char val[FLASH_TS_MAX_VAL_SIZE]; -}; - -#define FLASH_TS_IO_MAGIC 0xFE -#define FLASH_TS_IO_SET _IOW(FLASH_TS_IO_MAGIC, 0, struct flash_ts_io_req) -#define FLASH_TS_IO_GET _IOWR(FLASH_TS_IO_MAGIC, 1, struct flash_ts_io_req) - -#define FTS_DEVICE "/dev/fts" - -#endif /* _LINUX_FLASH_TS_H_ */ diff --git a/cgpt/flash_ts_drv.c b/cgpt/flash_ts_drv.c deleted file mode 100644 index 4709b37c..00000000 --- a/cgpt/flash_ts_drv.c +++ /dev/null @@ -1,72 +0,0 @@ -/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Utility for ChromeOS-specific GPT partitions, Please see corresponding .c - * files for more details. - */ - -#include <errno.h> -#include <stdio.h> -#include <string.h> - -#include "flash_ts.h" -#include "cgpt.h" - -inline int page_to_sector(const nand_geom *nand, int page) { - return page * (nand->szofpg / nand->szofsector); -} - -int nand_read_page(const nand_geom *nand, int page, void *buf, int size) { - uint8_t *page_buff; - - if (Load((struct drive *)nand->user, &page_buff, - page_to_sector(nand, page), nand->szofsector, - (size + nand->szofsector - 1) / nand->szofsector)) { - - // page may be not erased. return default data. - memset(buf, 0xff, size); - return 0; - } - memcpy(buf, page_buff, size); - free(page_buff); - return 0; -} - -int nand_write_page(const nand_geom *nand, - int page, const void *buf, int buf_size) { - void *page_buff; - int ret; - int sectors = (buf_size + nand->szofsector - 1) / nand->szofsector; - int size = nand->szofsector * sectors; - - page_buff = malloc(size); - if (!page_buff) - return -1; - - memset(page_buff, 0xff, size); - memcpy(page_buff, buf, buf_size); - - ret = Save((struct drive *)nand->user, page_buff, page_to_sector(nand, page), - nand->szofsector, sectors); - free(page_buff); - return ret; -} - -int nand_erase_block(const nand_geom *nand, int block) { - int sector = block * (nand->szofblk / nand->szofsector); - int res; - void *erase_buff = malloc(nand->szofblk); - if (!erase_buff) - return -1; - - memset(erase_buff, 0xff, nand->szofblk); - res = Save((struct drive *)nand->user, erase_buff, sector, - nand->szofsector, nand->szofblk / nand->szofsector); - free(erase_buff); - return res; -} - -int nand_is_bad_block(const nand_geom *nand, int block) { - return 0; -} |