refactor: added "sp_pkg" module

Added module "sp_pkg" to init and help operate the SP pkg, such that
hafnium can cleanly retrieve the FF-A manifest's and the boot info's
base address.

Change-Id: Ieb6925c487a4dac9b460353ba82a00d670176037
Signed-off-by: J-Alves <joao.alves@arm.com>
diff --git a/src/sp_pkg.c b/src/sp_pkg.c
new file mode 100644
index 0000000..62a08a3
--- /dev/null
+++ b/src/sp_pkg.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2022 The Hafnium Authors.
+ *
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file or at
+ * https://opensource.org/licenses/BSD-3-Clause.
+ */
+
+#include "hf/sp_pkg.h"
+
+#include <stdint.h>
+
+#include "hf/arch/std.h"
+
+#include "hf/addr.h"
+#include "hf/check.h"
+#include "hf/dlog.h"
+#include "hf/std.h"
+
+/*
+ * Function initializes the Secure Partition Package:
+ * - Maps whole region up to image such that Hafnium can parse the FF-A manifest
+ * and can use the first chunk of memory for booting purposes.
+ */
+bool sp_pkg_init(struct mm_stage1_locked stage1_locked, paddr_t pkg_start,
+		 struct sp_pkg_header *header, struct mpool *ppool)
+{
+	bool ret = false;
+	paddr_t pkg_end = pa_add(pkg_start, PAGE_SIZE);
+	void *pkg;
+
+	/* Firstly, map a single page of package header. */
+	pkg = mm_identity_map(stage1_locked, pkg_start, pkg_end,
+			      MM_MODE_R | MM_MODE_W, ppool);
+	assert(pkg != NULL);
+
+	memcpy_s(header, sizeof(struct sp_pkg_header), pkg,
+		 sizeof(struct sp_pkg_header));
+
+	if (header->magic != SP_PKG_HEADER_MAGIC) {
+		dlog_error("Invalid package magic.\n");
+		goto exit_unmap;
+	}
+
+	if (header->version != SP_PKG_HEADER_VERSION) {
+		dlog_error("Invalid package version.\n");
+		goto exit_unmap;
+	}
+
+	if (header->pm_offset % PAGE_SIZE != 0 ||
+	    header->img_offset % PAGE_SIZE != 0) {
+		dlog_error("SP pkg offsets are not page aligned.\n");
+		goto exit_unmap;
+	}
+
+	if (header->pm_offset > header->img_offset) {
+		dlog_error(
+			"SP pkg offsets must be in order: boot info < "
+			"partition manifest < image offset.\n");
+		goto exit_unmap;
+	}
+
+	/*
+	 * Check for overflow and then check the pm shouldn't override the
+	 * image.
+	 */
+	assert(UINT32_MAX - header->pm_offset >= header->pm_size);
+	if (header->pm_offset + header->pm_size > header->img_offset) {
+		dlog_error("Partition manifest bigger than its region.\n");
+		goto exit_unmap;
+	}
+
+	/*
+	 * Remap section up to pm as RW, to allow for writing of boot info
+	 * descriptors, if the SP specified boot info in its manifest.
+	 */
+	if (header->pm_offset > PAGE_SIZE) {
+		pkg_end = pa_add(pkg_start, header->pm_offset);
+		CHECK(mm_identity_map(stage1_locked, pkg_start, pkg_end,
+				      MM_MODE_R | MM_MODE_W, ppool) != NULL);
+	}
+
+	CHECK(mm_identity_map(stage1_locked, pkg_end,
+			      pa_add(pkg_end, header->pm_size), MM_MODE_R,
+			      ppool) != NULL);
+
+	ret = true;
+
+exit_unmap:
+	if (!ret) {
+		CHECK(mm_unmap(stage1_locked, pkg_start, pkg_end, ppool));
+	}
+
+	return ret;
+}
+
+/**
+ * Unmap SP Pkg from Hafnium's address space.
+ */
+void sp_pkg_deinit(struct mm_stage1_locked stage1_locked, vaddr_t pkg_start,
+		   struct sp_pkg_header *header, struct mpool *ppool)
+{
+	paddr_t to_unmap_end;
+
+	to_unmap_end = pa_from_va(
+		va_add(pkg_start, header->pm_offset + header->pm_size));
+
+	CHECK(mm_unmap(stage1_locked, pa_from_va(pkg_start), to_unmap_end,
+		       ppool));
+}