struct cbfs_file *cbfs_find(const char *name) { struct cbfs_header *header = cbfs_master_header(); void *offset; if (header == NULL) return NULL; offset = virt_to_phys(0 - ntohl(header->romsize) + ntohl(header->offset)); int align= ntohl(header->align); while(1) { struct cbfs_file *file = (struct cbfs_file *) offset; if (!cbfs_check_magic(file)) return NULL; debug("Check %s\n", CBFS_NAME(file)); if (!strcmp(CBFS_NAME(file), name)) return file; int flen = ntohl(file->len); int foffset = ntohl(file->offset); debug("CBFS: follow chain: %p + %x + %x + align -> ", offset, foffset, flen); void *oldoffset = offset; offset = (void*)ALIGN((uintptr_t)(offset + foffset + flen), align); debug("%p\n", (void *)offset); if (offset <= oldoffset) return NULL; if (offset < virt_to_phys(0xFFFFFFFF - ntohl(header->romsize))) return NULL; } }
int cbfs_create_empty_entry(struct cbfs_image *image, struct cbfs_file *entry, size_t len, const char *name) { memset(entry, CBFS_CONTENT_DEFAULT_VALUE, sizeof(*entry)); memcpy(entry->magic, CBFS_FILE_MAGIC, sizeof(entry->magic)); entry->type = htonl(CBFS_COMPONENT_NULL); entry->len = htonl(len); entry->checksum = 0; // TODO Build a checksum algorithm. entry->offset = htonl(cbfs_calculate_file_header_size(name)); memset(CBFS_NAME(entry), 0, ntohl(entry->offset) - sizeof(*entry)); strcpy(CBFS_NAME(entry), name); memset(CBFS_SUBHEADER(entry), CBFS_CONTENT_DEFAULT_VALUE, len); return 0; }
int cbfs_print_entry_info(struct cbfs_image *image, struct cbfs_file *entry, void *arg) { const char *name = CBFS_NAME(entry); struct cbfs_payload_segment *payload; FILE *fp = (FILE *)arg; if (!cbfs_is_valid_entry(image, entry)) { ERROR("cbfs_print_entry_info: Invalid entry at 0x%x\n", cbfs_get_entry_addr(image, entry)); return -1; } if (!fp) fp = stdout; fprintf(fp, "%-30s 0x%-8x %-12s %d\n", *name ? name : "(empty)", cbfs_get_entry_addr(image, entry), get_cbfs_entry_type_name(ntohl(entry->type)), ntohl(entry->len)); if (!verbose) return 0; DEBUG(" cbfs_file=0x%x, offset=0x%x, content_address=0x%x+0x%x\n", cbfs_get_entry_addr(image, entry), ntohl(entry->offset), cbfs_get_entry_addr(image, entry) + ntohl(entry->offset), ntohl(entry->len)); /* note the components of the subheader may be in host order ... */ switch (ntohl(entry->type)) { case CBFS_COMPONENT_STAGE: cbfs_print_stage_info((struct cbfs_stage *) CBFS_SUBHEADER(entry), fp); break; case CBFS_COMPONENT_PAYLOAD: payload = (struct cbfs_payload_segment *) CBFS_SUBHEADER(entry); while (payload) { /* Stop when PAYLOAD_SEGMENT_ENTRY seen. */ if (cbfs_print_payload_segment_info(payload, fp)) break; payload ++; } break; default: break; } return 0; }
struct cbfs_file *cbfs_get_entry(struct cbfs_image *image, const char *name) { struct cbfs_file *entry; for (entry = cbfs_find_first_entry(image); entry && cbfs_is_valid_entry(image, entry); entry = cbfs_find_next_entry(image, entry)) { if (strcasecmp(CBFS_NAME(entry), name) == 0) { DEBUG("cbfs_get_entry: found %s\n", name); return entry; } } return NULL; }
int cbfs_remove_entry(struct cbfs_image *image, const char *name) { struct cbfs_file *entry, *next; size_t len; entry = cbfs_get_entry(image, name); if (!entry) { ERROR("CBFS file %s not found.\n", name); return -1; } next = cbfs_find_next_entry(image, entry); assert(next); DEBUG("cbfs_remove_entry: Removed %s @ 0x%x\n", CBFS_NAME(entry), cbfs_get_entry_addr(image, entry)); entry->type = htonl(CBFS_COMPONENT_DELETED); len = (cbfs_get_entry_addr(image, next) - cbfs_get_entry_addr(image, entry)); entry->offset = htonl(cbfs_calculate_file_header_size("")); entry->len = htonl(len - ntohl(entry->offset)); memset(CBFS_NAME(entry), 0, ntohl(entry->offset) - sizeof(*entry)); memset(CBFS_SUBHEADER(entry), CBFS_CONTENT_DEFAULT_VALUE, ntohl(entry->len)); return 0; }