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