RPMB FS流程
具体见注释。
rpmb_fs_open
@optee_os/core/tee/tee_rpmb_fs.c
主要
- 构建struct rpmb_file_handle数据结构指针——文件指针
- 加/解锁
- call
rpmb_fs_open_internal
——open的主要逻辑
static TEE_Result rpmb_fs_open(struct tee_pobj *po, size_t *size,
struct tee_file_handle **ret_fh)
{
TEE_Result res;
//申请一个文件句柄,相当于fopen的FILE指针,po是上层的句柄,在这一层我们要用的是fh
struct rpmb_file_handle *fh = alloc_file_handle(po, po->temporary);
if (!fh)
return TEE_ERROR_OUT_OF_MEMORY;
mutex_lock(&rpmb_mutex);//日常加锁
//真·open
res = rpmb_fs_open_internal(fh, &po->uuid, false);
if (!res && size)
*size = fh->fat_entry.data_size;
mutex_unlock(&rpmb_mutex);//日常解锁
if (res)
free(fh);
else
*ret_fh = (struct tee_file_handle *)fh;
return res;
}
rpmb_fs_open_internal
@optee_os/core/tee/tee_rpmb_fs.c
主要
static TEE_Result rpmb_fs_open_internal(struct rpmb_file_handle *fh,
const TEE_UUID *uuid, bool create)
{
tee_mm_pool_t p;
bool pool_result;
TEE_Result res = TEE_ERROR_GENERIC;
/* We need to do setup in order to make sure fs_par is filled in */
res = rpmb_fs_setup(); //为使用FS的使用做准备,属于初始化动作
if (res != TEE_SUCCESS)
goto out;
fh->uuid = uuid;
if (create) { //如果创建文件
/* Upper memory allocation must be used for RPMB_FS. */
//准备在RPMB中申请一块空间用来存储新文件
pool_result = tee_mm_init(&p,
RPMB_STORAGE_START_ADDRESS,
fs_par->max_rpmb_address,
RPMB_BLOCK_SIZE_SHIFT,
TEE_MM_POOL_HI_ALLOC);
if (!pool_result) {
res = TEE_ERROR_OUT_OF_MEMORY;
goto out;
}
//读取fat表,为新的文件构造表项,fat表是用来管理RPMB FS的元数据
res = read_fat(fh, &p);
tee_mm_final(&p);
if (res != TEE_SUCCESS)
goto out;
} else { //如果不是创建文件
//读取fat表,为新的文件构造表项,fat表是用来管理RPMB FS的元数据
res = read_fat(fh, NULL);
if (res != TEE_SUCCESS)
goto out;
}
/*
* If this is opened with create and the entry found was not active
* then this is a new file and the FAT entry must be written
*/
if (create) { //如果创建文件
if ((fh->fat_entry.flags & FILE_IS_ACTIVE) == 0) { //如果分到的fat表项是没有被使用的
memset(&fh->fat_entry, 0,
sizeof(struct rpmb_fat_entry));
memcpy(fh->fat_entry.filename, fh->filename,
strlen(fh->filename));
/* Start address and size are 0 */
fh->fat_entry.flags = FILE_IS_ACTIVE; //设置fat表项为被使用的
res = generate_fek(&fh->fat_entry, uuid); //生成EFEK,用来给文件数据加密的
if (res != TEE_SUCCESS)
goto out;
DMSG("GENERATE FEK key: %p",
(void *)fh->fat_entry.fek);
DHEXDUMP(fh->fat_entry.fek, sizeof(fh->fat_entry.fek));
res = write_fat_entry(fh, true); //把新建的表项写入RPMB
if (res != TEE_SUCCESS)
goto out;
}
}
res = TEE_SUCCESS;
out:
return res;
}
rpmb_fs_setup
@optee_os/core/tee/tee_rpmb_fs.c
主要:
- 若
fs_par
已经赋值,说明这个结构体填充完了,立刻成功返回,不再初始化 - 获取RPMB分区块数,块大小是
1<<RPMB_BLOCK_SIZE_SHIFT
——256 - 读取
struct rpmb_fs_partition
,确定是否需要重置分区 - (可能会)重置分区
- 为
fs_par
指针申请结构体空间,并给成员赋值
static TEE_Result rpmb_fs_setup(void)
{
TEE_Result res = TEE_ERROR_GENERIC;
struct rpmb_fs_partition *partition_data = NULL;
struct rpmb_file_handle *fh = NULL;
uint32_t max_rpmb_block = 0;
if (fs_par) {
res = TEE_SUCCESS;
goto out;
}
//获取最大块数,后面用来填充fs_par
res = tee_rpmb_get_max_block(CFG_RPMB_FS_DEV_ID, &max_rpmb_block);
if (res != TEE_SUCCESS)
goto out;
partition_data = calloc(1, sizeof(struct rpmb_fs_partition));
if (!partition_data) {
res = TEE_ERROR_OUT_OF_MEMORY;
goto out;
}
//读取RPMB中最开始的那段数据,解析为struct rpmb_fs_partition
res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID, RPMB_STORAGE_START_ADDRESS,
(uint8_t *)partition_data,
sizeof(struct rpmb_fs_partition), NULL, NULL);
if (res != TEE_SUCCESS)
goto out;
#ifndef CFG_RPMB_RESET_FAT
if (partition_data->rpmb_fs_magic == RPMB_FS_MAGIC) { //核对魔数
if (partition_data->fs_version == FS_VERSION) { //核对版本
res = TEE_SUCCESS;
goto store_fs_par; // 正常情况会走这里
} else { //版本不对就不能访问
/* Wrong software is in use. */
res = TEE_ERROR_ACCESS_DENIED;
goto out;
}
}
#else
EMSG("**** Clearing Storage ****"); //正常不会走这里,这里会重置RPMB分区
#endif
//下面开始重置RPMB分区
/* Setup new partition data. */
partition_data->rpmb_fs_magic = RPMB_FS_MAGIC;
partition_data->fs_version = FS_VERSION;
partition_data->fat_start_address = RPMB_FS_FAT_START_ADDRESS; //512
/* Initial FAT entry with FILE_IS_LAST_ENTRY flag set. */
fh = alloc_file_handle(NULL, false); //准备写入一个fat表项
if (!fh) {
res = TEE_ERROR_OUT_OF_MEMORY;
goto out;
}
fh->fat_entry.flags = FILE_IS_LAST_ENTRY; //这个表项标记为最后一项
fh->rpmb_fat_address = partition_data->fat_start_address;
/* Write init FAT entry and partition data to RPMB. */
res = write_fat_entry(fh, true); //写入这个唯一的表项,这个表项对应的范围是从512开始所有空间
if (res != TEE_SUCCESS)
goto out;
//记下目前的write counter,在TEE OS里面好像没什么用
res =
tee_rpmb_get_write_counter(CFG_RPMB_FS_DEV_ID,
&partition_data->write_counter);
if (res != TEE_SUCCESS)
goto out;
//将新的struct rpmb_fs_partition写进去
res = tee_rpmb_write(CFG_RPMB_FS_DEV_ID, RPMB_STORAGE_START_ADDRESS,
(uint8_t *)partition_data,
sizeof(struct rpmb_fs_partition), NULL, NULL);
#ifndef CFG_RPMB_RESET_FAT
store_fs_par: //正常情况会从上面直接跳到这里
#endif
//开始填充fs_par
/* Store FAT start address. */
fs_par = calloc(1, sizeof(struct rpmb_fs_parameters));
if (!fs_par) {
res = TEE_ERROR_OUT_OF_MEMORY;
goto out;
}
//就填充这两个东西:fat表起始位置+RPMB分区最后一块的地址
fs_par->fat_start_address = partition_data->fat_start_address;
fs_par->max_rpmb_address = max_rpmb_block << RPMB_BLOCK_SIZE_SHIFT;
dump_fat();
out:
free(fh);
free(partition_data);
return res;
}