blob: 093de438d3bfd32b9e6ad15819c7695248481dd1 [file] [log] [blame]
J-Alves6e0abc42024-12-30 16:51:16 +00001/*
2 * Copyright 2024 The Hafnium Authors.
3 *
4 * Use of this source code is governed by a BSD-style
5 * license that can be found in the LICENSE file or at
6 * https://opensource.org/licenses/BSD-3-Clause.
7 */
8
9#include "hf/partition_pkg.h"
10
11#include <stdint.h>
12
13#include "hf/arch/std.h"
14
15#include "hf/addr.h"
16#include "hf/check.h"
17#include "hf/dlog.h"
18#include "hf/mm.h"
19#include "hf/sp_pkg.h"
20#include "hf/std.h"
21#include "hf/transfer_list.h"
22
23static void dump_partition_package(struct partition_pkg *pkg)
24{
25 dlog_verbose("%s: total %lx %lx\n", __func__, pa_addr(pkg->total.begin),
26 pa_addr(pkg->total.end));
27 dlog_verbose("%s: pm: %lx %lx\n", __func__, pa_addr(pkg->pm.begin),
28 pa_addr(pkg->pm.end));
29 dlog_verbose("%s: img: %lx %lx\n", __func__, pa_addr(pkg->img.begin),
30 pa_addr(pkg->img.end));
31 dlog_verbose("%s: boot_info: %lx %lx\n", __func__,
32 pa_addr(pkg->boot_info.begin),
33 pa_addr(pkg->boot_info.end));
34 if (mem_range_is_valid(pkg->hob)) {
35 dlog_verbose("%s: hob %lx %lx\n", __func__,
36 pa_addr(pkg->hob.begin), pa_addr(pkg->hob.end));
37 }
38}
39
40static bool partition_pkg_from_sp_pkg(struct mm_stage1_locked stage1_locked,
41 paddr_t pkg_start,
42 struct partition_pkg *pkg,
43 struct mpool *ppool)
44{
45 struct sp_pkg_header header;
46 bool ret = sp_pkg_init(stage1_locked, pkg_start, &header, ppool);
47 size_t total_mem_size = sp_pkg_get_mem_size(&header);
48
49 pkg->total.begin = pkg_start;
50 pkg->total.end = pa_add(pkg_start, total_mem_size);
51
52 pkg->pm.begin = pa_add(pkg_start, header.pm_offset);
53 pkg->pm.end = pa_add(pkg->pm.begin, header.pm_size);
54
55 pkg->img.begin = pa_add(pkg_start, header.img_offset);
56 pkg->img.end = pa_add(pkg->img.begin, header.img_size);
57
58 /*
59 * Repurpose the first page of the SP Package.
60 * FF-A boot info will overwrite the package, but it doesn't
61 * matter at this stage, given Hafnium already parsed it.
62 */
63 pkg->boot_info.begin = pkg_start;
64 pkg->boot_info.end = pa_add(pkg_start, header.pm_offset);
65
66 /* HOB section doesn't exist in the SP Pkg type. */
67 pkg->hob.begin = pa_init(0);
68 pkg->hob.end = pa_init(0);
69
70 dump_partition_package(pkg);
71
72 /* Map the whole package as RO. */
73 CHECK(mm_identity_map(stage1_locked, pkg->total.begin, pkg->total.end,
74 MM_MODE_R, ppool) != NULL);
75
76 return ret;
77}
78
79bool partition_pkg_init(struct mm_stage1_locked stage1_locked,
80 paddr_t pkg_start, struct partition_pkg *pkg,
81 struct mpool *ppool)
82{
83 bool ret = false;
84 paddr_t pkg_first_page = pa_add(pkg_start, PAGE_SIZE);
85 uint32_t *magic;
86 void *mapped_ptr;
87
88 /* Firstly, map a single page to be able to read package header. */
89 mapped_ptr = mm_identity_map(stage1_locked, pkg_start, pkg_first_page,
90 MM_MODE_R, ppool);
91 assert(mapped_ptr != NULL);
92 assert(pkg != NULL);
93
94 magic = (uint32_t *)mapped_ptr;
95
96 switch (*magic) {
97 case SP_PKG_HEADER_MAGIC:
98 /*
99 * Leave memory mapped in case it succeeded, to be cleared
100 * later.
101 */
102 if (!partition_pkg_from_sp_pkg(stage1_locked, pkg_start, pkg,
103 ppool)) {
104 goto out;
105 }
106 break;
107 default:
108 dlog_error("%s: invalid secure partition package %x @ %lx\n",
109 __func__, *magic, (uint64_t)magic);
110 goto out;
111 }
112
113 dump_partition_package(pkg);
114
115 /**
116 * The total memory range should encompass the remaining.
117 * Assert that none of the memory ranges are out of bounds.
118 */
119 assert(mem_range_contains_range(pkg->total, pkg->img));
120 assert(mem_range_contains_range(pkg->total, pkg->pm));
121 assert(mem_range_contains_range(pkg->total, pkg->boot_info));
122 assert(!mem_range_is_valid(pkg->hob) ||
123 mem_range_contains_range(pkg->total, pkg->hob));
124
125 /* Map Boot info section as RW. */
126 if (pa_addr(pkg->boot_info.begin) != 0U &&
127 pa_addr(pkg->boot_info.end) != 0U) {
128 CHECK(mm_identity_map(stage1_locked, pkg->boot_info.begin,
129 pkg->boot_info.end, MM_MODE_R | MM_MODE_W,
130 ppool) != NULL);
131 }
132
133 ret = true;
134
135out:
136 /* If failing unmap the memory. */
137 if (!ret) {
138 CHECK(mm_unmap(stage1_locked, pkg_start, pkg_first_page,
139 ppool));
140 }
141
142 return ret;
143}
144
145void partition_pkg_deinit(struct mm_stage1_locked stage1_locked,
146 struct partition_pkg *pkg, struct mpool *ppool)
147{
148 CHECK(mm_unmap(stage1_locked, pkg->total.begin, pkg->total.end, ppool));
149}