/* Get the headers from the buffer. * Return -1 in the event of an error. * The section headers are optional; if NULL * is passed in for pshdr they won't be parsed. * We don't (yet) make payload parsing optional * because we've never seen a use case. */ int elf_headers(const struct buffer *pinput, uint32_t arch, Elf64_Ehdr *ehdr, Elf64_Phdr **pphdr, Elf64_Shdr **pshdr) { struct parsed_elf pelf; int flags; flags = ELF_PARSE_PHDR; if (pshdr != NULL) flags |= ELF_PARSE_SHDR; if (parse_elf(pinput, &pelf, flags)) return -1; /* Copy out the parsed elf header. */ memcpy(ehdr, &pelf.ehdr, sizeof(*ehdr)); *pphdr = calloc(ehdr->e_phnum, sizeof(Elf64_Phdr)); memcpy(*pphdr, pelf.phdr, ehdr->e_phnum * sizeof(Elf64_Phdr)); if (pshdr != NULL) { *pshdr = calloc(ehdr->e_shnum, sizeof(Elf64_Shdr)); memcpy(*pshdr, pelf.shdr, ehdr->e_shnum * sizeof(Elf64_Shdr)); } parsed_elf_destroy(&pelf); return 0; }
int main(int argc, char *argv[]) { FILE *fp; u8 bfr[ALIGNMENT]; get_args(argc, argv); elf_size = get_filesize(elf_name); elf = mmap_file(elf_name); parse_elf(); meta_header_size = 0x80 + ehdr.e_phnum * (0x30 + 0x20 + 0x60) + 0x30; info_offset = 0x70; elf_offset = 0x90; phdr_offset = elf_offset + ehdr.e_ehsize; sec_offset = round_up(phdr_offset + ehdr.e_phentsize * ehdr.e_phnum, ALIGNMENT); version_offset = round_up(sec_offset + ehdr.e_phnum * 0x20, ALIGNMENT); ctrl_offset = round_up(version_offset + 0x10, ALIGNMENT); meta_offset = round_up(ctrl_offset + 0x70, ALIGNMENT); header_size = round_up(meta_offset + meta_header_size, 0x80); if (compression) compress_elf(); else fill_phdr_map(); build_sce_hdr(); build_info_hdr(); build_ctrl_hdr(); build_sec_hdr(); build_version_hdr(); build_meta_hdr(); self = malloc(header_size + elf_size); memset(self, 0, header_size + elf_size); build_hdr(); write_elf(); calculate_hashes(); sign_hdr(); sce_encrypt_data(self); sce_encrypt_header(self, &ks); fp = fopen(self_name, "wb"); if (fp == NULL) fail("fopen(%s) failed", self_name); if (fwrite(self, header_size + compressed_size, 1, fp) != 1) fail("unable to write self"); memset(bfr, 0, sizeof bfr); fwrite(bfr, round_up(compressed_size, ALIGNMENT) - compressed_size, 1, fp); fclose(fp); return 0; }
int main(int argc,char **argv) { if(argc!=2){ printf("Invalid Usage!!!\n"); printf("%s elf_file\n",argv[0]); return 1; } parse_elf(argv[1]); return 0; }
void start(uint32_t* modulep, void* physbase, void* physfree) { struct smap_t { uint64_t base, length; uint32_t type; }__attribute__((packed)) *smap; while(modulep[0] != 0x9001) modulep += modulep[1]+2; for(smap = (struct smap_t*)(modulep+2); smap < (struct smap_t*)((char*)modulep+modulep[1]+2*4); ++smap) { if (smap->type == 1 /* memory */ && smap->length != 0) { //print_out("Available Physical Memory [%x-%x]\n", smap->base, smap->base + smap->length); total = smap->base + smap->length; } } //print_out("tarfs in [%p:%p]\n", &_binary_tarfs_start, &_binary_tarfs_end); total = (total/1048576) +1; //print_out(" The Highest memory is %d ",total); //print_out("This is the address of physfree -- %p ", physfree); initialize_free_pages(); initialize_tasks(); register_fs((uint64_t)&_binary_tarfs_start); create_page_tables(physfree); //print_out(" Successfully created page tables"); __asm__("cli;"); file = parse_elf("bin/shell"); load_file_list = file->load_list; load_shell(); /* file = parse_elf("bin/hello"); load_file_list = file->load_list; load_file(); */ file = parse_elf("bin/try"); load_file_list = file->load_list; load_file(); switch_to(0); // kernel starts here while(1); }
int rmodule_init(struct rmod_context *ctx, const struct buffer *elfin) { struct parsed_elf *pelf; size_t i; int ret; ret = -1; memset(ctx, 0, sizeof(*ctx)); pelf = &ctx->pelf; if (parse_elf(elfin, pelf, ELF_PARSE_ALL)) { ERROR("Couldn't parse ELF!\n"); return -1; } /* Only allow executables to be turned into rmodules. */ if (pelf->ehdr.e_type != ET_EXEC) { ERROR("ELF is not an executable: %u.\n", pelf->ehdr.e_type); goto out; } /* Determine if architecture is supported. */ for (i = 0; i < ARRAY_SIZE(reloc_ops); i++) { if (reloc_ops[i].arch == pelf->ehdr.e_machine) { ctx->ops = &reloc_ops[i]; break; } } if (ctx->ops == NULL) { ERROR("ELF is unsupported arch: %u.\n", pelf->ehdr.e_machine); goto out; } /* Set the endian ops. */ if (ctx->pelf.ehdr.e_ident[EI_DATA] == ELFDATA2MSB) ctx->xdr = &xdr_be; else ctx->xdr = &xdr_le; if (find_program_segment(ctx)) goto out; if (filter_relocation_sections(ctx)) goto out; ret = 0; out: return ret; }
/* Get the headers from the buffer. * Return -1 in the event of an error. * The section headers are optional; if NULL * is passed in for pshdr they won't be parsed. * We don't (yet) make payload parsing optional * because we've never seen a use case. */ int elf_headers(const struct buffer *pinput, uint32_t arch, Elf64_Ehdr *ehdr, Elf64_Phdr **pphdr, Elf64_Shdr **pshdr) { struct parsed_elf pelf; int flags; flags = ELF_PARSE_PHDR; if (pshdr != NULL) flags |= ELF_PARSE_SHDR; if (parse_elf(pinput, &pelf, flags)) return -1; /* Copy out the parsed elf header. */ memcpy(ehdr, &pelf.ehdr, sizeof(*ehdr)); // The tool may work in architecture-independent way. if (arch != CBFS_ARCHITECTURE_UNKNOWN && !((ehdr->e_machine == EM_ARM) && (arch == CBFS_ARCHITECTURE_ARMV7)) && !((ehdr->e_machine == EM_386) && (arch == CBFS_ARCHITECTURE_X86))) { ERROR("The stage file has the wrong architecture\n"); return -1; } *pphdr = calloc(ehdr->e_phnum, sizeof(Elf64_Phdr)); memcpy(*pphdr, pelf.phdr, ehdr->e_phnum * sizeof(Elf64_Phdr)); if (pshdr != NULL) { *pshdr = calloc(ehdr->e_shnum, sizeof(Elf64_Shdr)); memcpy(*pshdr, pelf.shdr, ehdr->e_shnum * sizeof(Elf64_Shdr)); } parsed_elf_destroy(&pelf); return 0; }
static void walk_directory(const char *dirname) { assert(dirname); DIR *dir = opendir(dirname); if (dir) { struct dirent *entry; while ((entry = readdir(dir)) != NULL) { if (strcmp(entry->d_name, ".") == 0) continue; if (strcmp(entry->d_name, "..") == 0) continue; // build full path char *path; if (asprintf(&path, "%s/%s", dirname, entry->d_name) == -1) errExit("asprintf"); // check regular so library char *ptr = strstr(entry->d_name, ".so"); if (ptr && is_lib_64(path)) { if (*(ptr + 3) == '\0' || *(ptr + 3) == '.') { parse_elf(path); free(path); continue; } } // check directory // entry->d_type field is supported in glibc since version 2.19 (Feb 2014) // we'll use stat to check for directories struct stat s; if (stat(path, &s) == -1) errExit("stat"); if (S_ISDIR(s.st_mode)) walk_directory(path); } closedir(dir); } }
static void copy_libs_for_lib(const char *lib) { Storage *lib_path; for (lib_path = lib_paths; lib_path; lib_path = lib_path->next) { char *fname; if (asprintf(&fname, "%s/%s", lib_path->name, lib) == -1) errExit("asprintf"); if (access(fname, R_OK) == 0 && is_lib_64(fname)) { if (!storage_find(libs, fname)) { storage_add(&libs, fname); // libs may need other libs parse_elf(fname); } free(fname); return; } free(fname); } // log a warning and continue if (!arg_quiet) fprintf(stderr, "Warning fldd: cannot find %s, skipping...\n", lib); }
act_rv_t act_memleak_mq_maps(act_memleak_mq_maps_t *p_mq_ref1) { act_int_t i; act_memleak_avl_node_t **pp_func_root; act_memleak_avl_node_t **pp_file_line_root; act_memleak_ref_root_t *p_ref_root; if (big2little){ p_mq_ref1->pid = int_big2little(p_mq_ref1->pid); } for(i = 0; i < MAPS_MAX; i++){ if (big2little){ p_mq_ref1->u.maps[i].add1 = int_big2little(p_mq_ref1->u.maps[i].add1); p_mq_ref1->u.maps[i].add2 = int_big2little(p_mq_ref1->u.maps[i].add2); p_mq_ref1->u.maps[i].add3 = int_big2little(p_mq_ref1->u.maps[i].add3); p_mq_ref1->u.maps[i].add4 = int_big2little(p_mq_ref1->u.maps[i].add4); } act_printf("add1=0x%x add2=0x%x add3=0x%x add4=0x%x name:%s\n", p_mq_ref1->u.maps[i].add1, p_mq_ref1->u.maps[i].add2, p_mq_ref1->u.maps[i].add3, p_mq_ref1->u.maps[i].add4, p_mq_ref1->u.maps[i].name); } p_ref_root = act_memleak_ref_root_find(p_mq_ref1->pid); pp_func_root = &p_ref_root->p_func_ref_root; pp_file_line_root = &p_ref_root->p_file_line_ref_root; if (p_mq_ref1->u.maps[MAPS_MAIN].add1 != 0){ parse_elf(pp_func_root, pp_file_line_root, p_mq_ref1->u.maps[MAPS_MAIN].name, 0, 0, 0); //sprintf(p_name, "%s", p_mq_ref1->u.maps[MAPS_MAIN].name); } if (p_mq_ref1->u.maps[MAPS_LIB_CMS_CORE].add1 != 0){ parse_elf(pp_func_root, pp_file_line_root, "./libdbus.so", p_mq_ref1->u.maps[MAPS_LIB_CMS_CORE].add1, p_mq_ref1->u.maps[MAPS_LIB_CMS_CORE].add2, p_mq_ref1->u.maps[MAPS_LIB_CMS_CORE].add3); } if (p_mq_ref1->u.maps[MAPS_LIB_CMS_UTIL].add1 != 0){ parse_elf(pp_func_root, pp_file_line_root, "./libuClibc-0.9.30.1.so", p_mq_ref1->u.maps[MAPS_LIB_CMS_UTIL].add1, p_mq_ref1->u.maps[MAPS_LIB_CMS_UTIL].add2, p_mq_ref1->u.maps[MAPS_LIB_CMS_UTIL].add3); } if (p_mq_ref1->u.maps[MAPS_LIB_CMS_CORE].add1 != 0){ parse_elf(pp_func_root, pp_file_line_root, "./libcms_core.so", p_mq_ref1->u.maps[MAPS_LIB_CMS_CORE].add1, p_mq_ref1->u.maps[MAPS_LIB_CMS_CORE].add2, p_mq_ref1->u.maps[MAPS_LIB_CMS_CORE].add3); } if (p_mq_ref1->u.maps[MAPS_LIB_CMS_UTIL].add1 != 0){ parse_elf(pp_func_root, pp_file_line_root, "./libcms_util.so", p_mq_ref1->u.maps[MAPS_LIB_CMS_UTIL].add1, p_mq_ref1->u.maps[MAPS_LIB_CMS_UTIL].add2, p_mq_ref1->u.maps[MAPS_LIB_CMS_UTIL].add3); } if (p_mq_ref1->u.maps[MAPS_LIB_CMS_DAL].add1 != 0){ parse_elf(pp_func_root, pp_file_line_root, "./libcms_dal.so", p_mq_ref1->u.maps[MAPS_LIB_CMS_DAL].add1, p_mq_ref1->u.maps[MAPS_LIB_CMS_DAL].add2, p_mq_ref1->u.maps[MAPS_LIB_CMS_DAL].add3); } if (p_mq_ref1->u.maps[MAPS_LIB_CMS_MSG].add1 != 0){ parse_elf(pp_func_root, pp_file_line_root, "./libcms_msg.so", p_mq_ref1->u.maps[MAPS_LIB_CMS_MSG].add1, p_mq_ref1->u.maps[MAPS_LIB_CMS_MSG].add2, p_mq_ref1->u.maps[MAPS_LIB_CMS_MSG].add3); } if (p_mq_ref1->u.maps[MAPS_LIB_NANO_XML].add1 != 0){ parse_elf(pp_func_root, pp_file_line_root, "./libnanoxml.so", p_mq_ref1->u.maps[MAPS_LIB_NANO_XML].add1, p_mq_ref1->u.maps[MAPS_LIB_NANO_XML].add2, p_mq_ref1->u.maps[MAPS_LIB_NANO_XML].add3); } if (p_mq_ref1->u.maps[MAPS_LIB_XDSL_CTL].add1 != 0){ parse_elf(pp_func_root, pp_file_line_root, "./libxdslctl.so", p_mq_ref1->u.maps[MAPS_LIB_XDSL_CTL].add1, p_mq_ref1->u.maps[MAPS_LIB_XDSL_CTL].add2, p_mq_ref1->u.maps[MAPS_LIB_XDSL_CTL].add3); } if (p_mq_ref1->u.maps[MAPS_LIB_ATM_CTL].add1 != 0){ parse_elf(pp_func_root, pp_file_line_root, "./libatmctl.so", p_mq_ref1->u.maps[MAPS_LIB_ATM_CTL].add1, p_mq_ref1->u.maps[MAPS_LIB_ATM_CTL].add2, p_mq_ref1->u.maps[MAPS_LIB_ATM_CTL].add3); } if (p_mq_ref1->u.maps[MAPS_LIB_CMS_BOARD_CTL].add1 != 0){ parse_elf(pp_func_root, pp_file_line_root, "./libcms_boardctl.so", p_mq_ref1->u.maps[MAPS_LIB_CMS_BOARD_CTL].add1, p_mq_ref1->u.maps[MAPS_LIB_CMS_BOARD_CTL].add2, p_mq_ref1->u.maps[MAPS_LIB_CMS_BOARD_CTL].add3); } if (p_mq_ref1->u.maps[MAPS_LIB_WL_MNGR].add1 != 0){ parse_elf(pp_func_root, pp_file_line_root, "./libwlmngr.so", p_mq_ref1->u.maps[MAPS_LIB_WL_MNGR].add1, p_mq_ref1->u.maps[MAPS_LIB_WL_MNGR].add2, p_mq_ref1->u.maps[MAPS_LIB_WL_MNGR].add3); } if (p_mq_ref1->u.maps[MAPS_LIB_WL_CTL].add1 != 0){ parse_elf(pp_func_root, pp_file_line_root, "./libwlctl.so", p_mq_ref1->u.maps[MAPS_LIB_WL_CTL].add1, p_mq_ref1->u.maps[MAPS_LIB_WL_CTL].add2, p_mq_ref1->u.maps[MAPS_LIB_WL_CTL].add3); } if (p_mq_ref1->u.maps[MAPS_LIB_NVRAM].add1 != 0){ parse_elf(pp_func_root, pp_file_line_root, "./libnvram.so", p_mq_ref1->u.maps[MAPS_LIB_NVRAM].add1, p_mq_ref1->u.maps[MAPS_LIB_NVRAM].add2, p_mq_ref1->u.maps[MAPS_LIB_NVRAM].add3); } if (p_mq_ref1->u.maps[MAPS_LIB_CGI].add1 != 0){ parse_elf(pp_func_root, pp_file_line_root, "./libcgi.so", p_mq_ref1->u.maps[MAPS_LIB_CGI].add1, p_mq_ref1->u.maps[MAPS_LIB_CGI].add2, p_mq_ref1->u.maps[MAPS_LIB_CGI].add3); } act_printf("END MQPS pid:%d name:%s\n", p_mq_ref1->pid, p_mq_ref1->u.maps[MAPS_MAIN].name); act_memleak_add_pid(p_mq_ref1->pid, p_mq_ref1->u.maps[MAPS_MAIN].name); return ACT_RV_SUC; }
int main(int argc, char *argv[]) { FILE *fp; u8 bfr[ALIGNMENT]; if (argc != 9) fail("usage: makeself [type] [version suffix] [version] [vendor id] [auth id] [sdk type] [elf] [self]"); get_type(argv[1]); get_keys(argv[2]); get_version(argv[3]); get_vendor(argv[4]); get_auth(argv[5]); get_sdktype(argv[6]); elf_size = get_filesize(argv[7]); elf = mmap_file(argv[7]); parse_elf(); meta_header_size = 0x80 + ehdr.e_phnum * (0x30 + 0x20 + 0x60) + 0x30; info_offset = 0x70; elf_offset = 0x90; phdr_offset = elf_offset + ehdr.e_ehsize; sec_offset = round_up(phdr_offset + ehdr.e_phentsize * ehdr.e_phnum, ALIGNMENT); version_offset = round_up(sec_offset + ehdr.e_phnum * 0x20, ALIGNMENT); ctrl_offset = round_up(version_offset + 0x10, ALIGNMENT); meta_offset = round_up(ctrl_offset + 0x70, ALIGNMENT); header_size = round_up(meta_offset + meta_header_size, 0x80); shdr_offset = ehdr.e_shoff + header_size; build_sce_hdr(); build_info_hdr(); build_ctrl_hdr(); build_sec_hdr(); build_version_hdr(); build_meta_hdr(); self = malloc(header_size + elf_size); memset(self, 0, header_size + elf_size); build_hdr(); calculate_hashes(); sign_hdr(); sce_encrypt_data(self); sce_encrypt_header(self, &ks); fp = fopen(argv[8], "wb"); if (fp == NULL) fail("fopen(%s) failed", argv[4]); if (fwrite(self, header_size + elf_size, 1, fp) != 1) fail("unable to write self"); memset(bfr, 0, sizeof bfr); fwrite(bfr, round_up(elf_size, ALIGNMENT) - elf_size, 1, fp); fclose(fp); return 0; }
int main(int argc, char **argv) { #if 0 { //system("cat /proc/self/status"); int i; for (i = 0; i < argc; i++) printf("*%s* ", argv[i]); printf("\n"); } #endif if (argc < 2) { fprintf(stderr, "Error fldd: invalid arguments\n"); usage(); exit(1); } if (strcmp(argv[1], "--help") == 0) { usage(); return 0; } // check program access if (access(argv[1], R_OK)) { fprintf(stderr, "Error fldd: cannot access %s\n", argv[1]); exit(1); } char *quiet = getenv("FIREJAIL_QUIET"); if (quiet && strcmp(quiet, "yes") == 0) arg_quiet = 1; if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") ==0) { usage(); return 0; } int fd = STDOUT_FILENO; // attempt to open the file if (argc == 3) { fd = open(argv[2], O_CREAT | O_TRUNC | O_WRONLY, 0644); if (!fd) { fprintf(stderr, "Error fldd: invalid arguments\n"); usage(); exit(1); } } // initialize local storage lib_paths_init(); // process files struct stat s; if (stat(argv[1], &s) == -1) errExit("stat"); if (S_ISDIR(s.st_mode)) walk_directory(argv[1]); else { if (is_lib_64(argv[1])) parse_elf(argv[1]); else fprintf(stderr, "Warning fldd: %s is not a 64bit program/library\n", argv[1]); } // print libraries and exit storage_print(libs, fd); if (argc == 3) close(fd); return 0; }
/* * @func encrypt_ip modifies the content of some sections. * @param INOUT uint8_t* elf_buf, buffer of ELF binary * @param size_t elf_size, size of ELF binary in bytes * @param IN uint8_t* key, AES-GCM-128 key * @param bool debug, true iff enclave is requried to support debug * @return encip_ret_e: * ENCIP_ERROR_ENCRYPTIP_INVALID_PARAM if any input parameter is NULL * Respective error results in case any of the following functions fail: * parse_elf, get_pcl_tbl init_random_iv, encrypt_or_clear_ip_sections or sha256 * ENCIP_ERROR_MEM_ALLOC if memory allocation fails * ENCIP_ERROR_SEALED_BUF_SIZE if sealed buf size exceeds the size allocated for it in PCL table * ENCIP_SUCCESS if success */ encip_ret_e encrypt_ip(INOUT uint8_t* elf_buf, size_t elf_size, IN uint8_t* key, bool debug) { if(NULL == elf_buf || NULL == key) return ENCIP_ERROR_ENCRYPTIP_INVALID_PARAM; encip_ret_e ret = ENCIP_ERROR_FAIL; pcl_data_t dat = { .elf_sec = 0, .shstrndx = 0, .sections_names = NULL, .phdr = NULL, .nsections = 0, .nsegments = 0, }; pcl_table_t* tbl = NULL; ret = parse_elf(elf_buf, elf_size, &dat); if(ENCIP_ERROR(ret)) return ret; ret = get_pcl_tbl(elf_buf, elf_size, &dat, &tbl); if(ENCIP_ERROR(ret)) return ret; // Verify state of binary: if(PCL_CIPHER == tbl->pcl_state) return ENCIP_ERROR_ALREADY_ENCRYPTED; if(PCL_PLAIN != tbl->pcl_state) return ENCIP_ERROR_IMPROPER_STATE; // Encrypt or clear IP sections: uint32_t num_rvas = 0; ret = encrypt_or_clear_ip_sections(&dat, key, elf_buf, elf_size, tbl, &num_rvas, debug); if(ENCIP_ERROR(ret)) return ret; // Set GUID: memcpy(tbl->pcl_guid, g_pcl_guid, sizeof(tbl->pcl_guid)); // Set sealed blob size: tbl->sealed_blob_size = (size_t)sgx_calc_sealed_data_size(SGX_PCL_GUID_SIZE, SGX_AESGCM_KEY_SIZE); // Verify calculated size equals hard coded size of buffer in PCL table: if(PCL_SEALED_BLOB_SIZE != tbl->sealed_blob_size) return ENCIP_ERROR_SEALED_BUF_SIZE; // Set num RVAs: tbl->num_rvas = num_rvas; // Set decryption key sha256 hash result: ret = sha256(key, SGX_AESGCM_KEY_SIZE, tbl->decryption_key_hash); if(ENCIP_ERROR(ret)) return ret; // Set PCL state tbl->pcl_state = PCL_CIPHER; return ENCIP_SUCCESS; } /* * @func print_usage prints sgx_encrypt usage instructions * @param IN char* encip_name is the name of the application */ void print_usage(IN char* encip_name) { printf("\n"); printf("\tUsage: \n"); printf("\t %s -i <input enclave so file name> -o <output enclave so file name> -k <key file name> [-d]\n", encip_name); printf("\t -d (optional) prevents the tool from disabling the debug capabilities\n"); printf("\n"); }
/* returns size of result, or -1 if error. * Note that, with the new code, this function * works for all elf files, not just the restricted set. */ int parse_elf_to_stage(const struct buffer *input, struct buffer *output, enum comp_algo algo, uint32_t *location, const char *ignore_section) { struct parsed_elf pelf; Elf64_Phdr *phdr; Elf64_Ehdr *ehdr; Elf64_Shdr *shdr_ignored; Elf64_Addr virt_to_phys; char *buffer; struct buffer outheader; int ret = -1; int headers; int i, outlen; uint32_t data_start, data_end, mem_end; comp_func_ptr compress = compression_function(algo); if (!compress) return -1; DEBUG("start: parse_elf_to_stage(location=0x%x)\n", *location); int flags = ELF_PARSE_PHDR | ELF_PARSE_SHDR | ELF_PARSE_STRTAB; if (parse_elf(input, &pelf, flags)) { ERROR("Couldn't parse ELF\n"); return -1; } ehdr = &pelf.ehdr; phdr = &pelf.phdr[0]; /* Find the section header corresponding to ignored-section */ shdr_ignored = find_ignored_section_header(&pelf, ignore_section); if (ignore_section && (shdr_ignored == NULL)) WARN("Ignore section not found\n"); headers = ehdr->e_phnum; /* Ignore the program header containing ignored section */ for (i = 0; i < headers; i++) { if (is_phdr_ignored(&phdr[i], shdr_ignored)) phdr[i].p_type = PT_NULL; } data_start = ~0; data_end = 0; mem_end = 0; virt_to_phys = 0; for (i = 0; i < headers; i++) { unsigned int start, mend, rend; if (phdr[i].p_type != PT_LOAD) continue; /* Empty segments are never interesting */ if (phdr[i].p_memsz == 0) continue; /* BSS */ start = phdr[i].p_paddr; mend = start + phdr[i].p_memsz; rend = start + phdr[i].p_filesz; if (start < data_start) data_start = start; if (rend > data_end) data_end = rend; if (mend > mem_end) mem_end = mend; if (virt_to_phys == 0) virt_to_phys = phdr[i].p_paddr - phdr[i].p_vaddr; } if (data_start < *location) { data_start = *location; } if (data_end <= data_start) { ERROR("data ends (%08lx) before it starts (%08lx). Make sure " "the ELF file is correct and resides in ROM space.\n", (unsigned long)data_end, (unsigned long)data_start); exit(1); } /* allocate an intermediate buffer for the data */ buffer = calloc(data_end - data_start, 1); if (buffer == NULL) { ERROR("Unable to allocate memory: %m\n"); goto err; } /* Copy the file data into the buffer */ for (i = 0; i < headers; i++) { unsigned int l_start, l_offset = 0; if (phdr[i].p_type != PT_LOAD) continue; if (phdr[i].p_memsz == 0) continue; l_start = phdr[i].p_paddr; if (l_start < *location) { l_offset = *location - l_start; l_start = *location; } /* A legal ELF file can have a program header with * non-zero length but zero-length file size and a * non-zero offset which, added together, are > than * input->size (i.e. the total file size). So we need * to not even test in the case that p_filesz is zero. */ if (! phdr[i].p_filesz) continue; if (input->size < (phdr[i].p_offset + phdr[i].p_filesz)){ ERROR("Underflow copying out the segment." "File has %zu bytes left, segment end is %zu\n", input->size, (size_t)(phdr[i].p_offset + phdr[i].p_filesz)); free(buffer); goto err; } memcpy(buffer + (l_start - data_start), &input->data[phdr[i].p_offset + l_offset], phdr[i].p_filesz - l_offset); } /* Now make the output buffer */ if (buffer_create(output, sizeof(struct cbfs_stage) + data_end - data_start, input->name) != 0) { ERROR("Unable to allocate memory: %m\n"); free(buffer); goto err; } memset(output->data, 0, output->size); /* Compress the data, at which point we'll know information * to fill out the header. This seems backward but it works because * - the output header is a known size (not always true in many xdr's) * - we do need to know the compressed output size first * If compression fails or makes the data bigger, we'll warn about it * and use the original data. */ if (compress(buffer, data_end - data_start, (output->data + sizeof(struct cbfs_stage)), &outlen) < 0 || (unsigned)outlen > data_end - data_start) { WARN("Compression failed or would make the data bigger " "- disabled.\n"); memcpy(output->data + sizeof(struct cbfs_stage), buffer, data_end - data_start); algo = CBFS_COMPRESS_NONE; } free(buffer); /* Set up for output marshaling. */ outheader.data = output->data; outheader.size = 0; /* Coreboot expects entry point to be physical address. Thus, adjust the * entry point accordingly. */ fill_cbfs_stage(&outheader, algo, ehdr->e_entry + virt_to_phys, data_start, outlen, mem_end - data_start); if (*location) *location -= sizeof(struct cbfs_stage); output->size = sizeof(struct cbfs_stage) + outlen; ret = 0; err: parsed_elf_destroy(&pelf); return ret; }