diff --git a/base.mk b/base.mk index 050e529..dc446c1 100644 --- a/base.mk +++ b/base.mk @@ -72,6 +72,9 @@ PRODUCT_COPY_FILES += \ device/phh/treble/twrp/twrp.sh:system/bin/twrp.sh \ device/phh/treble/twrp/busybox-armv7l:system/bin/busybox_phh +PRODUCT_PACKAGES += \ + simg2img_simple + ifneq (,$(wildcard external/exfat)) PRODUCT_PACKAGES += \ mkfs.exfat \ diff --git a/cmds/Android.bp b/cmds/Android.bp index d5d5a77..dd8faf6 100644 --- a/cmds/Android.bp +++ b/cmds/Android.bp @@ -16,3 +16,11 @@ cc_binary { "uevent.cpp", ], } + +cc_binary { + name: "simg2img_simple", + srcs: [ + "simg2img_simple.cpp", + ], + host_supported: true, +} diff --git a/cmds/simg2img_simple.cpp b/cmds/simg2img_simple.cpp new file mode 100644 index 0000000..f8a25a3 --- /dev/null +++ b/cmds/simg2img_simple.cpp @@ -0,0 +1,97 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include + +typedef struct sparse_header { + uint32_t magic; /* 0xed26ff3a */ + uint16_t major_version; /* (0x1) - reject images with higher major versions */ + uint16_t minor_version; /* (0x0) - allow images with higer minor versions */ + uint16_t file_hdr_sz; /* 28 bytes for first revision of the file format */ + uint16_t chunk_hdr_sz; /* 12 bytes for first revision of the file format */ + uint32_t blk_sz; /* block size in bytes, must be a multiple of 4 (4096) */ + uint32_t total_blks; /* total blocks in the non-sparse output image */ + uint32_t total_chunks; /* total chunks in the sparse input image */ + uint32_t image_checksum; /* CRC32 checksum of the original data, counting "don't care" */ + /* as 0. Standard 802.3 polynomial, use a Public Domain */ + /* table implementation */ +} sparse_header_t; + +#define SPARSE_HEADER_MAGIC 0xed26ff3a + +#define CHUNK_TYPE_RAW 0xCAC1 +#define CHUNK_TYPE_FILL 0xCAC2 +#define CHUNK_TYPE_DONT_CARE 0xCAC3 +#define CHUNK_TYPE_CRC32 0xCAC4 + +typedef struct chunk_header { + uint16_t chunk_type; /* 0xCAC1 -> raw; 0xCAC2 -> fill; 0xCAC3 -> don't care */ + uint16_t reserved1; + uint32_t chunk_sz; /* in blocks in output image */ + uint32_t total_sz; /* in bytes of chunk input file including chunk header and data */ +} chunk_header_t; + +/* Following a Raw or Fill or CRC32 chunk is data. + * For a Raw chunk, it's the data in chunk_sz * blk_sz. + * For a Fill chunk, it's 4 bytes of the fill data. + * For a CRC32 chunk, it's 4 bytes of CRC32 + */ + +void nsendfile(int out_fd, int in_fd, size_t count) { + while(count) { + ssize_t res = splice(in_fd, NULL, out_fd, NULL, count, 0); + if(res == 0 || res == -1) exit(112); + count -= res; + } +} + +int main() { + sparse_header_t hdr; + if(read(0, &hdr, sizeof(hdr)) != sizeof(hdr)) exit(1); + if(hdr.magic != SPARSE_HEADER_MAGIC) exit(2); + if(hdr.blk_sz != 4096) exit(6); + if(hdr.major_version != 1) exit(11); + if(hdr.minor_version != 0) exit(12); + if(hdr.file_hdr_sz != 28) exit(13); + if(hdr.chunk_hdr_sz != 12) exit(14); + + char block[4096]; + for(unsigned i=0; i $system + elif [ "$method" == sparse ];then + simg2img_simple > $system + elif [ "$method" == raw ];then + cat > $system + fi + ) && break done sync