blob: 62a08a398263dde03a1fdd08d08f4b1f232edcfa [file] [log] [blame]
J-Alves2f86c1e2022-02-23 18:44:19 +00001/*
2 * Copyright 2022 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/sp_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/std.h"
19
20/*
21 * Function initializes the Secure Partition Package:
22 * - Maps whole region up to image such that Hafnium can parse the FF-A manifest
23 * and can use the first chunk of memory for booting purposes.
24 */
25bool sp_pkg_init(struct mm_stage1_locked stage1_locked, paddr_t pkg_start,
26 struct sp_pkg_header *header, struct mpool *ppool)
27{
28 bool ret = false;
29 paddr_t pkg_end = pa_add(pkg_start, PAGE_SIZE);
30 void *pkg;
31
32 /* Firstly, map a single page of package header. */
33 pkg = mm_identity_map(stage1_locked, pkg_start, pkg_end,
34 MM_MODE_R | MM_MODE_W, ppool);
35 assert(pkg != NULL);
36
37 memcpy_s(header, sizeof(struct sp_pkg_header), pkg,
38 sizeof(struct sp_pkg_header));
39
40 if (header->magic != SP_PKG_HEADER_MAGIC) {
41 dlog_error("Invalid package magic.\n");
42 goto exit_unmap;
43 }
44
45 if (header->version != SP_PKG_HEADER_VERSION) {
46 dlog_error("Invalid package version.\n");
47 goto exit_unmap;
48 }
49
50 if (header->pm_offset % PAGE_SIZE != 0 ||
51 header->img_offset % PAGE_SIZE != 0) {
52 dlog_error("SP pkg offsets are not page aligned.\n");
53 goto exit_unmap;
54 }
55
56 if (header->pm_offset > header->img_offset) {
57 dlog_error(
58 "SP pkg offsets must be in order: boot info < "
59 "partition manifest < image offset.\n");
60 goto exit_unmap;
61 }
62
63 /*
64 * Check for overflow and then check the pm shouldn't override the
65 * image.
66 */
67 assert(UINT32_MAX - header->pm_offset >= header->pm_size);
68 if (header->pm_offset + header->pm_size > header->img_offset) {
69 dlog_error("Partition manifest bigger than its region.\n");
70 goto exit_unmap;
71 }
72
73 /*
74 * Remap section up to pm as RW, to allow for writing of boot info
75 * descriptors, if the SP specified boot info in its manifest.
76 */
77 if (header->pm_offset > PAGE_SIZE) {
78 pkg_end = pa_add(pkg_start, header->pm_offset);
79 CHECK(mm_identity_map(stage1_locked, pkg_start, pkg_end,
80 MM_MODE_R | MM_MODE_W, ppool) != NULL);
81 }
82
83 CHECK(mm_identity_map(stage1_locked, pkg_end,
84 pa_add(pkg_end, header->pm_size), MM_MODE_R,
85 ppool) != NULL);
86
87 ret = true;
88
89exit_unmap:
90 if (!ret) {
91 CHECK(mm_unmap(stage1_locked, pkg_start, pkg_end, ppool));
92 }
93
94 return ret;
95}
96
97/**
98 * Unmap SP Pkg from Hafnium's address space.
99 */
100void sp_pkg_deinit(struct mm_stage1_locked stage1_locked, vaddr_t pkg_start,
101 struct sp_pkg_header *header, struct mpool *ppool)
102{
103 paddr_t to_unmap_end;
104
105 to_unmap_end = pa_from_va(
106 va_add(pkg_start, header->pm_offset + header->pm_size));
107
108 CHECK(mm_unmap(stage1_locked, pa_from_va(pkg_start), to_unmap_end,
109 ppool));
110}