int flash_emu_dev_create (struct node *bdev_node, /*const*/ char *flash_node_path) { struct flash_dev *flash; struct block_dev * bdev; size_t block_size, factor; if(NULL == (bdev = (struct block_dev *) bdev_node->nas->fi->privdata)) { return -ENOTBLK; } flash = flash_create(flash_node_path, bdev->size); if(err(flash)) { return err(flash); } flash->privdata = bdev; /* XXX */ flash->block_info.block_size = FLASH_ERASE_BLOCK_SIZE; block_size = bdev->driver->ioctl(bdev, IOCTL_GETBLKSIZE, NULL, 0); factor = FLASH_ERASE_BLOCK_SIZE / block_size; if(0 == factor) { factor++; } flash->block_info.blocks = bdev->driver->ioctl(bdev, IOCTL_GETDEVSIZE, NULL, 0); flash->block_info.blocks /= factor; flash->start = 0; flash->end = bdev->size; flash->drv = &flash_emu_drv; return 0; }
int parse_flash_partition(uint8_t *data, unsigned int length, const char *partition_name, uint32_t offset, const char *filepath, int detected_device) { struct flash_file *flash; int file_device; flash = flash_create(data, length); if(!flash) { fprintf(stderr, "%s: Memory error\n", program); return 0; } switch(flash->header->magic) { case AOS_ZMfX_MAGIC: { if(verbose) printf("\t%s: Stage 2 bootloader\n", filepath); break; } case AOS_KERNEL_MAGIC: { if(verbose) printf("\t%s: Kernel (zImage+initramfs)\n", filepath); break; } case AOS_GZIP_MAGIC: { if(verbose) printf("\t%s: Boot Logo\n", filepath); break; } default: { if(offset == 0x3f8000 || offset == 0x000000) { // We know those are never signed, so we don't warn about them flash_free(flash); return 0; } printf("\t%s: Unknown magic, this is weird.\n", filepath); flash_free(flash); return 0; } } if(flash->header->magic != AOS_GZIP_MAGIC) { if(flash->header->bits != 0x400) { if(verbose) printf("\t%s: Signature is 0 bits long (SDE Firmware?).\n", filepath); } else { if(!flash_is_signed(flash)) { if(verbose) printf("\t%s: File is not signed.\n", filepath); } else { if(!flash_detect_key(flash, Bootloader_Keys, MPK_KNOWN_DEVICES, &file_device)) { printf("WARNING: %s: Signature is not valid.\n", filepath); } else { if(detected_device != file_device) { printf("WARNING: %s: The detected device type for this file does not match the .aos device type (detected %s).\n", filepath, mpk_device_type(file_device)); } else { if(verbose) printf("\t%s: Signature is valid, detected device type %s.\n", filepath, mpk_device_type(file_device)); } } } } } if(flash->header->magic == AOS_KERNEL_MAGIC) { unsigned int gz_length; uint8_t *gz_data; char *folder_name; char *device_shortname; gz_data = (uint8_t *)flash->header+flash->header->cpio; gz_length = (flash->length - flash->header->cpio); if(*(uint32_t *)gz_data == AOS_GZIP_MAGIC) { folder_name = strdup((const char *)&gz_data[10]); if(endswith(folder_name, ".cpio")) folder_name[strlen(folder_name)-strlen(".cpio")] = 0; } else if((*(uint32_t *)gz_data & AOS_GZIP_NONAME_MASK) == AOS_GZIP_NONAME_MAGIC) { folder_name = bprintf("%s", partition_name); } else { printf("error: Could not find GZIP magic at given offset in %s.\n", filepath); flash_free(flash); return 0; } switch(detected_device) { case MPK_DEVICE_A5: device_shortname = "a5"; break; case MPK_DEVICE_A5IT: device_shortname = "a5it"; break; case MPK_DEVICE_A3GP: device_shortname = "a3g"; break; default: device_shortname = "unk"; break; } // Unpack script log_write("unpack.sh", "## zImage+initramfs: %s\n", filepath); log_write("unpack.sh", "rm -f -r unpacked/%s/\n", folder_name); log_write("unpack.sh", "mkdir -p unpacked/%s/initramfs/\n", folder_name); log_write("unpack.sh", "aos-unpack %s --%s --output unpacked/%s/ --zimage zImage --initramfs initramfs.cpio.gz\n", filepath, device_shortname, folder_name); log_write("unpack.sh", "gunzip --decompress unpacked/%s/initramfs.cpio.gz\n", folder_name); log_write("unpack.sh", "(cd unpacked/%s/initramfs/ && cpio -i -d -H newc -F ../initramfs.cpio --no-absolute-filenames)\n", folder_name, folder_name); log_write("unpack.sh", "rm unpacked/%s/initramfs.cpio\n", folder_name); log_write("unpack.sh", "\n"); // Repack script log_write("repack.sh", "## zImage+initramfs: %s\n", filepath); log_write("repack.sh", "(cd unpacked/%s/initramfs/ && find . | cpio -o -H newc -F ../initramfs.cpio)\n", folder_name); log_write("repack.sh", "rm -f -r unpacked/%s/initramfs/\n", folder_name); log_write("repack.sh", "gzip --name --best unpacked/%s/initramfs.cpio\n", folder_name); log_write("repack.sh", "aos-repack --kernel --output %s --zimage unpacked/%s/zImage --initramfs unpacked/%s/initramfs.cpio.gz\n", filepath, folder_name, folder_name); log_write("repack.sh", "rm -f -r unpacked/%s/\n", folder_name); log_write("repack.sh", "\n"); free(folder_name); } else if(flash->header->magic == AOS_GZIP_MAGIC) { const char *gz_name = (const char *)&data[10]; log_write("unpack.sh", "## .gz: %s\n", filepath); log_write("unpack.sh", "mkdir -p unpacked/\n", gz_name); log_write("unpack.sh", "rm -f unpacked/%s\n", gz_name); log_write("unpack.sh", "cp %s unpacked/%s.gz\n", filepath, gz_name); log_write("unpack.sh", "gunzip -d unpacked/%s.gz\n", gz_name); log_write("unpack.sh", "\n"); log_write("repack.sh", "## .gz: %s\n", filepath); log_write("repack.sh", "gzip -N --best unpacked/%s\n", gz_name); log_write("repack.sh", "cp unpacked/%s.gz %s\n", gz_name, filepath); log_write("repack.sh", "rm -f unpacked/%s.gz\n", gz_name); log_write("repack.sh", "\n"); } flash_free(flash); return 1; }
int parse_cramfs_archive(const char *filename, uint8_t *data, unsigned int length, const char *filepath, int detected_device) { struct flash_file *flash; int file_device; char cramfs_name[2048]; flash = flash_create(data, length); if(!flash) { fprintf(stderr, "%s: Memory error\n", program); return 0; } if(flash->header->magic != AOS_CRAMFS_MAGIC) { fprintf(stderr, "%s: Invalid Cramfs magic on file.\n", filename); flash_free(flash); return 0; } if(!flash_detect_key(flash, Bootloader_Keys, MPK_KNOWN_DEVICES, &file_device)) { printf("WARNING: %s: Signature is invalid.\n", filename); } else { if(detected_device != file_device) { printf("WARNING: %s: The detected device type for this file does not match the .aos device type (detected %s).\n", filename, mpk_device_type(file_device)); } else { if(verbose) printf("\t%s: Signature is valid, detected device type %s\n", filename, mpk_device_type(file_device)); } } strcpy(cramfs_name, filename); cramfs_name[strlen(cramfs_name)-strlen(".secure")] = 0; log_write("unpack.sh", "## .cramfs.secure: %s\n", filepath); log_write("unpack.sh", "rm -f -r unpacked/%s\n", cramfs_name); log_write("unpack.sh", "mkdir -p unpacked\n"); if(*(uint32_t *)&flash->header->data[0] == 0x28cd3d45 /* CRAMFS_MAGIC */) { /* this is a cramfs with a small header (0x100 bytes), which is nonstandard for a cramfs file. */ log_write("unpack.sh", "dd if=%s of=unpacked/%s.stripped bs=256 skip=1\n", filepath, cramfs_name); log_write("unpack.sh", "(cd unpacked/ && cramfsck -v -x %s %s.stripped)\n", cramfs_name, cramfs_name); log_write("unpack.sh", "rm unpacked/%s.stripped\n", cramfs_name); } else { /* this is a cramfs file with either no header or a standard cramfs header (0x200 bytes). */ log_write("unpack.sh", "cramfsck -x unpacked/%s %s\n", cramfs_name, filepath); } log_write("unpack.sh", "\n"); log_write("repack.sh", "## .cramfs.secure: %s\n", filepath); if(*(uint32_t *)&flash->header->data[0] == 0x28cd3d45 /* CRAMFS_MAGIC */) { log_write("repack.sh", "mkcramfs unpacked/%s unpacked/%s.tmp\n", cramfs_name, cramfs_name); log_write("repack.sh", "rm -f -r unpacked/%s\n", cramfs_name); log_write("repack.sh", "aos-fix --add-header unpacked/%s.tmp\n", cramfs_name); log_write("repack.sh", "mv unpacked/%s.tmp unpacked/%s.secure\n", cramfs_name, cramfs_name); } else { // create a cramfs with padding for the header, and write the header in-place log_write("repack.sh", "mkcramfs -p unpacked/%s unpacked/%s.secure\n", cramfs_name, cramfs_name); log_write("repack.sh", "rm -f -r unpacked/%s\n", cramfs_name); log_write("repack.sh", "aos-fix --add-header --overwrite unpacked/%s.secure\n", cramfs_name); } log_write("repack.sh", "mv unpacked/%s.secure %s\n", cramfs_name, filepath); log_write("repack.sh", "\n"); flash_free(flash); return 1; }