1 /*
2  * Copyright (C) 2018-2022 Intel Corporation.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <types.h>
8 #include <asm/cpu.h>
9 #include <asm/pgtable.h>
10 #include <rtl.h>
11 #include <asm/seed.h>
12 #include "seed_abl.h"
13 
14 #define ABL_SEED_LEN 32U
15 struct abl_seed_info {
16 	uint8_t svn;
17 	uint8_t reserved[3];
18 	uint8_t seed[ABL_SEED_LEN];
19 };
20 
21 #define ABL_SEED_LIST_MAX 4U
22 struct abl_svn_seed {
23 	uint32_t size_of_this_struct;
24 	uint32_t version;
25 	uint32_t num_seeds;
26 	struct abl_seed_info seed_list[ABL_SEED_LIST_MAX];
27 };
28 
29 /*
30  * parse_seed_abl
31  *
32  * description:
33  *    This function parse seed_list which provided by ABL.
34  *
35  * input:
36  *    cmdline       pointer to cmdline string
37  *
38  * output:
39  *    phy_seed      pointer to physical seed structure
40  *
41  * return value:
42  *    true if parse successfully, otherwise false.
43  */
parse_seed_abl(uint64_t addr,struct physical_seed * phy_seed)44 bool parse_seed_abl(uint64_t addr, struct physical_seed *phy_seed)
45 {
46 	uint32_t i;
47 	uint32_t legacy_seed_index = 0U;
48 	struct seed_info *seed_list;
49 	struct abl_svn_seed *abl_seed = (struct abl_svn_seed *)hpa2hva(addr);
50 	bool status = false;
51 
52 	if ((phy_seed != NULL) && (abl_seed != NULL) &&
53 	    (abl_seed->num_seeds >= 2U) && (abl_seed->num_seeds <= ABL_SEED_LIST_MAX)) {
54 
55 		seed_list = phy_seed->seed_list;
56 		/*
57 		 * The seed_list from ABL contains several seeds which based on SVN
58 		 * and one legacy seed which is not based on SVN. The legacy seed's
59 		 * svn value is minimum in the seed list. And CSE ensures at least two
60 		 * seeds will be generated which will contain the legacy seed.
61 		 * Here find the legacy seed index first.
62 		 */
63 		for (i = 1U; i < abl_seed->num_seeds; i++) {
64 			if (abl_seed->seed_list[i].svn < abl_seed->seed_list[legacy_seed_index].svn) {
65 				legacy_seed_index = i;
66 			}
67 		}
68 
69 		/*
70 		 * Copy out abl_seed for trusty and clear the original seed in memory.
71 		 * The Service VM requires the legacy seed to derive RPMB key. So skip the
72 		 * legacy seed when clear original seed.
73 		 */
74 		(void)memset((void *)&phy_seed->seed_list[0U], 0U, sizeof(phy_seed->seed_list));
75 		for (i = 0U; i < abl_seed->num_seeds; i++) {
76 			seed_list[i].cse_svn = abl_seed->seed_list[i].svn;
77 			(void)memcpy_s((void *)&seed_list[i].seed[0U], sizeof(seed_list[i].seed),
78 					(void *)&abl_seed->seed_list[i].seed[0U], sizeof(abl_seed->seed_list[i].seed));
79 
80 			if (i == legacy_seed_index) {
81 				continue;
82 			}
83 
84 			(void)memset((void *)&abl_seed->seed_list[i].seed[0U], 0U,
85 							sizeof(abl_seed->seed_list[i].seed));
86 		}
87 
88 		phy_seed->num_seeds = abl_seed->num_seeds;
89 		status = true;
90 	}
91 
92 	return status;
93 }
94