in nitro_enclaves/ne_ioctl_sample.c [285:396]
static int ne_load_enclave_image(int enclave_fd, struct ne_user_mem_region ne_user_mem_regions[],
char *enclave_image_path)
{
unsigned char *enclave_image = NULL;
int enclave_image_fd = -1;
size_t enclave_image_size = 0;
size_t enclave_memory_size = 0;
unsigned long i = 0;
size_t image_written_bytes = 0;
struct ne_image_load_info image_load_info = {
.flags = NE_EIF_IMAGE,
};
struct stat image_stat_buf = {};
int rc = -EINVAL;
size_t temp_image_offset = 0;
for (i = 0; i < NE_DEFAULT_NR_MEM_REGIONS; i++)
enclave_memory_size += ne_user_mem_regions[i].memory_size;
rc = stat(enclave_image_path, &image_stat_buf);
if (rc < 0) {
printf("Error in get image stat info [%m]\n");
return rc;
}
enclave_image_size = image_stat_buf.st_size;
if (enclave_memory_size < enclave_image_size) {
printf("The enclave memory is smaller than the enclave image size\n");
return -ENOMEM;
}
rc = ioctl(enclave_fd, NE_GET_IMAGE_LOAD_INFO, &image_load_info);
if (rc < 0) {
switch (errno) {
case NE_ERR_NOT_IN_INIT_STATE: {
printf("Error in get image load info, enclave not in init state\n");
break;
}
case NE_ERR_INVALID_FLAG_VALUE: {
printf("Error in get image load info, provided invalid flag\n");
break;
}
default:
printf("Error in get image load info [%m]\n");
}
return rc;
}
printf("Enclave image offset in enclave memory is %lld\n",
image_load_info.memory_offset);
enclave_image_fd = open(enclave_image_path, O_RDONLY);
if (enclave_image_fd < 0) {
printf("Error in open enclave image file [%m]\n");
return enclave_image_fd;
}
enclave_image = mmap(NULL, enclave_image_size, PROT_READ,
MAP_PRIVATE, enclave_image_fd, 0);
if (enclave_image == MAP_FAILED) {
printf("Error in mmap enclave image [%m]\n");
return -1;
}
temp_image_offset = image_load_info.memory_offset;
for (i = 0; i < NE_DEFAULT_NR_MEM_REGIONS; i++) {
size_t bytes_to_write = 0;
size_t memory_offset = 0;
size_t memory_size = ne_user_mem_regions[i].memory_size;
size_t remaining_bytes = 0;
void *userspace_addr = ne_user_mem_regions[i].userspace_addr;
if (temp_image_offset >= memory_size) {
temp_image_offset -= memory_size;
continue;
} else if (temp_image_offset != 0) {
memory_offset = temp_image_offset;
memory_size -= temp_image_offset;
temp_image_offset = 0;
}
remaining_bytes = enclave_image_size - image_written_bytes;
bytes_to_write = memory_size < remaining_bytes ?
memory_size : remaining_bytes;
memcpy(userspace_addr + memory_offset,
enclave_image + image_written_bytes, bytes_to_write);
image_written_bytes += bytes_to_write;
if (image_written_bytes == enclave_image_size)
break;
}
munmap(enclave_image, enclave_image_size);
close(enclave_image_fd);
return 0;
}