static int ne_load_enclave_image()

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;
}