From 1b527e52a399f5dd7d57272774f629647d66cfd4 Mon Sep 17 00:00:00 2001 From: Qi Yadong Date: Mon, 23 Jul 2018 12:34:38 +0800 Subject: [PATCH] HV: parse seed through cmdline during boot stage 1. Add strstr_s in lib to support locate substring in a string 2. Parse "ImageBootParamsAddr=" from cmdline and retrieve seed 3. Convert the addresses to SOS GPA since they will be used in SOS. Signed-off-by: Qi Yadong Reviewed-by: Wang Kai Acked-by: Zhu Bing Acked-by: Anthony Xu Acked-by: Eddie Dong --- hypervisor/boot/sbl/multiboot.c | 109 ++++++++++++++++++++++++++++++-- hypervisor/include/lib/rtl.h | 2 + hypervisor/lib/string.c | 67 ++++++++++++++++++++ 3 files changed, 174 insertions(+), 4 deletions(-) diff --git a/hypervisor/boot/sbl/multiboot.c b/hypervisor/boot/sbl/multiboot.c index 5b4e0d868..5d6480e21 100644 --- a/hypervisor/boot/sbl/multiboot.c +++ b/hypervisor/boot/sbl/multiboot.c @@ -13,6 +13,18 @@ #define ACRN_DBG_BOOT 6U +#define MAX_BOOT_PARAMS_LEN 64U + +static const char *boot_params_arg = "ImageBootParamsAddr="; + +struct image_boot_params { + uint32_t size_of_this_struct; + uint32_t version; + uint64_t p_seed_list; + uint64_t p_platform_info; + uint64_t reserved; +}; + /* There are two sources for vm0 kernel cmdline: * - cmdline from sbl. mbi->cmdline * - cmdline from acrn stitching tool. mod[0].mm_string @@ -106,6 +118,76 @@ static void *get_kernel_load_addr(void *kernel_src_addr) return kernel_src_addr; } +/* + * parse_image_boot_params + * + * description: + * This function parse image_boot_params from cmdline. Mainly on + * 1. parse structure address from cmdline + * 2. get seed_list address and call function to parse seed + * 3. convert address in the structure from HPA to SOS's GPA + * 4. clear original image_boot_params argument in cmdline since + * original address is HPA, need to convert and append later + * when compose kernel command line. + * + * input: + * vm pointer to vm structure + * cmdline pointer to cmdline string + * + * return value: + * boot_params HVA of image_boot_params if parse success, or + * else a NULL pointer. + */ +static void *parse_image_boot_params(struct vm *vm, char *cmdline) +{ + char *arg, *arg_end; + char *param; + uint32_t len; + struct image_boot_params *boot_params; + + if (cmdline == NULL) { + goto fail; + } + + len = strnlen_s(boot_params_arg, MAX_BOOT_PARAMS_LEN); + arg = strstr_s(cmdline, MEM_2K, boot_params_arg, len); + if (arg == NULL) { + goto fail; + } + + param = arg + len; + boot_params = (struct image_boot_params *)HPA2HVA(strtoul_hex(param)); + if (boot_params == NULL) { + goto fail; + } + + parse_seed_list((struct seed_list_hob *)HPA2HVA( + boot_params->p_seed_list)); + + /* + * Convert the addresses to SOS GPA since this structure will be used + * in SOS. + */ + boot_params->p_seed_list = hpa2gpa(vm, boot_params->p_seed_list); + boot_params->p_platform_info = + hpa2gpa(vm, boot_params->p_platform_info); + + /* + * Replace original arguments with spaces since SOS's GPA is not + * identity mapped to HPA. The argument will be appended later when + * compose cmdline for SOS. + */ + arg_end = strchr(arg, ' '); + len = arg_end ? (uint32_t)(arg_end - arg) : strnlen_s(arg, MEM_2K); + memset(arg, ' ', len); + + return (void *)boot_params; + +fail: + parse_seed_list(NULL); + return NULL; +} + /** * @param[inout] vm pointer to a vm descriptor * @@ -157,13 +239,32 @@ int init_vm0_boot_info(struct vm *vm) */ if ((mbi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE) != 0U) { char *cmd_src, *cmd_dst; - uint32_t off; + uint32_t off = 0U; + void *boot_params_addr; + char buf[MAX_BOOT_PARAMS_LEN]; cmd_dst = kernel_cmdline; cmd_src = HPA2HVA((uint64_t)mbi->mi_cmdline); - (void)strncpy_s(cmd_dst, MEM_2K, cmd_src, - strnlen_s(cmd_src, MEM_2K)); - off = strnlen_s(cmd_dst, MEM_2K); + + boot_params_addr = parse_image_boot_params(vm, cmd_src); + /* + * Convert ImageBootParamsAddr to SOS GPA and append to + * kernel cmdline + */ + if (boot_params_addr != NULL) { + memset(buf, 0U, sizeof(buf)); + snprintf(buf, MAX_BOOT_PARAMS_LEN, "%s0x%X ", + boot_params_arg, + HVA2GPA(vm, (uint64_t)boot_params_addr)); + (void)strncpy_s(cmd_dst, MEM_2K, buf, + MAX_BOOT_PARAMS_LEN); + off = strnlen_s(cmd_dst, MEM_2K); + } + + cmd_dst += off; + (void)strncpy_s(cmd_dst, MEM_2K - off, cmd_src, + strnlen_s(cmd_src, MEM_2K - off)); + off = strnlen_s(cmd_dst, MEM_2K - off); cmd_dst[off] = ' '; /* insert space */ off += 1U; diff --git a/hypervisor/include/lib/rtl.h b/hypervisor/include/lib/rtl.h index 967e9b4b7..9ab50a37f 100644 --- a/hypervisor/include/lib/rtl.h +++ b/hypervisor/include/lib/rtl.h @@ -42,6 +42,8 @@ int udiv32(uint32_t dividend, uint32_t divisor, struct udiv_result *res); int atoi(const char *str); long strtol_deci(const char *nptr); uint64_t strtoul_hex(const char *nptr); +char *strstr_s(const char *str1, size_t maxlen1, + const char *str2, size_t maxlen2); /** * Frequency of TSC in KHz (where 1KHz = 1000Hz). Only valid after diff --git a/hypervisor/lib/string.c b/hypervisor/lib/string.c index b333e7b32..b58f61bc9 100644 --- a/hypervisor/lib/string.c +++ b/hypervisor/lib/string.c @@ -393,3 +393,70 @@ int strncmp(const char *s1, const char *s2, size_t n_arg) return *s1 - *s2; } + +/* + * strstr_s + * + * description: + * Search str2 in str1 + * + * input: + * str1 pointer to string to be searched for the substring. + * + * maxlen1 maximum length of str1. + * + * str2 pointer to the sub-string. + * + * maxlen2 maximum length of str2. + * + * return value: + * Pointer to the first occurrence of str2 in str1, + * or return null if not found. + */ +char *strstr_s (const char *str1, size_t maxlen1, + const char *str2, size_t maxlen2) +{ + size_t len1, len2; + size_t i; + + if ((str1 == NULL) || (str2 == NULL)) { + return NULL; + } + + if ((maxlen1 == 0U) || (maxlen2 == 0U)) { + return NULL; + } + + len1 = strnlen_s(str1, maxlen1); + len2 = strnlen_s(str2, maxlen2); + + if (len1 == 0U) { + return NULL; + } + + /* + * str2 points to a string with zero length, or + * str2 equals str1, return str1 + */ + if (len2 == 0U || str1 == str2) { + return (char *)str1; + } + + while (len1 >= len2) { + for (i=0U; i