# 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 ```