occlum/demos/runtime_boot/README.md

91 lines
3.6 KiB
Markdown

# Runtime boot pre-generated UnionFS image
Generally, every Occlum instance has to pass the `Occlum build` process.
In some scenarios, mount and boot a pre-generated UnionFS image without `Occlum build` is a good feature. This demo introduces a way to runtime boot a BASH demo.
## Flow
### First, build a [`BASH`](../bash) Occlum instance
The later step will use the image content to generate UnionFS image.
### Build and start a [`gen_rootfs`](./gen_rootfs) Occlum instance
This `gen_rootfs` mounts a empty **sefs** (uses the lower path as mount target dir), copy the BASH Occlum image content to the mount point, unmount the **sefs**. It generates an encrypted **sefs** image containing the BASH image content. The **key** used in this demo is `"c7-32-b3-ed-44-df-ec-7b-25-2d-9a-32-38-8d-58-61"`.
### Build customized [`init`](./init)
Occlum [`default init`](../../tools/init) calls syscall (363) `MountRootFS` to mount and boot Occlum instance generated by normal `occlum build`.
```
(MountRootFS = 363) => do_mount_rootfs(key_ptr: *const sgx_key_128bit_t, rootfs_config: *const user_rootfs_config)
```
The first parameter `key_ptr` is optional.
The second parameter `rootfs_config` needs to be set as NULL.
But for runtime booting pre-generated image, The first parameter `key_ptr` is must to have, the second parameter `rootfs_config` needs have valid members.
```
struct user_rootfs_config {
// length of the struct
len: usize,
// UnionFS type rootfs upper layer, read-write layer
upper_layer_path: *const i8,
// UnionFS type rootfs lower layer, read-only layer
lower_layer_path: *const i8,
entry_point: *const i8,
// HostFS source path
hostfs_source: *const i8,
// HostFS target path, default value is "/host"
hostfs_target: *const i8,
// An array of pointers to null-terminated strings
// and must be terminated by a null pointer
envp: *const *const i8,
}
```
In this demo, parameters values are provided as below.
* **len**
The length of the struct which should be the value of `size_of(user_rootfs_config)`.
It is helpful for possible future extension.
* **rootfs_key**
The key to encrypt/decrypt the rootfs, here it is `"c7-32-b3-ed-44-df-ec-7b-25-2d-9a-32-38-8d-58-61".
* **rootfs_upper_layer**
The upper layer path of the unionfs type rootfs. In this case, it is relative path `"../gen_rootfs_instance/mnt_unionfs/upper"`.
* **rootfs_lower_layer**
The lower layer path of the unionfs type rootfs. In this case, it is relative path `"../gen_rootfs_instance/mnt_unionfs/lower"`.
* **rootfs_entry**
The entry point of the rootfs. In his case, it is `"/bin"`.
* **hostfs_source**
It is set to be `/tmp` in this case.
* **envp**
An array of pointers to null-terminated strings and must be terminated by a null pointer.
For example, set it to the address of ["TEST=1234", "TEST2=4567", NULL].
In this example customized init, the above parameters are declared in the source [`main.rs`](./init/src/main.rs). In real case, they could be acquired by LA/RA or by modifying the PAL api `pal_run_init_process`.
### Build a boot template Occlum instance
This template uses the customized init. The RootFS image is not important, which will be replaced during boot.
All above steps could be done with one [`script`](./build_content.sh).
```
./build_content.sh
```
After running the script, runtime boot BASH could be done as below even if the default RootFS image has no BASH function.
```
# cd boot_instance
# occlum run /bin/occlum_bash_test.sh
```
Also, the runtime environment passed by **envp** could be verified by
```
# occlum run /bin/busybox env
```