char * get(Url *u) { extern Prefs prefs; CURL *curl; CURLcode res; FILE *outfile; char *outfilename = prefs.tmpfile; curl = curl_easy_init(); if (curl) { int success = 0; if (prefs.archive) { outfilename = datestamp_filename(); } outfile = fopen(outfilename, "w"); /* Really, this should have a max counter for retries so we * don't get all spammy with trying to get a broken image * over and over and over */ while (!success) { curl_easy_setopt(curl, CURLOPT_URL, u->urlstring); if (prefs.userpass != NULL) { curl_easy_setopt(curl, CURLOPT_USERPWD, prefs.userpass); } curl_easy_setopt(curl, CURLOPT_FILE, outfile); res = curl_easy_perform(curl); success = verify_image(outfile); } fclose (outfile); curl_easy_cleanup(curl); } return outfilename; }
/* Returns -1 if somethings fails otherwise 0 */ int check_image(char* in){ /* Load an image at given path */ FILE *imageinput; imageinput = fopen(in, "rb"); if (imageinput == NULL){ std::cerr << "[ ERROR ] Image does not exist at given location" << std::endl; return -1; } /* Check if file has contents */ unsigned imagefilesize = get_file_size(imageinput); if (imagefilesize == 0){ std::cerr << "[ ERROR ] Image has no size" << std::endl; return -1; } /* Load image in buffer and close file */ unsigned char* image = NULL; image = (unsigned char*)malloc(imagefilesize); fread(image, imagefilesize, 1, imageinput); fclose(imageinput); /* Extract image header */ boot_img_hdr* hdr = NULL; hdr = (boot_img_hdr*)malloc(sizeof(boot_img_hdr)); memcpy(hdr, image, sizeof(boot_img_hdr)); /* Check if image is an Android bootimage */ if (memcmp((char*)hdr->magic, "ANDROID!", 8) != 0){ std::cerr << "[ ERROR ] File is not an Android boot image" << std::endl; return -1; } /* Load necessary variables from header and delete header */ unsigned kernel_actual; unsigned ramdisk_actual; unsigned imagesize_actual; unsigned dt_actual; unsigned page_size = hdr->page_size; unsigned page_mask = hdr->page_size - 1; kernel_actual = ROUND_TO_PAGE(hdr->kernel_size, page_mask); ramdisk_actual = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask); dt_actual = ROUND_TO_PAGE(hdr->dt_size, page_mask); free(hdr); /* Calculate size of the "real" image */ imagesize_actual = (page_size + kernel_actual + ramdisk_actual + dt_actual) ; /* If the "real" image is bigger than the file, the file is probably corrupted */ if (imagefilesize < imagesize_actual){ std::cerr << "[ ERROR ] File is invalid (is it corrupted?)" << std::endl; return -1; } /* Verify the image. */ verify_image(image, image + imagesize_actual, imagesize_actual); return 0; }
/* Returns -1 if somethings fails otherwise 0 */ int sign_image(char* in, char* out){ /* An int is enough because the partitions shouldn't be bigger than 4GB */ int finalimagesize = 0; /* Load an image at given path */ FILE *imageinput; imageinput = fopen(in, "rb"); if (imageinput == NULL){ std::cerr << "[ ERROR ] Image does not exist at given location" << std::endl; return -1; } /* Check if file has contents */ unsigned imagefilesize = get_file_size(imageinput); if (imagefilesize == 0){ std::cerr << "[ ERROR ] Image has no size" << std::endl; return -1; } /* Extract image header first to determine if the final image is bigger than the orignal */ boot_img_hdr* hdr = NULL; hdr = (boot_img_hdr*)malloc(sizeof(boot_img_hdr)); fread(hdr, sizeof(boot_img_hdr), 1, imageinput); /* Reposition pointer at start */ fseek(imageinput, 0, SEEK_SET); /* Check if image is an Android bootimage */ if (memcmp((char*)hdr->magic, "ANDROID!", 8) != 0){ std::cerr << "[ ERROR ] File is not an Android boot image" << std::endl; return -1; } /* Load necessary variables from header and delete header */ unsigned kernel_actual; unsigned ramdisk_actual; unsigned imagesize_actual; unsigned dt_actual; unsigned page_size = hdr->page_size; unsigned page_mask = hdr->page_size - 1; kernel_actual = ROUND_TO_PAGE(hdr->kernel_size, page_mask); ramdisk_actual = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask); dt_actual = ROUND_TO_PAGE(hdr->dt_size, page_mask); free(hdr); /* Calculate size of the "real" image */ imagesize_actual = (page_size + kernel_actual + ramdisk_actual + dt_actual); /* If the "real" image is bigger than the file, the file is probably corrupted */ if (imagefilesize < imagesize_actual){ std::cerr << "[ ERROR ] File is invalid (is it corrupted?)" << std::endl; return -1; } /* If the file is smaller than the "real" image + one page, a buffer with the size of the image would be too small we need allocate a new bigger one */ if (imagefilesize < imagesize_actual + page_size){ finalimagesize = imagefilesize + page_size; } else { finalimagesize = imagefilesize; } /* Load image in buffer and close file */ unsigned char* image = NULL; image = (unsigned char*)malloc(finalimagesize); fread(image, 1, imagefilesize, imageinput); fclose(imageinput); /* Create output file */ FILE *imageoutput; imageoutput = fopen(out, "wb"); if (imageoutput == NULL){ std::cerr << "[ ERROR ] Can't write output image to disk" << std::endl; return -1; } /* Hash the real image */ unsigned char hash[65]; unsigned char signature[SIGNATURE_SIZE]; memset(signature, 0, SIGNATURE_SIZE); sha256_buffer(image, imagesize_actual, hash); /* Create signature with given hash */ int sig = create_signature(hash, signature); /* If the signature is created successfully AND the signature passes the check, the signature will be written into the image buffer, which will written to the output file */ if (sig != -1){ std::cerr << std::endl << "[ STATUS ] Checking created signature... "; if (verify_image(image, signature, imagesize_actual) == 0){ memcpy(image + imagesize_actual, signature, SIGNATURE_SIZE); fwrite(image, finalimagesize, 1, imageoutput); } } /* Cleanup */ fclose(imageoutput); free(image); /* Final check of the output file */ std::cerr << std::endl << "[ STATUS ] Checking created image... "; check_image(out); return 0; }
int elf_load(struct sys_info *info, const char *filename, const char *cmdline) { Elf_ehdr ehdr; Elf_phdr *phdr = NULL; unsigned long phdr_size; unsigned long checksum_offset; unsigned short checksum = 0; Elf_Bhdr *boot_notes = NULL; int retval = -1; int image_retval; image_name = image_version = NULL; if (!file_open(filename)) goto out; if (lfile_read(&ehdr, sizeof ehdr) != sizeof ehdr) { debug("Can't read ELF header\n"); retval = LOADER_NOT_SUPPORT; goto out; } if (ehdr.e_ident[EI_MAG0] != ELFMAG0 || ehdr.e_ident[EI_MAG1] != ELFMAG1 || ehdr.e_ident[EI_MAG2] != ELFMAG2 || ehdr.e_ident[EI_MAG3] != ELFMAG3 || ehdr.e_ident[EI_CLASS] != ARCH_ELF_CLASS || ehdr.e_ident[EI_DATA] != ARCH_ELF_DATA || ehdr.e_ident[EI_VERSION] != EV_CURRENT || ehdr.e_type != ET_EXEC || !ARCH_ELF_MACHINE_OK(ehdr.e_machine) || ehdr.e_version != EV_CURRENT || ehdr.e_phentsize != sizeof(Elf_phdr)) { debug("Not a bootable ELF image\n"); retval = LOADER_NOT_SUPPORT; goto out; } phdr_size = ehdr.e_phnum * sizeof *phdr; phdr = malloc(phdr_size); file_seek(ehdr.e_phoff); if (lfile_read(phdr, phdr_size) != phdr_size) { printk("Can't read program header\n"); goto out; } if (!check_mem_ranges(info, phdr, ehdr.e_phnum)) goto out; checksum_offset = process_image_notes(phdr, ehdr.e_phnum, &checksum); printk("Loading %s", image_name ? image_name : "image"); if (image_version) printk(" version %s", image_version); printk("...\n"); if (!load_segments(phdr, ehdr.e_phnum, checksum_offset)) goto out; if (checksum_offset) { if (!verify_image(&ehdr, phdr, ehdr.e_phnum, checksum)) goto out; } boot_notes = build_boot_notes(info, cmdline); //debug("current time: %lu\n", currticks()); debug("entry point is %#x\n", ehdr.e_entry); printk("Jumping to entry point...\n"); image_retval = start_elf(ehdr.e_entry & ADDRMASK, virt_to_phys(boot_notes)); // console_init(); FIXME printk("Image returned with return value %#x\n", image_retval); retval = 0; out: if (phdr) free(phdr); if (boot_notes) free(boot_notes); if (image_name) free(image_name); if (image_version) free(image_version); return retval; }
int elf_load(struct sys_info *info, ihandle_t dev, const char *cmdline, void **boot_notes) { Elf_ehdr ehdr; Elf_phdr *phdr = NULL; unsigned long checksum_offset, file_size; unsigned short checksum = 0; int retval = -1; unsigned int offset; image_name = image_version = NULL; /* Mark the saved-program-state as invalid */ feval("0 state-valid !"); fd = open_ih(dev); if (fd == -1) { goto out; } offset = find_elf(&ehdr); if (!offset) { retval = LOADER_NOT_SUPPORT; goto out; } #if DEBUG printk("ELF header:\n"); printk(" ehdr.e_type = %d\n", (int)ehdr.e_type); printk(" ehdr.e_machine = %d\n", (int)ehdr.e_machine); printk(" ehdr.e_version = %d\n", (int)ehdr.e_version); printk(" ehdr.e_entry = 0x%08x\n", (int)ehdr.e_entry); printk(" ehdr.e_phoff = 0x%08x\n", (int)ehdr.e_phoff); printk(" ehdr.e_shoff = 0x%08x\n", (int)ehdr.e_shoff); printk(" ehdr.e_flags = %d\n", (int)ehdr.e_flags); printk(" ehdr.e_ehsize = 0x%08x\n", (int)ehdr.e_ehsize); printk(" ehdr.e_phentsize = 0x%08x\n", (int)ehdr.e_phentsize); printk(" ehdr.e_phnum = %d\n", (int)ehdr.e_phnum); #endif if (ehdr.e_phnum > MAX_HEADERS) { printk ("elfload: too many program headers (MAX_HEADERS)\n"); retval = 0; goto out; } phdr = elf_readhdrs(offset, &ehdr); if (!phdr) goto out; if (!check_mem_ranges(info, phdr, ehdr.e_phnum)) goto out; checksum_offset = process_image_notes(phdr, ehdr.e_phnum, &checksum, offset); printf("Loading %s", image_name ? image_name : "image"); if (image_version) printf(" version %s", image_version); printf("...\n"); if (!load_segments(phdr, ehdr.e_phnum, checksum_offset, offset, &file_size)) goto out; if (checksum_offset) { if (!verify_image(&ehdr, phdr, ehdr.e_phnum, checksum)) goto out; } /* If we are attempting an ELF boot image, we pass a non-NULL pointer into boot_notes and mark the image as elf-boot rather than standard ELF */ if (boot_notes) { *boot_notes = (void *)virt_to_phys(build_boot_notes(info, cmdline)); feval("elf-boot saved-program-state >sps.file-type !"); } else { feval("elf saved-program-state >sps.file-type !"); } //debug("current time: %lu\n", currticks()); debug("entry point is " FMT_elf "\n", addr_fixup(ehdr.e_entry)); // Initialise saved-program-state PUSH(addr_fixup(ehdr.e_entry)); feval("saved-program-state >sps.entry !"); PUSH(file_size); feval("saved-program-state >sps.file-size !"); feval("-1 state-valid !"); out: close_io(fd); if (phdr) free(phdr); if (image_name) free(image_name); if (image_version) free(image_version); return retval; }
int elf_load(struct sys_info *info, const char *filename, const char *cmdline) { Elf_ehdr ehdr; Elf_phdr *phdr = NULL; unsigned long phdr_size; unsigned long checksum_offset; unsigned short checksum = 0; Elf_Bhdr *boot_notes = NULL; int retval = -1; int image_retval; unsigned int offset; image_name = image_version = NULL; if (!file_open(filename)) goto out; for (offset = 0; offset < 16 * 512; offset += 512) { if ((size_t)lfile_read(&ehdr, sizeof ehdr) != sizeof ehdr) { debug("Can't read ELF header\n"); retval = LOADER_NOT_SUPPORT; goto out; } if (ehdr.e_ident[EI_MAG0] == ELFMAG0) break; file_seek(offset); } if (ehdr.e_ident[EI_MAG0] != ELFMAG0 || ehdr.e_ident[EI_MAG1] != ELFMAG1 || ehdr.e_ident[EI_MAG2] != ELFMAG2 || ehdr.e_ident[EI_MAG3] != ELFMAG3 || ehdr.e_ident[EI_CLASS] != ARCH_ELF_CLASS || ehdr.e_ident[EI_DATA] != ARCH_ELF_DATA || ehdr.e_ident[EI_VERSION] != EV_CURRENT || ehdr.e_type != ET_EXEC || !ARCH_ELF_MACHINE_OK(ehdr.e_machine) || ehdr.e_version != EV_CURRENT || ehdr.e_phentsize != sizeof(Elf_phdr)) { debug("Not a bootable ELF image\n"); retval = LOADER_NOT_SUPPORT; goto out; } phdr_size = ehdr.e_phnum * sizeof *phdr; phdr = malloc(phdr_size); file_seek(offset + ehdr.e_phoff); if ((unsigned long)lfile_read(phdr, phdr_size) != phdr_size) { printf("Can't read program header\n"); goto out; } if (!check_mem_ranges(info, phdr, ehdr.e_phnum)) goto out; checksum_offset = process_image_notes(phdr, ehdr.e_phnum, &checksum, offset); printf("Loading %s", image_name ? image_name : "image"); if (image_version) printf(" version %s", image_version); printf("...\n"); if (!load_segments(phdr, ehdr.e_phnum, checksum_offset, offset)) goto out; if (checksum_offset) { if (!verify_image(&ehdr, phdr, ehdr.e_phnum, checksum)) goto out; } boot_notes = build_boot_notes(info, cmdline); //debug("current time: %lu\n", currticks()); debug("entry point is %#llx\n", addr_fixup(ehdr.e_entry)); printf("Jumping to entry point...\n"); #if 0 { extern unsigned int qemu_mem_size; extern char boot_device; void *init_openprom(unsigned long memsize, const char *cmdline, char boot_device); int (*entry)(const void *romvec, int p2, int p3, int p4, int p5); const void *romvec; romvec = init_openprom(qemu_mem_size, cmdline, boot_device); entry = (void *) addr_fixup(ehdr.e_entry); image_retval = entry(romvec, 0, 0, 0, 0); } #else image_retval = start_elf(addr_fixup(ehdr.e_entry), virt_to_phys(boot_notes)); #endif // console_init(); FIXME printf("Image returned with return value %#x\n", image_retval); retval = 0; out: file_close(); if (phdr) free(phdr); if (boot_notes) free(boot_notes); if (image_name) free(image_name); if (image_version) free(image_version); return retval; }