如何编译生成system镜像
- 首先来看编译过程中的log输出,并结合log输出可以一窥究竟。
不知道csdn咋回事,上传的图片一点儿都清晰。。输出的log可以参照末尾该处的信息
- 编译生成verity_medatata.img的核心python代码如下
编译生成system verity_medatata的关键python代码system/extras/verity/build_verity_metadata.py
VERSION = 0
MAGIC_NUMBER = 0xb001b001
BLOCK_SIZE = 4096
METADATA_SIZE = BLOCK_SIZE * 8
def build_verity_table(block_device, data_blocks, root_hash, salt):
table = "1 %s %s %s %s %s %s sha256 %s %s"
table %= ( block_device,
block_device,
BLOCK_SIZE,
BLOCK_SIZE,
data_blocks,
data_blocks,
root_hash,
salt)
return table
各个成员分别代表的含义:
Field | Purpose | Size | Value |
---|---|---|---|
magic number | used by fs_mgr as a sanity check | 4 bytes | 0xb001b001 |
version | used to version the metadata block | 4 bytes | current 0 |
signature | the signature of the table PKCS1.5 padded from | 256 bytes | |
table length | the length of the dm-verity table in bytes | 4 bytes | |
table | the dm-verity table described earlier | ‘table length’ bytes | |
padding | this structure is 0-padded to 32k in length | 0 |
- 编译过程的示意图
- 编译生成fecdata信息的关键代码
相关数据结构system/extras/libfec/include/fec/io.h
#define FEC_BLOCKSIZE 4096
#define FEC_DEFAULT_ROOTS 2
#define FEC_MAGIC 0xFECFECFE
#define FEC_VERSION 0
/* disk format for the header */
struct fec_header {
uint32_t magic;
uint32_t version;
uint32_t size;
uint32_t roots;
uint32_t fec_size;
uint64_t inp_size;
uint8_t hash[SHA256_DIGEST_LENGTH];
};
struct fec_verity_metadata {
bool disabled;
uint64_t data_size;
uint8_t signature[RSANUMBYTES];
uint8_t ecc_signature[RSANUMBYTES];
const char *table;
uint32_t table_length;
};
通过dump镜像来看信息
我是分割线。。。。。。
上面的两张图说的比较清楚了,就不在赘述其计算过程。
通过代码来研究
system/extras/libfec/fec_open.cpp
system/core/fs_mgr/fs_mgr_verity.cpp
其中核心代码片段如下所示
//system/core/fs_mgr/fs_mgr_verity.cpp
int fs_mgr_setup_verity(struct fstab_rec *fstab){
alignas(dm_ioctl) char buffer[DM_BUF_SIZE];
struct dm_ioctl *io = (struct dm_ioctl *) buffer;
char *mount_point = basename(fstab->mount_point);
if (fec_open(&f, fstab->blk_device, O_RDONLY, FEC_VERITY_DISABLE,
FEC_DEFAULT_ROOTS) < 0) {
ERROR("Failed to open '%s' (%s)\n", fstab->blk_device,
strerror(errno));
return retval;
}
// read verity metadata
if (fec_verity_get_metadata(f, &verity) < 0) {
ERROR("Failed to get verity metadata '%s' (%s)\n", fstab->blk_device,
strerror(errno));
goto out;
}
#ifdef ALLOW_ADBD_DISABLE_VERITY
if (verity.disabled) {
retval = FS_MGR_SETUP_VERITY_DISABLED;
INFO("Attempt to cleanly disable verity - only works in USERDEBUG\n");
goto out;
}
#endif
// read ecc metadata
if (fec_ecc_get_metadata(f, ¶ms.ecc) < 0) {
params.ecc.valid = false;
}
params.ecc_dev = fstab->blk_device;
// get the device mapper fd
if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) {
ERROR("Error opening device mapper (%s)\n", strerror(errno));
goto out;
}
// create the device
if (create_verity_device(io, mount_point, fd) < 0) {
ERROR("Couldn't create verity device!\n");
goto out;
}
// get the name of the device file
if (get_verity_device_name(io, mount_point, fd, &verity_blk_name) < 0) {
ERROR("Couldn't get verity device number!\n");
goto out;
}
if (load_verity_state(fstab, ¶ms.mode) < 0) {
/* if accessing or updating the state failed, switch to the default
* safe mode. This makes sure the device won't end up in an endless
* restart loop, and no corrupted data will be exposed to userspace
* without a warning. */
params.mode = VERITY_MODE_EIO;
}
// verify the signature on the table
if (verify_verity_signature(verity) < 0) {
if (params.mode == VERITY_MODE_LOGGING) {
//....
} else {
//....
}
// activate the device
// 激活创建的mapped device 设备
if (resume_verity_table(io, mount_point, fd) < 0) {
goto out;
}
// mark the underlying block device as read-only
//设置为只读模式
fs_mgr_set_blk_ro(fstab->blk_device);
// assign the new verity block device as the block device
//重新分配verity block设备
free(fstab->blk_device);
fstab->blk_device = verity_blk_name;
verity_blk_name = 0;
// make sure we've set everything up properly
if (test_access(fstab->blk_device) < 0) {
goto out;
}
retval = FS_MGR_SETUP_VERITY_SUCCESS;
}
//system/extras/libfec/fec_open.cpp
/* locates, validates, and loads ecc data from `f->fd' */
static int load_ecc(fec_handle *f){
//此处的data_size 为整个镜像的大小。
//FEC header 大小为4KB(4096 byte)且存放在镜像的最后一个4KB
//故:offset = data_size - FEC_BLOCKSIZE 为 FEC header 的起始地址
uint64_t offset = f->data_size - FEC_BLOCKSIZE;
if (parse_ecc(f, offset) == 0)
//...
}
/* attempts to read an ecc header from `offset', and checks for a
* backup copy at the end of the block if the primary header is
* not valid
*/
static int parse_ecc(fec_handle *f, uint64_t offset){
/* check the primary header at the beginning of the block */
//读取主 fec header中的内容
if (parse_ecc_header(f, offset) == 0) {
return 0;
}
/* check the backup header at the end of the block */
//读取备份的fec内容
//offset+FEC_BLOCKSIZE 就到了文件的末尾
//说明镜像的最后4KB存储的是备份的FEC相关信息
if (parse_ecc_header(f, offset + FEC_BLOCKSIZE - sizeof(fec_header)) == 0) {
//...
}
}
/* attempts to read and validate an ecc header from file position `offset' */
static int parse_ecc_header(fec_handle *f, uint64_t offset){
check(f);
//先判断rsn的值是否在 (0,255)范围内
check(f->ecc.rsn > 0 && f->ecc.rsn < FEC_RSM);
//f->size 要大于 sizeof fec_header
check(f->size > sizeof(fec_header));
debug("offset = %" PRIu64, offset);
//镜像的起始相对地址为0,offset的值必须要小于f->size - sizeof fec_header
if (offset > f->size - sizeof(fec_header)) {
return -1;
}
fec_header header;
/* there's obviously no ecc data at this point, so there is no need to
call fec_pread to access this data */
if (!raw_pread(f, &header, sizeof(fec_header), offset)) {
error("failed to read: %s", strerror(errno));
return -1;
}
/* move offset back to the beginning of the block for validating header */
//TODO:
offset -= offset % FEC_BLOCKSIZE;
/* structure: data | ecc | header */
if (offset < header.fec_size ||
offset - header.fec_size != header.inp_size) {
error("unexpected input size: %" PRIu64 " vs %" PRIu64, offset,
header.inp_size);
return -1;
}
f->data_size = header.inp_size;
f->ecc.blocks = fec_div_round_up(f->data_size, FEC_BLOCKSIZE);
f->ecc.rounds = fec_div_round_up(f->ecc.blocks, f->ecc.rsn);
if (header.fec_size !=
(uint32_t)f->ecc.rounds * f->ecc.roots * FEC_BLOCKSIZE) {
error("inconsistent ecc size %u", header.fec_size);
return -1;
}
f->ecc.size = header.fec_size;
f->ecc.start = header.inp_size;
/* validate encoding data; caller may opt not to use it if invalid */
SHA256_CTX ctx;
SHA256_Init(&ctx);
uint8_t buf[FEC_BLOCKSIZE];
uint32_t n = 0;
uint32_t len = FEC_BLOCKSIZE;
while (n < f->ecc.size) {
if (len > f->ecc.size - n) {
len = f->ecc.size - n;
}
if (!raw_pread(f, buf, len, f->ecc.start + n)) {
error("failed to read ecc: %s", strerror(errno));
return -1;
}
SHA256_Update(&ctx, buf, len);
n += len;
}
uint8_t hash[SHA256_DIGEST_LENGTH];
SHA256_Final(hash, &ctx);
//校验结果
f->ecc.valid = !memcmp(hash, header.hash, SHA256_DIGEST_LENGTH);
}
编译log附件
[ 87% 37962/43356] Target system fs image: out/target/product/chopin/obj/PACKAGING/systemimage_intermediates/system.img
BuildImage: in_dir = out/target/product/chopin/system, out_file = out/target/product/chopin/obj/PACKAGING/systemimage_intermediates/system.img
Running: mkuserimg.sh -s out/target/product/chopin/system
out/target/product/chopin/obj/PACKAGING/systemimage_intermediates/system.img
ext4 system 3666415616
-D out/target/product/chopin/system -L system
out/target/product/chopin/root/file_contexts.bin
make_ext4fs -s -T -1 -S out/target/product/chopin/root/file_contexts.bin
-L system -l 3666415616
-a system out/target/product/chopin/obj/PACKAGING/systemimage_intermediates/system.img
out/target/product/chopin/system out/target/product/chopin/system
Creating filesystem with parameters:
Size: 3666415616
Block size: 4096
Blocks per group: 32768
Inodes per group: 8000
Inode size: 256
Journal blocks: 13986
Label: system
Blocks: 895121
Block groups: 28
Reserved block group size: 223
Created filesystem with 3833/224000 inodes and 328224/895121 blocks
Running ['mkuserimg.sh', '-s', 'out/target/product/chopin/system',
'out/target/product/chopin/obj/PACKAGING/systemimage_intermediates/system.img',
'ext4', 'system', '3666415616',
'-D', 'out/target/product/chopin/system', '-L', 'system',
'out/target/product/chopin/root/file_contexts.bin'
]command, exit code = 0
build_verity_tree -A axxxxxe7e7 out/target/product/chopin/obj/PACKAGING/systemimage_intermediates/system.img /tmp/tmptAeT9M_verity_images/verity.img
system/extras/verity/build_verity_metadata.py 3666415616 /tmp/tmptAeT9M_verity_images/verity_metadata.img
5fdddddd
axxxxxe7e7
/dev/block/bootdevice/by-name/system
verity_signer build/target/product/security/verity.pk8
cat /tmp/tmptAeT9M_verity_images/verity_metadata.img >> /tmp/tmptAeT9M_verity_images/verity.img
fec -e out/target/product/chopin/obj/PACKAGING/systemimage_intermediates/system.img
/tmp/tmptAeT9M_verity_images/verity.img
/tmp/tmptAeT9M_verity_images/verity_fec.img
cat /tmp/tmptAeT9M_verity_images/verity_fec.img >> /tmp/tmptAeT9M_verity_images/verity.img
append2simg out/target/product/chopin/obj/PACKAGING/systemimage_intermediates/system.img /tmp/tmptAeT9M_verity_images/verity.img
[ 87% 37963/43356] Install system fs image: out/target/product/chopin/system.img
out/target/product/chopin/system.img+out/target/product/chopin/obj/PACKAGING/recovery_patch_intermediates/recovery_from_boot.p
maxsize=3802411008 blocksize=135168 total=1343068018 reserve=38522880