summaryrefslogtreecommitdiffstats
path: root/src/import/chips/p9/xip/p9_xip_image.c
diff options
context:
space:
mode:
authorClaus Michael Olsen <cmolsen@us.ibm.com>2017-03-30 20:20:23 -0500
committerSachin Gupta <sgupta2m@in.ibm.com>2017-05-12 22:27:58 -0400
commit8fb3f52276fd37466afb34b85a1dbda3c8ee3e9f (patch)
treeff056cec9819cca8d29ffd98c6b341eae770ad4f /src/import/chips/p9/xip/p9_xip_image.c
parent618c88eba551a9a971b8873a3ec1e9a13230f93e (diff)
downloadtalos-sbe-8fb3f52276fd37466afb34b85a1dbda3c8ee3e9f.tar.gz
talos-sbe-8fb3f52276fd37466afb34b85a1dbda3c8ee3e9f.zip
H-code ddLevel support - Front-end hooks for user and back-end codes.
xip_image.c has been renamed to xip_image.C to take advantage of C++ ability to overload function call arg list to avoid having to introduce additional skinny "xip_dd_get_section" and "xip_dd_append" functions. p9_xip_get_section() and p9_xip_append() APIs have been updated with an additional DD support arg as their last parm. P9XipSection.iv_reserved8[0] converted to iv_ddSupport to enable XIP level knowledge about ddSupport capability of XIP sections. Introduced p9_xip_dd_section_support() that queries a section's iv_ddSupport flag to tell caller true/false about a sections ddLevel support status. Added support in xip_tool.C as follows: - Updated "append" command to accept an optional arg, ddSupport, if section has ddLevel support or not. - Updated "extract" command to accept an optional arg, ddLevel, specifying which ddLevel to extract. - Updated "report" command's listing to show ddLevel support status of sections. Change-Id: I17e1e09d63e894d4f26cb7b324cf10ab784d78a4 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/38666 Tested-by: PPE CI <ppe-ci+hostboot@us.ibm.com> Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com> Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com> Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/38667 Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: Sachin Gupta <sgupta2m@in.ibm.com>
Diffstat (limited to 'src/import/chips/p9/xip/p9_xip_image.c')
-rw-r--r--src/import/chips/p9/xip/p9_xip_image.c3158
1 files changed, 0 insertions, 3158 deletions
diff --git a/src/import/chips/p9/xip/p9_xip_image.c b/src/import/chips/p9/xip/p9_xip_image.c
deleted file mode 100644
index c97a3d02..00000000
--- a/src/import/chips/p9/xip/p9_xip_image.c
+++ /dev/null
@@ -1,3158 +0,0 @@
-/* IBM_PROLOG_BEGIN_TAG */
-/* This is an automatically generated prolog. */
-/* */
-/* $Source: src/import/chips/p9/xip/p9_xip_image.c $ */
-/* */
-/* OpenPOWER sbe Project */
-/* */
-/* Contributors Listed Below - COPYRIGHT 2015,2017 */
-/* [+] International Business Machines Corp. */
-/* */
-/* */
-/* Licensed under the Apache License, Version 2.0 (the "License"); */
-/* you may not use this file except in compliance with the License. */
-/* You may obtain a copy of the License at */
-/* */
-/* http://www.apache.org/licenses/LICENSE-2.0 */
-/* */
-/* Unless required by applicable law or agreed to in writing, software */
-/* distributed under the License is distributed on an "AS IS" BASIS, */
-/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
-/* implied. See the License for the specific language governing */
-/* permissions and limitations under the License. */
-/* */
-/* IBM_PROLOG_END_TAG */
-
-/// \file p9_xip_image.c
-/// \brief APIs for validating, normalizing, searching and manipulating
-/// P9-XIP images.
-///
-/// The background, APIs and implementation details are documented in the
-/// document "P9-XIP Binary format" currently available at this link:
-///
-/// - https://mcdoc.boeblingen.de.ibm.com/out/out.ViewDocument.php?documentid=2678
-///
-/// \bug The p9_xip_validate() API should be carefully reviewed to ensure
-/// that validating even a corrupt image can not lead to a segfault, i.e., to
-/// ensure that no memory outside of the putative bounds of the image is ever
-/// referenced during validation.
-
-#include <stddef.h>
-#ifdef _WIN32
- #include "win32_stdint.h"
- #include "endian.h"
-#else
- #include <stdint.h>
- #include <endian.h>
-#endif
-#include <stdlib.h>
-#include <string.h>
-#include "p9_xip_image.h"
-
-
-////////////////////////////////////////////////////////////////////////////
-// Local Functions
-////////////////////////////////////////////////////////////////////////////
-
-#ifdef DEBUG_P9_XIP_IMAGE
-
-// Debugging support, normally disabled. All of the formatted I/O you see in
-// the code is effectively under this switch.
-
-#ifdef __FAPI
-
- #include "fapi.H"
- #define fprintf(stream, ...) FAPI_ERR(__VA_ARGS__)
- #define printf(...) FAPI_INF(__VA_ARGS__)
- #define TRACE_NEWLINE ""
-
-#else // __FAPI
-
- #include <stdio.h>
- #define TRACE_NEWLINE "\n"
-
-#endif // __FAPI
-
-// Portable formatting of uint64_t. The ISO C99 standard requires
-// __STDC_FORMAT_MACROS to be defined in order for PRIx64 etc. to be defined.
-
-#define __STDC_FORMAT_MACROS
-#include <inttypes.h>
-
-#define F0x016llx "0x%016" PRIx64
-#define F0x012llx "0x%012" PRIx64
-
-XIP_STATIC P9_XIP_ERROR_STRINGS(p9_xip_error_strings);
-
-#define TRACE_ERROR(x) \
- ({ \
- fprintf(stderr, "%s:%d : Returning error code %d : %s" TRACE_NEWLINE, \
- __FILE__, __LINE__, (x), \
- P9_XIP_ERROR_STRING(p9_xip_error_strings, (x))); \
- (x); \
- })
-
-#define TRACE_ERRORX(x, ...) \
- ({ \
- TRACE_ERROR(x); \
- fprintf(stderr, ##__VA_ARGS__); \
- (x); \
- })
-
-// Uncomment these if required for debugging, otherwise we get warnings from
-// GCC as they are not otherwise used.
-
-#if 0
-
-XIP_STATIC P9_XIP_TYPE_STRINGS(type_strings);
-
-XIP_STATIC void
-dumpToc(int index, P9XipToc* toc)
-{
- printf("TOC entry %d @ %p\n"
- " iv_id = 0x%08x\n"
- " iv_data = 0x%08x\n"
- " iv_type = %s\n"
- " iv_section = 0x%02x\n"
- " iv_elements = %d\n",
- index, toc,
- htobe32(toc->iv_id),
- htobe32(toc->iv_data),
- P9_XIP_TYPE_STRING(type_strings, toc->iv_type),
- toc->iv_section,
- toc->iv_elements);
-}
-
-#endif
-
-#if 0
-
-XIP_STATIC void
-dumpItem(P9XipItem* item)
-{
- printf("P9XipItem @ %p\n"
- " iv_toc = %p\n"
- " iv_address = " F0x016llx "\n"
- " iv_imageData = %p\n"
- " iv_id = %s\n"
- " iv_type = %s\n"
- " iv_elements = %d\n",
- item,
- item->iv_toc,
- item->iv_address,
- item->iv_imageData,
- item->iv_id,
- P9_XIP_TYPE_STRING(type_strings, item->iv_type),
- item->iv_elements);
- dumpToc(-1, item->iv_toc);
-}
-
-#endif /* 0 */
-
-XIP_STATIC void
-dumpSectionTable(const void* i_image)
-{
- int i, rc;
- P9XipSection section;
-
- printf("Section table dump of image @ %p\n"
- " Entry Offset Size\n"
- "-------------------------------\n",
- i_image);
-
- for (i = 0; i < P9_XIP_SECTIONS; i++)
- {
- rc = p9_xip_get_section(i_image, i, &section);
-
- if (rc)
- {
- printf(">>> dumpSectionTable got error at entry %d : %s\n",
- i, P9_XIP_ERROR_STRING(p9_xip_error_strings, rc));
- break;
- }
-
- printf("%7d 0x%08x 0x%08x\n",
- i, section.iv_offset, section.iv_size);
- }
-}
-
-#else
-
-#define TRACE_ERROR(x) (x)
-#define TRACE_ERRORX(x, ...) (x)
-#define dumpToc(...)
-#define dumpItem(...)
-#define dumpSectionTable(...)
-
-#endif
-
-
-XIP_STATIC uint64_t
-xipLinkAddress(const void* i_image)
-{
- return htobe64(((P9XipHeader*)i_image)->iv_linkAddress);
-}
-
-
-/// What is the image size?
-
-XIP_STATIC uint32_t
-xipImageSize(const void* i_image)
-{
- return htobe32(((P9XipHeader*)i_image)->iv_imageSize);
-}
-
-
-/// Set the image size
-
-XIP_STATIC void
-xipSetImageSize(void* io_image, const size_t i_size)
-{
- ((P9XipHeader*)io_image)->iv_imageSize = htobe32(i_size);
-}
-
-
-/// Re-establish the required final alignment
-
-XIP_STATIC void
-xipFinalAlignment(void* io_image)
-{
- uint32_t size;
-
- size = xipImageSize(io_image);
-
- if ((size % P9_XIP_FINAL_ALIGNMENT) != 0)
- {
- xipSetImageSize(io_image,
- size + (P9_XIP_FINAL_ALIGNMENT -
- (size % P9_XIP_FINAL_ALIGNMENT)));
- }
-}
-
-
-/// Compute a host address from an image address and offset
-
-XIP_STATIC void*
-xipHostAddressFromOffset(const void* i_image, const uint32_t offset)
-{
- return (void*)((unsigned long)i_image + offset);
-}
-
-
-/// Convert a IMAGE address to a host address
-
-XIP_STATIC void*
-xipImage2Host(const void* i_image, const uint64_t i_imageAddress)
-{
- return xipHostAddressFromOffset(i_image,
- i_imageAddress - xipLinkAddress(i_image));
-}
-
-
-XIP_STATIC int
-xipValidateImageAddress(const void* i_image,
- const uint64_t i_imageAddress,
- const uint32_t size)
-{
- int rc;
-
- if ((i_imageAddress < xipLinkAddress(i_image)) ||
- (i_imageAddress > (xipLinkAddress(i_image) +
- xipImageSize(i_image) -
- size)))
- {
- rc = TRACE_ERRORX(P9_XIP_INVALID_ARGUMENT,
- "The IMAGE address " F0x012llx
- " is outside the bounds "
- "of the image ("
- F0x012llx ":" F0x012llx
- ") for %u-byte access.\n",
- i_imageAddress,
- xipLinkAddress(i_image),
- xipLinkAddress(i_image) + xipImageSize(i_image) - 1,
- size);
- }
- else
- {
- rc = 0;
- }
-
- return rc;
-}
-
-
-/// Get the magic number from the image
-
-XIP_STATIC uint64_t
-xipMagic(const void* i_image)
-{
- return htobe64(((P9XipHeader*)i_image)->iv_magic);
-}
-
-
-/// Get the header version from the image
-
-XIP_STATIC uint8_t
-xipHeaderVersion(const void* i_image)
-{
- return ((P9XipHeader*)i_image)->iv_headerVersion;
-}
-
-
-/// Has the image been normalized?
-
-XIP_STATIC uint8_t
-xipNormalized(const void* i_image)
-{
- return ((P9XipHeader*)i_image)->iv_normalized;
-}
-
-
-/// Has the image TOC been sorted?
-
-XIP_STATIC uint8_t
-xipSorted(const void* i_image)
-{
- return ((P9XipHeader*)i_image)->iv_tocSorted;
-}
-
-
-/// A quick check that the image exists, has the correct magic and header
-/// version, and optionally is normalized.
-
-XIP_STATIC int
-xipQuickCheck(const void* i_image, const int i_normalizationRequired)
-{
- int rc;
-
- do
- {
- rc = 0;
-
- if (i_image == 0)
- {
- rc = TRACE_ERRORX(P9_XIP_IMAGE_ERROR,
- "Image pointer is NULL (0)\n");
- break;
- }
-
- if ((xipMagic(i_image) >> 32) != P9_XIP_MAGIC)
- {
- rc = TRACE_ERRORX(P9_XIP_IMAGE_ERROR,
- "Magic number mismatch; Found "
- "" F0x016llx ", expected 0x%08x........\n",
- xipMagic(i_image), P9_XIP_MAGIC);
- break;
- }
-
- if ((xipHeaderVersion(i_image)) != P9_XIP_HEADER_VERSION)
- {
- rc = TRACE_ERRORX(P9_XIP_IMAGE_ERROR,
- "Header version mismatch; Expecting %d, "
- "found %d\n",
- P9_XIP_HEADER_VERSION,
- xipHeaderVersion(i_image));
- break;
- }
-
- if (i_normalizationRequired && !xipNormalized(i_image))
- {
- rc = TRACE_ERRORX(P9_XIP_NOT_NORMALIZED,
- "Image not normalized\n");
- break;
- }
- }
- while(0);
-
- return rc;
-}
-
-
-/// Convert a 32-bit relocatable offset to a full IMAGE 48-bit address
-
-XIP_STATIC uint64_t
-xipFullAddress(const void* i_image, uint32_t offset)
-{
- return (xipLinkAddress(i_image) & 0x0000ffff00000000ull) + offset;
-}
-
-
-/// Translate a section table entry
-
-XIP_STATIC void
-xipTranslateSection(P9XipSection* o_dest, const P9XipSection* i_src)
-{
-#ifndef _BIG_ENDIAN
-
-#if P9_XIP_HEADER_VERSION != 9
-#error This code assumes the P9-XIP header version 9 layout
-#endif
-
- o_dest->iv_offset = htobe32(i_src->iv_offset);
- o_dest->iv_size = htobe32(i_src->iv_size);
- o_dest->iv_alignment = i_src->iv_alignment;
- o_dest->iv_reserved8[0] = 0;
- o_dest->iv_reserved8[1] = 0;
- o_dest->iv_reserved8[2] = 0;
-#else
-
- if (o_dest != i_src)
- {
- *o_dest = *i_src;
- }
-
-#endif /* _BIG_ENDIAN */
-}
-
-
-/// Translate a TOC entry
-
-XIP_STATIC void
-xipTranslateToc(P9XipToc* o_dest, P9XipToc* i_src)
-{
-#ifndef _BIG_ENDIAN
-
-#if P9_XIP_HEADER_VERSION != 9
-#error This code assumes the P9-XIP header version 9 layout
-#endif
-
- o_dest->iv_id = htobe32(i_src->iv_id);
- o_dest->iv_data = htobe32(i_src->iv_data);
- o_dest->iv_type = i_src->iv_type;
- o_dest->iv_section = i_src->iv_section;
- o_dest->iv_elements = i_src->iv_elements;
- o_dest->iv_pad = 0;
-#else
-
- if (o_dest != i_src)
- {
- *o_dest = *i_src;
- }
-
-#endif /* _BIG_ENDIAN */
-}
-
-
-/// Find the final (highest-address) section of the image
-
-XIP_STATIC int
-xipFinalSection(const void* i_image, int* o_sectionId)
-{
- int i, rc, found;
- uint32_t offset;
- P9XipHeader hostHeader;
-
- p9_xip_translate_header(&hostHeader, (P9XipHeader*)i_image);
-
- found = 0;
- offset = 0;
- *o_sectionId = 0; /* Make GCC -O3 happy */
-
- for (i = 0; i < P9_XIP_SECTIONS; i++)
- {
- if ((hostHeader.iv_section[i].iv_size != 0) &&
- (hostHeader.iv_section[i].iv_offset >= offset))
- {
- *o_sectionId = i;
- offset = hostHeader.iv_section[i].iv_offset;
- found = 1;
- }
- }
-
- if (!found)
- {
- rc = TRACE_ERRORX(P9_XIP_IMAGE_ERROR, "The image is empty\n");
- }
- else
- {
- rc = 0;
- }
-
- return rc;
-}
-
-
-/// Return a pointer to an image-format section table entry
-
-XIP_STATIC int
-xipGetSectionPointer(const void* i_image,
- const int i_sectionId,
- P9XipSection** o_imageSection)
-{
- int rc;
-
- if ((i_sectionId < 0) || (i_sectionId >= P9_XIP_SECTIONS))
- {
- rc = TRACE_ERROR(P9_XIP_INVALID_ARGUMENT);
- }
- else
- {
- *o_imageSection =
- &(((P9XipHeader*)i_image)->iv_section[i_sectionId]);
- rc = 0;
- }
-
- return rc;
-}
-
-
-/// Restore a section table entry from host format to image format.
-
-XIP_STATIC int
-xipPutSection(const void* i_image,
- const int i_sectionId,
- P9XipSection* i_hostSection)
-{
- int rc;
- P9XipSection* imageSection;
-
- rc = xipGetSectionPointer(i_image, i_sectionId, &imageSection);
-
- if (!rc)
- {
- xipTranslateSection(imageSection, i_hostSection);
- }
-
- return rc;
-}
-
-
-/// Set the offset of a section
-
-XIP_STATIC int
-xipSetSectionOffset(void* io_image, const int i_section,
- const uint32_t i_offset)
-{
- P9XipSection* section;
- int rc;
-
- rc = xipGetSectionPointer(io_image, i_section, &section);
-
- if (!rc)
- {
- section->iv_offset = htobe32(i_offset);
- }
-
- return rc;
-}
-
-
-/// Set the size of a section
-
-XIP_STATIC int
-xipSetSectionSize(void* io_image, const int i_section, const uint32_t i_size)
-{
- P9XipSection* section;
- int rc;
-
- rc = xipGetSectionPointer(io_image, i_section, &section);
-
- if (!rc)
- {
- section->iv_size = htobe32(i_size);
- }
-
- return rc;
-}
-
-
-/// Translate a IMAGE address in the image to a section and offset
-
-// We first check to be sure that the IMAGE address is contained in the image,
-// using the full 48-bit form. Then we scan the section table to see which
-// section contains the address - if none then the image is corrupted. We can
-// (must) use the 32-bit offset form of the address here.
-
-XIP_STATIC int
-xipImage2Section(const void* i_image,
- const uint64_t i_imageAddress,
- int* o_section,
- uint32_t* o_offset)
-{
- int rc, sectionId;
- P9XipSection section;
- uint32_t addressOffset;
-
- do
- {
- rc = 0;
-
- if ((i_imageAddress < xipLinkAddress(i_image)) ||
- (i_imageAddress >
- (xipLinkAddress(i_image) + xipImageSize(i_image))))
- {
- rc = TRACE_ERRORX(P9_XIP_INVALID_ARGUMENT,
- "image2section: The i_imageAddress argument "
- "(" F0x016llx ")\nis outside the bounds of the "
- "image (" F0x016llx ":" F0x016llx ")\n",
- i_imageAddress,
- xipLinkAddress(i_image),
- xipLinkAddress(i_image) + xipImageSize(i_image));
- break;
- }
-
- addressOffset = (i_imageAddress - xipLinkAddress(i_image)) & 0xffffffff;
-
- for (sectionId = 0; sectionId < P9_XIP_SECTIONS; sectionId++)
- {
- rc = p9_xip_get_section(i_image, sectionId, &section);
-
- if (rc)
- {
- rc = TRACE_ERROR(P9_XIP_BUG); /* Can't happen */
- break;
- }
-
- if ((section.iv_size != 0) &&
- (addressOffset >= section.iv_offset) &&
- (addressOffset < (section.iv_offset + section.iv_size)))
- {
- break;
- }
- }
-
- if (rc)
- {
- break;
- }
-
- if (sectionId == P9_XIP_SECTIONS)
- {
- rc = TRACE_ERRORX(P9_XIP_IMAGE_ERROR,
- "Error processing IMAGE address " F0x016llx ". "
- "The address is not mapped in any section.\n"
- "A section table dump appears below\n",
- i_imageAddress);
- dumpSectionTable(i_image);
- break;
- }
-
- *o_section = sectionId;
- *o_offset = addressOffset - section.iv_offset;
-
- }
- while(0);
-
- return rc;
-}
-
-
-// Delete the last, i.e., final, section of the image.
-
-XIP_STATIC int
-xipDeleteLastSection(void* io_image,
- const int i_sectionId)
-{
- int rc, final;
- P9XipSection section;
-
- do
- {
-
- xipSetSectionOffset(io_image, i_sectionId, 0);
- xipSetSectionSize(io_image, i_sectionId, 0);
-
-
- // For cleanliness we also remove any alignment padding that had been
- // appended between the now-last section and the deleted section, then
- // re-establish the final alignment. The assumption is that all images
- // always have the correct final alignment, so there is no way this
- // could overflow a designated buffer space since the image size is
- // the same or has been reduced.
-
- rc = xipFinalSection(io_image, &final);
-
- if (rc)
- {
- break;
- }
-
- rc = p9_xip_get_section(io_image, final, &section);
-
- if (rc)
- {
- break;
- }
-
- xipSetImageSize(io_image, section.iv_offset + section.iv_size);
- xipFinalAlignment(io_image);
-
- }
- while (0);
-
- return rc;
-}
-
-
-/// Get the information required to search the TOC.
-///
-/// All return values are optional.
-
-int
-p9_xip_get_toc(void* i_image,
- P9XipToc** o_toc,
- size_t* o_entries,
- int* o_sorted,
- char** o_strings)
-{
- int rc;
- P9XipSection tocSection, stringsSection;
-
- do
- {
- rc = p9_xip_get_section(i_image, P9_XIP_SECTION_TOC, &tocSection);
-
- if (rc)
- {
- break;
- }
-
- rc = p9_xip_get_section(i_image, P9_XIP_SECTION_STRINGS,
- &stringsSection);
-
- if (rc)
- {
- break;
- }
-
- if (o_toc)
- {
- *o_toc = (P9XipToc*)((uint8_t*)i_image + tocSection.iv_offset);
- }
-
- if (o_entries)
- {
- *o_entries = tocSection.iv_size / sizeof(P9XipToc);
- }
-
- if (o_sorted)
- {
- *o_sorted = xipSorted(i_image);
- }
-
- if (o_strings)
- {
- *o_strings = (char*)i_image + stringsSection.iv_offset;
- }
- }
- while (0);
-
- return rc;
-}
-
-
-/// Compare two normalized TOC entries for sorting.
-
-XIP_STATIC int
-xipCompareToc(const P9XipToc* i_a, const P9XipToc* i_b,
- const char* i_strings)
-{
- return strcmp(i_strings + htobe32(i_a->iv_id),
- i_strings + htobe32(i_b->iv_id));
-}
-
-
-/// Iterative quicksort of the TOC
-
-// Note: The stack requirement is limited to 256 bytes + minor local storage.
-
-XIP_STATIC void
-xipQuickSort(P9XipToc* io_toc, int i_left, int i_right,
- const char* i_strings)
-{
- int i, j, left, right, sp;
- P9XipToc pivot, temp;
- uint32_t stack[64];
-
- sp = 0;
- stack[sp++] = i_left;
- stack[sp++] = i_right;
-
- while (sp)
- {
-
- right = stack[--sp];
- left = stack[--sp];
-
- i = left;
- j = right;
-
- pivot = io_toc[(i + j) / 2];
-
- while (i <= j)
- {
- while (xipCompareToc(&(io_toc[i]), &pivot, i_strings) < 0)
- {
- i++;
- }
-
- while (xipCompareToc(&(io_toc[j]), &pivot, i_strings) > 0)
- {
- j--;
- }
-
- if (i <= j)
- {
- temp = io_toc[i];
- io_toc[i] = io_toc[j];
- io_toc[j] = temp;
- i++;
- j--;
- }
- }
-
- if (left < j)
- {
- stack[sp++] = left;
- stack[sp++] = j;
- }
-
- if (i < right)
- {
- stack[sp++] = i;
- stack[sp++] = right;
- }
- }
-}
-
-
-/// TOC linear search
-
-XIP_STATIC int
-xipLinearSearch(void* i_image, const char* i_id, P9XipToc** o_entry)
-{
- int rc;
- P9XipToc* imageToc, hostToc;
- size_t entries;
- char* strings;
-
- *o_entry = 0;
- rc = p9_xip_get_toc(i_image, &imageToc, &entries, 0, &strings);
-
- if (!rc)
- {
- for (; entries; entries--, imageToc++)
- {
- xipTranslateToc(&hostToc, imageToc);
-
- if (strcmp(i_id, strings + hostToc.iv_id) == 0)
- {
- break;
- }
- }
-
- if (entries)
- {
- *o_entry = imageToc;
- rc = 0;
- }
- else
- {
- *o_entry = 0;
- rc = TRACE_ERROR(P9_XIP_ITEM_NOT_FOUND);
- }
- }
-
- return rc;
-}
-
-
-/// A classic binary search of a (presumed) sorted array
-
-XIP_STATIC int
-xipBinarySearch(void* i_image, const char* i_id, P9XipToc** o_entry)
-{
- int rc;
- P9XipToc* imageToc;
- size_t entries;
- char* strings;
- int sorted, left, right, next, sort;
-
- do
- {
- *o_entry = 0;
-
- rc = p9_xip_get_toc(i_image, &imageToc, &entries, &sorted, &strings);
-
- if (rc)
- {
- break;
- }
-
- if (!sorted)
- {
- rc = TRACE_ERROR(P9_XIP_BUG);
- break;
- }
-
- left = 0;
- right = entries - 1;
-
- while (left <= right)
- {
- next = (left + right) / 2;
- sort = strcmp(i_id, strings + htobe32(imageToc[next].iv_id));
-
- if (sort == 0)
- {
- *o_entry = &(imageToc[next]);
- break;
- }
- else if (sort < 0)
- {
- right = next - 1;
- }
- else
- {
- left = next + 1;
- }
- }
-
- if (*o_entry == 0)
- {
- rc = TRACE_ERROR(P9_XIP_ITEM_NOT_FOUND);
- break;
- }
- }
- while (0);
-
- return rc;
-}
-
-
-/// Validate a TOC entry as a mapping function
-///
-/// The TOC is validated by searching for the entry, which will uncover
-/// duplicate entries or problems with sorting/searching.
-
-XIP_STATIC int
-xipValidateTocEntry(void* io_image, const P9XipItem* i_item, void* io_arg)
-{
- int rc;
- P9XipItem found;
-
- do
- {
- rc = p9_xip_find(io_image, i_item->iv_id, &found);
-
- if (rc)
- {
- rc = TRACE_ERRORX(rc, "TOC entry for %s not found\n",
- i_item->iv_id);
- }
- else if (found.iv_toc != i_item->iv_toc)
- {
- rc = TRACE_ERRORX(P9_XIP_TOC_ERROR,
- "Duplicate TOC entry for '%s'\n", i_item->iv_id);
- }
-
- break;
- }
- while (0);
-
- return rc;
-}
-
-
-// This is the FNV-1a hash, used for hashing symbol names in the .fixed
-// section into 32-bit hashes for the mini-TOC.
-
-// According to the authors:
-
-// "FNV hash algorithms and source code have been released into the public
-// domain. The authors of the FNV algorithmm look deliberate steps to disclose
-// the algorhtm (sic) in a public forum soon after it was invented. More than
-// a year passed after this public disclosure and the authors deliberatly took
-// no steps to patent the FNV algorithm. Therefore it is safe to say that the
-// FNV authors have no patent claims on the FNV algorithm as published."
-
-#define FNV_OFFSET_BASIS 2166136261u
-#define FNV_PRIME32 16777619u
-
-uint32_t
-xipHash32(const char* s)
-{
- uint32_t hash;
-
- hash = FNV_OFFSET_BASIS;
-
- while (*s)
- {
- hash ^= *s++;
- hash *= FNV_PRIME32;
- }
-
- return hash;
-}
-
-
-// Normalize a TOC entry
-
-// Normalize the TOC entry by converting relocatable pointers into 32-bit
-// offsets from the beginning of the section containing the data. All
-// addresses in the TOC are actually 32-bit offsets in the address space named
-// in bits 16:31 of the link address of the image.
-
-XIP_STATIC int
-xipNormalizeToc(void* io_image, P9XipToc* io_imageToc,
- P9XipHashedToc** io_fixedTocEntry,
- size_t* io_fixedEntriesRemaining)
-{
- P9XipToc hostToc;
- int idSection, dataSection;
- uint32_t idOffset, dataOffset;
- char* hostString;
- int rc;
-
- do
- {
-
- // Translate the TOC entry to host format. Then locate the
- // sections/offsets of the Id string (which must be in .strings) and
- // the data.
-
- xipTranslateToc(&hostToc, io_imageToc);
-
- hostString =
- (char*)xipImage2Host(io_image,
- xipFullAddress(io_image, hostToc.iv_id));
-
- rc = xipImage2Section(io_image,
- xipFullAddress(io_image, hostToc.iv_id),
- &idSection,
- &idOffset);
-
- if (rc)
- {
- break;
- }
-
- if (idSection != P9_XIP_SECTION_STRINGS)
- {
- rc = TRACE_ERROR(P9_XIP_IMAGE_ERROR);
- break;
- }
-
- rc = xipImage2Section(io_image,
- xipFullAddress(io_image, hostToc.iv_data),
- &dataSection,
- &dataOffset);
-
- if (rc)
- {
- break;
- }
-
- // Now replace the Id and data pointers with their offsets, and update
- // the data section in the TOC entry.
-
- hostToc.iv_id = idOffset;
- hostToc.iv_data = dataOffset;
- hostToc.iv_section = dataSection;
-
- // If this TOC entry is from .fixed, create a new record in .fixed_toc
-
- if (hostToc.iv_section == P9_XIP_SECTION_FIXED)
- {
-
- if (*io_fixedEntriesRemaining == 0)
- {
- rc = TRACE_ERRORX(P9_XIP_TOC_ERROR,
- "Too many TOC entries for .fixed\n");
- break;
- }
-
- if (hostToc.iv_data != (uint16_t)hostToc.iv_data)
- {
- rc = TRACE_ERRORX(P9_XIP_IMAGE_ERROR,
- "The .fixed section is too big to index\n");
- break;
- }
-
- (*io_fixedTocEntry)->iv_hash = htobe32(xipHash32(hostString));
- (*io_fixedTocEntry)->iv_offset = htobe16(hostToc.iv_data);
- (*io_fixedTocEntry)->iv_type = hostToc.iv_type;
- (*io_fixedTocEntry)->iv_elements = hostToc.iv_elements;
-
- (*io_fixedTocEntry)++;
- (*io_fixedEntriesRemaining)--;
- }
-
- // Finally update the TOC entry
-
- xipTranslateToc(io_imageToc, &hostToc);
-
- }
- while (0);
-
- return rc;
-}
-
-
-// Check for hash collisions in the .fixed mini-TOC. Note that endianness is
-// not an issue here, as we're comparing for equality.
-
-XIP_STATIC int
-xipHashCollision(P9XipHashedToc* i_fixedToc, size_t i_entries)
-{
- int rc;
- size_t i, j;
-
- rc = 0;
-
- for (i = 0; i < i_entries; i++)
- {
- for (j = i + 1; j < i_entries; j++)
- {
- if (i_fixedToc[i].iv_hash == i_fixedToc[j].iv_hash)
- {
- rc = TRACE_ERRORX(P9_XIP_HASH_COLLISION,
- "Hash collision at index %zd\n",
- i);
- break;
- }
- }
-
- if (rc)
- {
- break;
- }
- }
-
- return rc;
-}
-
-
-/// Decode a normalized image-format TOC entry into a host-format P9XipItem
-/// structure
-
-XIP_STATIC int
-xipDecodeToc(void* i_image,
- P9XipToc* i_imageToc,
- P9XipItem* o_item)
-{
- int rc;
- P9XipToc hostToc;
- P9XipSection dataSection, stringsSection;
-
- do
- {
- if (!xipNormalized(i_image))
- {
- rc = TRACE_ERROR(P9_XIP_NOT_NORMALIZED);
- break;
- }
-
-
- // Translate the TOC entry and set the TOC pointer, data type and
- // number of elements in the outgoing structure. The Id string is
- // always located in the TOC_STRINGS section.
-
- xipTranslateToc(&hostToc, i_imageToc);
-
- o_item->iv_toc = i_imageToc;
- o_item->iv_type = hostToc.iv_type;
- o_item->iv_elements = hostToc.iv_elements;
-
- p9_xip_get_section(i_image, P9_XIP_SECTION_STRINGS, &stringsSection);
- o_item->iv_id =
- (char*)i_image + stringsSection.iv_offset + hostToc.iv_id;
-
-
- // The data (or text address) are addressed by relative offsets from
- // the beginning of their section. The TOC entry may remain in the TOC
- // even though the section has been removed from the image, so this
- // case needs to be covered.
-
- rc = p9_xip_get_section(i_image, hostToc.iv_section, &dataSection);
-
- if (rc)
- {
- break;
- }
-
- if (dataSection.iv_size == 0)
- {
- rc = TRACE_ERROR(P9_XIP_DATA_NOT_PRESENT);
- break;
- }
-
- o_item->iv_imageData =
- (void*)((uint8_t*)i_image +
- dataSection.iv_offset + hostToc.iv_data);
-
- o_item->iv_address =
- xipLinkAddress(i_image) + dataSection.iv_offset + hostToc.iv_data;
-
- o_item->iv_partial = 0;
-
- }
- while (0);
-
- return rc;
-}
-
-int
-p9_xip_decode_toc_dump(void* i_image, void* i_dump,
- P9XipToc* i_imageToc,
- P9XipItem* o_item)
-{
- int rc = 0;
- P9XipToc hostToc = {0};
- P9XipSection stringsSection = {0};
-
- if (!xipNormalized(i_image))
- {
- rc = TRACE_ERROR(P9_XIP_NOT_NORMALIZED);
- return rc;
- }
-
- // Translate the TOC entry and set the TOC pointer, data type and
- // number of elements in the outgoing structure. The Id string is
- // always located in the TOC_STRINGS section.
-
- xipTranslateToc(&hostToc, i_imageToc);
-
- o_item->iv_toc = i_imageToc;
- o_item->iv_type = hostToc.iv_type;
- o_item->iv_elements = hostToc.iv_elements;
-
- p9_xip_get_section(i_image, P9_XIP_SECTION_STRINGS, &stringsSection);
- o_item->iv_id =
- (char*)i_image + stringsSection.iv_offset + hostToc.iv_id;
-
- //Print only the attributes present in fixed section of SEEPROM image
- if (hostToc.iv_section == P9_XIP_SECTION_FIXED)
- {
- //get the attribute value from dump file
- o_item->iv_imageData = (void*)((uint8_t*)i_dump + hostToc.iv_data);
- o_item->iv_address = xipLinkAddress(i_image) + hostToc.iv_data;
- o_item->iv_partial = 0;
- }
- else
- {
- o_item->iv_address = 0;
- }
-
- return rc;
-}
-
-/// Sort the TOC
-
-XIP_STATIC int
-xipSortToc(void* io_image)
-{
- int rc;
- P9XipToc* hostToc;
- size_t entries;
- char* strings;
-
- do
- {
- rc = xipQuickCheck(io_image, 1);
-
- if (rc)
- {
- break;
- }
-
- if (xipSorted(io_image))
- {
- break;
- }
-
- rc = p9_xip_get_toc(io_image, &hostToc, &entries, 0, &strings);
-
- if (rc)
- {
- break;
- }
-
- xipQuickSort(hostToc, 0, entries - 1, strings);
-
- ((P9XipHeader*)io_image)->iv_tocSorted = 1;
-
- }
- while (0);
-
- return rc;
-}
-
-
-// Pad the image with 0 to a given power-of-2 alignment. The image size is
-// modified to reflect the pad, but the caller must modify the section size to
-// reflect the pad.
-
-XIP_STATIC int
-xipPadImage(void* io_image, uint32_t i_allocation,
- uint32_t i_align, uint32_t* pad)
-{
- int rc;
-
- do
- {
- rc = 0;
-
- if ((i_align == 0) || ((i_align & (i_align - 1)) != 0))
- {
- rc = TRACE_ERRORX(P9_XIP_INVALID_ARGUMENT,
- "Alignment specification (%u) "
- "not a power-of-2\n",
- i_align);
- break;
- }
-
- *pad = xipImageSize(io_image) % i_align;
-
- if (*pad != 0)
- {
- *pad = i_align - *pad;
-
- if ((xipImageSize(io_image) + *pad) > i_allocation)
- {
- rc = TRACE_ERROR(P9_XIP_WOULD_OVERFLOW);
- break;
- }
-
- memset((void*)((unsigned long)io_image + xipImageSize(io_image)),
- 0, *pad);
- xipSetImageSize(io_image, xipImageSize(io_image) + *pad);
- }
- }
- while (0);
-
- return rc;
-}
-
-
-// Get the .fixed_toc section
-
-XIP_STATIC int
-xipGetFixedToc(void* io_image,
- P9XipHashedToc** o_imageToc,
- size_t* o_entries)
-{
- int rc;
- P9XipSection section;
-
- rc = p9_xip_get_section(io_image, P9_XIP_SECTION_FIXED_TOC, &section);
-
- if (!rc)
- {
-
- *o_imageToc =
- (P9XipHashedToc*)((unsigned long)io_image + section.iv_offset);
-
- *o_entries = section.iv_size / sizeof(P9XipHashedToc);
- }
-
- return rc;
-}
-
-
-// Search for an item in the fixed TOC, and populate a partial TOC entry if
-// requested. This table is small and unsorted so a linear search is
-// adequate. The TOC structures are also small so all byte-reversal is done
-// 'by hand' rather than with a translate-type API.
-
-XIP_STATIC int
-xipFixedFind(void* i_image, const char* i_id, P9XipItem* o_item)
-{
- int rc;
- P9XipHashedToc* toc;
- size_t entries;
- uint32_t hash;
- P9XipSection fixedSection;
- uint32_t offset;
-
- do
- {
- rc = xipGetFixedToc(i_image, &toc, &entries);
-
- if (rc)
- {
- break;
- }
-
- for (hash = htobe32(xipHash32(i_id)); entries != 0; entries--, toc++)
- {
- if (toc->iv_hash == hash)
- {
- break;
- }
- }
-
- if (entries == 0)
- {
- rc = P9_XIP_ITEM_NOT_FOUND;
- break;
- }
- else
- {
- rc = 0;
- }
-
- // The caller may have requested a lookup only (o_item == 0), in which
- // case we're done. Otherwise we create a partial P9XipItem and
- // populate the non-0 fields analogously to the xipDecodeToc()
- // routine. The data resides in the .fixed section in this case.
-
- if (o_item == 0)
- {
- break;
- }
-
- o_item->iv_partial = 1;
- o_item->iv_toc = 0;
- o_item->iv_id = 0;
-
- o_item->iv_type = toc->iv_type;
- o_item->iv_elements = toc->iv_elements;
-
- rc = p9_xip_get_section(i_image, P9_XIP_SECTION_FIXED, &fixedSection);
-
- if (rc)
- {
- break;
- }
-
- if (fixedSection.iv_size == 0)
- {
- rc = TRACE_ERROR(P9_XIP_DATA_NOT_PRESENT);
- break;
- }
-
- offset = fixedSection.iv_offset + htobe16(toc->iv_offset);
-
- o_item->iv_imageData = (void*)((uint8_t*)i_image + offset);
- o_item->iv_address = xipLinkAddress(i_image) + offset;
-
- }
- while (0);
-
- return rc;
-}
-
-
-// Search for an item in the special built-in TOC of header fields, and
-// populate a partial TOC entry if requested.
-//
-// This facility was added to allow header data to be searched by name even
-// when the TOC has been stripped. This API will only be used in the case of a
-// stripped TOC since the header fields are also indexed in the main TOC.
-//
-// The table is allocated on the stack in order to make this code concurrently
-// patchable in PHYP (although PHYP applications will never use this code).
-// The table is small and unsorted so a linear search is adequate, and the
-// stack requirememts are small.
-
-XIP_STATIC int
-xipHeaderFind(void* i_image, const char* i_id, P9XipItem* o_item)
-{
- int rc;
- unsigned i;
- uint32_t offset;
- P9XipSection headerSection;
-
-#define HEADER_TOC(id, field, type) \
- {#id, offsetof(P9XipHeader, field), type}
-
- struct HeaderToc
- {
-
- const char* iv_id;
- uint16_t iv_offset;
- uint8_t iv_type;
-
- } toc[] =
- {
-
- HEADER_TOC(magic, iv_magic, P9_XIP_UINT64),
- HEADER_TOC(link_address, iv_linkAddress, P9_XIP_UINT64),
-
- HEADER_TOC(image_size, iv_imageSize, P9_XIP_UINT32),
- HEADER_TOC(build_date, iv_buildDate, P9_XIP_UINT32),
- HEADER_TOC(build_time, iv_buildTime, P9_XIP_UINT32),
- HEADER_TOC(build_tag, iv_buildTag, P9_XIP_STRING),
-
- HEADER_TOC(header_version, iv_headerVersion, P9_XIP_UINT8),
- HEADER_TOC(toc_normalized, iv_normalized, P9_XIP_UINT8),
- HEADER_TOC(toc_sorted, iv_tocSorted, P9_XIP_UINT8),
-
- HEADER_TOC(build_user, iv_buildUser, P9_XIP_STRING),
- HEADER_TOC(build_host, iv_buildHost, P9_XIP_STRING),
-
- };
-
- do
- {
-
- rc = P9_XIP_ITEM_NOT_FOUND;
-
- for (i = 0; i < (sizeof(toc) / sizeof(struct HeaderToc)); i++)
- {
- if (strcmp(i_id, toc[i].iv_id) == 0)
- {
- rc = 0;
- break;
- }
- }
-
- if (rc)
- {
- break;
- }
-
- // The caller may have requested a lookup only (o_item == 0), in which
- // case we're done. Otherwise we create a partial P9XipItem and
- // populate the non-0 fields analogously to the xipDecodeToc()
- // routine. The data resides in the .fixed section in this case.
-
- if (o_item == 0)
- {
- break;
- }
-
- o_item->iv_partial = 1;
- o_item->iv_toc = 0;
- o_item->iv_id = 0;
-
- o_item->iv_type = toc[i].iv_type;
- o_item->iv_elements = 1; /* True for now... */
-
- rc = p9_xip_get_section(i_image, P9_XIP_SECTION_HEADER,
- &headerSection);
-
- if (rc)
- {
- break;
- }
-
- if (headerSection.iv_size == 0)
- {
- rc = TRACE_ERROR(P9_XIP_DATA_NOT_PRESENT);
- break;
- }
-
- offset = headerSection.iv_offset + toc[i].iv_offset;
-
- o_item->iv_imageData = (void*)((uint8_t*)i_image + offset);
- o_item->iv_address = xipLinkAddress(i_image) + offset;
-
- }
- while (0);
-
- return rc;
-}
-
-
-////////////////////////////////////////////////////////////////////////////
-// Published API
-////////////////////////////////////////////////////////////////////////////
-
-int
-p9_xip_validate(void* i_image, const uint32_t i_size)
-{
- P9XipHeader hostHeader;
- int rc = 0, i;
- uint32_t linkAddress, imageSize, extent, offset, size;
- uint8_t alignment;
-
- p9_xip_translate_header(&hostHeader, (P9XipHeader*)i_image);
-
- do
- {
-
- // Validate C/Assembler constraints.
-
- if (sizeof(P9XipSection) != SIZE_OF_P9_XIP_SECTION)
- {
- rc = TRACE_ERRORX(P9_XIP_BUG,
- "C/Assembler size mismatch(%ld/%d) "
- "for P9XipSection\n",
- sizeof(P9XipSection), SIZE_OF_P9_XIP_SECTION);
- break;
- }
-
- if (sizeof(P9XipToc) != SIZE_OF_P9_XIP_TOC)
- {
- rc = TRACE_ERRORX(P9_XIP_BUG,
- "C/Assembler size mismatch(%ld/%d) "
- "for P9XipToc\n",
- sizeof(P9XipToc), SIZE_OF_P9_XIP_TOC);
- break;
- }
-
- if (sizeof(P9XipHashedToc) != SIZE_OF_P9_XIP_HASHED_TOC)
- {
- rc = TRACE_ERRORX(P9_XIP_BUG,
- "C/Assembler size mismatch(%ld/%d) "
- "for P9XipHashedToc\n",
- sizeof(P9XipHashedToc),
- SIZE_OF_P9_XIP_HASHED_TOC);
- break;
- }
-
- // Validate the image pointer and magic number
-
- rc = xipQuickCheck(i_image, 0);
-
- if (rc)
- {
- break;
- }
-
- // Validate the image size
-
- linkAddress = hostHeader.iv_linkAddress;
- imageSize = hostHeader.iv_imageSize;
- extent = linkAddress + imageSize;
-
- if (imageSize < sizeof(P9XipHeader))
- {
- rc = TRACE_ERRORX(P9_XIP_IMAGE_ERROR,
- "p9_xip_validate(%p, %u) : "
- "The image size recorded in the image "
- "(%u) is smaller than the header size.\n",
- i_image, i_size, imageSize);
- break;
- }
-
- if (imageSize != i_size)
- {
- rc = TRACE_ERRORX(P9_XIP_IMAGE_ERROR,
- "p9_xip_validate(%p, %u) : "
- "The image size recorded in the image "
- "(%u) does not match the i_size parameter.\n",
- i_image, i_size, imageSize);
- break;
- }
-
- if (extent <= linkAddress)
- {
- rc = TRACE_ERRORX(P9_XIP_IMAGE_ERROR,
- "p9_xip_validate(%p, %u) : "
- "Given the link address (%u) and the "
- "image size, the image wraps the address space\n",
- i_image, i_size, linkAddress);
- break;
- }
-
- if ((imageSize % P9_XIP_FINAL_ALIGNMENT) != 0)
- {
- rc = TRACE_ERRORX(P9_XIP_ALIGNMENT_ERROR,
- "p9_xip_validate(%p, %u) : "
- "The image size (%u) is not a multiple of %u\n",
- i_image, i_size, imageSize,
- P9_XIP_FINAL_ALIGNMENT);
- break;
- }
-
- // Validate that all sections appear to be within the image
- // bounds, and are aligned correctly.
-
- for (i = 0; i < P9_XIP_SECTIONS; i++)
- {
-
- offset = hostHeader.iv_section[i].iv_offset;
- size = hostHeader.iv_section[i].iv_size;
- alignment = hostHeader.iv_section[i].iv_alignment;
-
- if ((offset > imageSize) ||
- ((offset + size) > imageSize) ||
- ((offset + size) < offset))
- {
- rc = TRACE_ERRORX(P9_XIP_IMAGE_ERROR,
- "Section %d does not appear to be within "
- "the bounds of the image\n"
- "offset = %u, size = %u, image size = %u\n",
- i, offset, size, imageSize);
- break;
- }
-
- if ((offset % alignment) != 0)
- {
- rc = TRACE_ERRORX(P9_XIP_ALIGNMENT_ERROR,
- "Section %d requires %d-byte initial "
- "alignment but the section offset is %u\n",
- i, alignment, offset);
- break;
- }
- }
-
- if (rc)
- {
- break;
- }
-
- // If the TOC exists and the image is normalized, validate each TOC
- // entry.
-
- size = hostHeader.iv_section[P9_XIP_SECTION_TOC].iv_size;
-
- if (size != 0)
- {
- if (xipNormalized(i_image))
- {
- rc = p9_xip_map_toc(i_image, xipValidateTocEntry, 0);
-
- if (rc)
- {
- break;
- }
- }
- }
- }
- while (0);
-
- return rc;
-}
-
-
-int
-p9_xip_validate2(void* i_image, const uint32_t i_size, const uint32_t i_maskIgnores)
-{
- P9XipHeader hostHeader;
- int rc = 0, i;
- uint32_t linkAddress, imageSize, extent, offset, size;
- uint8_t alignment;
-
- p9_xip_translate_header(&hostHeader, (P9XipHeader*)i_image);
-
- do
- {
-
- // Validate C/Assembler constraints.
-
- if (sizeof(P9XipSection) != SIZE_OF_P9_XIP_SECTION)
- {
- rc = TRACE_ERRORX(P9_XIP_BUG,
- "C/Assembler size mismatch(%ld/%d) "
- "for P9XipSection\n",
- sizeof(P9XipSection), SIZE_OF_P9_XIP_SECTION);
- break;
- }
-
- if (sizeof(P9XipToc) != SIZE_OF_P9_XIP_TOC)
- {
- rc = TRACE_ERRORX(P9_XIP_BUG,
- "C/Assembler size mismatch(%ld/%d) "
- "for P9XipToc\n",
- sizeof(P9XipToc), SIZE_OF_P9_XIP_TOC);
- break;
- }
-
- if (sizeof(P9XipHashedToc) != SIZE_OF_P9_XIP_HASHED_TOC)
- {
- rc = TRACE_ERRORX(P9_XIP_BUG,
- "C/Assembler size mismatch(%ld/%d) "
- "for P9XipHashedToc\n",
- sizeof(P9XipHashedToc),
- SIZE_OF_P9_XIP_HASHED_TOC);
- break;
- }
-
- // Validate the image pointer and magic number
-
- rc = xipQuickCheck(i_image, 0);
-
- if (rc)
- {
- break;
- }
-
- // Validate the image size
-
- linkAddress = hostHeader.iv_linkAddress;
- imageSize = hostHeader.iv_imageSize;
- extent = linkAddress + imageSize;
-
- if (imageSize < sizeof(P9XipHeader))
- {
- rc = TRACE_ERRORX(P9_XIP_IMAGE_ERROR,
- "p9_xip_validate2(%p, %u) : "
- "The image size recorded in the image "
- "(%u) is smaller than the header size.\n",
- i_image, i_size, imageSize);
- break;
- }
-
- if (imageSize != i_size && !(i_maskIgnores & P9_XIP_IGNORE_FILE_SIZE))
- {
- rc = TRACE_ERRORX(P9_XIP_IMAGE_ERROR,
- "p9_xip_validate2(%p, %u) : "
- "The image size recorded in the image "
- "(%u) does not match the i_size parameter.\n",
- i_image, i_size, imageSize);
- break;
- }
-
- if (extent <= linkAddress)
- {
- rc = TRACE_ERRORX(P9_XIP_IMAGE_ERROR,
- "p9_xip_validate2(%p, %u) : "
- "Given the link address (%u) and the "
- "image size, the image wraps the address space\n",
- i_image, i_size, linkAddress);
- break;
- }
-
- if ((imageSize % P9_XIP_FINAL_ALIGNMENT) != 0)
- {
- rc = TRACE_ERRORX(P9_XIP_ALIGNMENT_ERROR,
- "p9_xip_validate2(%p, %u) : "
- "The image size (%u) is not a multiple of %u\n",
- i_image, i_size, imageSize,
- P9_XIP_FINAL_ALIGNMENT);
- break;
- }
-
- // Validate that all sections appear to be within the image
- // bounds, and are aligned correctly.
-
- for (i = 0; i < P9_XIP_SECTIONS; i++)
- {
-
- offset = hostHeader.iv_section[i].iv_offset;
- size = hostHeader.iv_section[i].iv_size;
- alignment = hostHeader.iv_section[i].iv_alignment;
-
- if ((offset > imageSize) ||
- ((offset + size) > imageSize) ||
- ((offset + size) < offset))
- {
- rc = TRACE_ERRORX(P9_XIP_IMAGE_ERROR,
- "Section %d does not appear to be within "
- "the bounds of the image\n"
- "offset = %u, size = %u, image size = %u\n",
- i, offset, size, imageSize);
- break;
- }
-
- if ((offset % alignment) != 0)
- {
- rc = TRACE_ERRORX(P9_XIP_ALIGNMENT_ERROR,
- "Section %d requires %d-byte initial "
- "alignment but the section offset is %u\n",
- i, alignment, offset);
- break;
- }
- }
-
- if (rc)
- {
- break;
- }
-
- // If the TOC exists and the image is normalized, validate each TOC
- // entry.
-
- size = hostHeader.iv_section[P9_XIP_SECTION_TOC].iv_size;
-
- if (size != 0)
- {
- if (xipNormalized(i_image))
- {
- rc = p9_xip_map_toc(i_image, xipValidateTocEntry, 0);
-
- if (rc)
- {
- break;
- }
- }
- }
- }
- while (0);
-
- return rc;
-}
-
-
-// Normalization:
-//
-// 1. Normalize the TOC, unless the image is already normalized. The image
-// must be marked as normalized before sorting.
-//
-// 2. Sort the TOC.
-//
-// 3. Clear the section offsets of any empty sections to make the section
-// table reports less confusing.
-//
-// 4. Clear normalization status on any failure.
-
-int
-p9_xip_normalize(void* io_image)
-{
- int rc, i;
- P9XipSection section;
- P9XipToc* imageToc;
- P9XipHashedToc* fixedImageToc;
- P9XipHashedToc* fixedTocEntry;
- size_t tocEntries, fixedTocEntries, fixedEntriesRemaining;
-
- do
- {
- rc = xipQuickCheck(io_image, 0);
-
- if (rc)
- {
- break;
- }
-
- if (!xipNormalized(io_image))
- {
-
- rc = p9_xip_get_toc(io_image, &imageToc, &tocEntries, 0, 0);
-
- if (rc)
- {
- break;
- }
-
- rc = xipGetFixedToc(io_image, &fixedImageToc, &fixedTocEntries);
-
- if (rc)
- {
- break;
- }
-
- fixedTocEntry = fixedImageToc;
- fixedEntriesRemaining = fixedTocEntries;
-
- for (; tocEntries--; imageToc++)
- {
- rc = xipNormalizeToc(io_image, imageToc,
- &fixedTocEntry, &fixedEntriesRemaining);
-
- if (rc)
- {
- break;
- }
-
- }
-
- if (rc)
- {
- break;
- }
-
- if (fixedEntriesRemaining != 0)
- {
- rc = TRACE_ERRORX(P9_XIP_TOC_ERROR,
- "Not enough TOC entries for .fixed");
- break;
- }
-
- rc = xipHashCollision(fixedImageToc, fixedTocEntries);
-
- if (rc)
- {
- break;
- }
-
- ((P9XipHeader*)io_image)->iv_normalized = 1;
- }
-
- rc = xipSortToc(io_image);
-
- if (rc)
- {
- break;
- }
-
- for (i = 0; i < P9_XIP_SECTIONS; i++)
- {
- rc = p9_xip_get_section(io_image, i, &section);
-
- if (rc)
- {
- break;
- }
-
- if (section.iv_size == 0)
- {
- xipSetSectionOffset(io_image, i, 0);
- }
- }
-
- if (rc)
- {
- break;
- }
-
- }
- while(0);
-
- ((P9XipHeader*)io_image)->iv_normalized = (rc == 0);
-
- return rc;
-}
-
-
-int
-p9_xip_image_size(void* io_image, uint32_t* o_size)
-{
- int rc;
-
- rc = xipQuickCheck(io_image, 0);
-
- if (!rc)
- {
- *o_size = xipImageSize(io_image);
- }
-
- return rc;
-}
-
-
-int
-p9_xip_get_section(const void* i_image,
- const int i_sectionId,
- P9XipSection* o_hostSection)
-{
- int rc;
- P9XipSection* imageSection;
-
- rc = xipGetSectionPointer(i_image, i_sectionId, &imageSection);
-
- if (!rc)
- {
- xipTranslateSection(o_hostSection, imageSection);
- }
-
- return rc;
-}
-
-
-// If the 'big' TOC is not present, search the mini-TOCs that only index the
-// .fixed and .header sections.
-
-int
-p9_xip_find(void* i_image,
- const char* i_id,
- P9XipItem* o_item)
-{
- int rc;
- P9XipToc* toc;
- P9XipItem item, *pitem;
- P9XipSection* tocSection;
-
- do
- {
- rc = xipQuickCheck(i_image, 1);
-
- if (rc)
- {
- break;
- }
-
- rc = xipGetSectionPointer(i_image, P9_XIP_SECTION_TOC, &tocSection);
-
- if (rc)
- {
- break;
- }
-
- if (tocSection->iv_size == 0)
- {
- rc = xipFixedFind(i_image, i_id, o_item);
-
- if (rc)
- {
- rc = xipHeaderFind(i_image, i_id, o_item);
- }
-
- break;
- }
-
- if (xipSorted(i_image))
- {
- rc = xipBinarySearch(i_image, i_id, &toc);
- }
- else
- {
- rc = xipLinearSearch(i_image, i_id, &toc);
- }
-
- if (rc)
- {
- break;
- }
-
- if (o_item)
- {
- pitem = o_item;
- }
- else
- {
- pitem = &item;
- }
-
- rc = xipDecodeToc(i_image, toc, pitem);
-
- if (rc)
- {
- break;
- }
-
- }
- while (0);
-
- return rc;
-}
-
-int
-p9_xip_get_item(const P9XipItem* i_item, uint64_t* o_data, uint32_t i_index)
-{
- if ((i_item->iv_elements != 0) && (i_index >= i_item->iv_elements))
- {
- return TRACE_ERROR(P9_XIP_BOUNDS_ERROR);
- }
-
- switch (i_item->iv_type)
- {
- case P9_XIP_UINT8:
- *o_data = ((uint8_t*)(i_item->iv_imageData))[i_index];
- break;
-
- case P9_XIP_UINT16:
- *o_data = htobe16(((uint16_t*)(i_item->iv_imageData))[i_index]);
- break;
-
- case P9_XIP_UINT32:
- *o_data = htobe32(((uint32_t*)(i_item->iv_imageData))[i_index]);
- break;
-
- case P9_XIP_UINT64:
- *o_data = htobe64(((uint64_t*)(i_item->iv_imageData))[i_index]);
- break;
-
- case P9_XIP_INT8:
- *o_data = ((int8_t*)(i_item->iv_imageData))[i_index];
- break;
-
- case P9_XIP_INT16:
- *o_data = htobe16(((int16_t*)(i_item->iv_imageData))[i_index]);
- break;
-
- case P9_XIP_INT32:
- *o_data = htobe32(((int32_t*)(i_item->iv_imageData))[i_index]);
- break;
-
- case P9_XIP_INT64:
- *o_data = htobe64(((int64_t*)(i_item->iv_imageData))[i_index]);
- break;
-
- case P9_XIP_ADDRESS:
- if (i_index)
- {
- return TRACE_ERROR(P9_XIP_BOUNDS_ERROR);
- }
-
- *o_data = i_item->iv_address;
- break;
-
- case P9_XIP_STRING:
- //Nothing to do in case of string, but making sure rc is valid
- break;
-
- default:
- return TRACE_ERROR(P9_XIP_TYPE_ERROR);
- break;
- }
-
- return 0;
-}
-
-int
-p9_xip_get_element(void* i_image,
- const char* i_id,
- const uint32_t i_index,
- uint64_t* o_data)
-{
- int rc;
- P9XipItem item;
-
- rc = p9_xip_find(i_image, i_id, &item);
-
- if (rc)
- {
- return rc;
- }
-
- return p9_xip_get_item(&item, o_data, i_index);
-}
-
-
-int
-p9_xip_get_scalar(void* i_image, const char* i_id, uint64_t* o_data)
-{
- return p9_xip_get_element(i_image, i_id, 0, o_data);
-}
-
-int
-p9_xip_get_string(void* i_image, const char* i_id, char** o_data)
-{
- int rc;
- P9XipItem item;
-
- rc = p9_xip_find(i_image, i_id, &item);
-
- if (!rc)
- {
- switch (item.iv_type)
- {
- case P9_XIP_STRING:
- *o_data = (char*)(item.iv_imageData);
- break;
-
- default:
- rc = TRACE_ERROR(P9_XIP_TYPE_ERROR);
- break;
- }
- }
-
- return rc;
-}
-
-
-int
-p9_xip_read_uint64(const void* i_image,
- const uint64_t i_imageAddress,
- uint64_t* o_data)
-{
- int rc;
-
- do
- {
- rc = xipQuickCheck(i_image, 0);
-
- if (rc)
- {
- break;
- }
-
- rc = xipValidateImageAddress(i_image, i_imageAddress, 8);
-
- if (rc)
- {
- break;
- }
-
- if (i_imageAddress % 8)
- {
- rc = TRACE_ERROR(P9_XIP_ALIGNMENT_ERROR);
- break;
- }
-
- *o_data =
- htobe64(*((uint64_t*)xipImage2Host(i_image, i_imageAddress)));
-
- }
- while(0);
-
- return rc;
-}
-
-
-int
-p9_xip_set_scalar(void* io_image, const char* i_id, const uint64_t i_data)
-{
- int rc;
- P9XipItem item;
-
- rc = p9_xip_find(io_image, i_id, &item);
-
- if (!rc)
- {
- switch(item.iv_type)
- {
- case P9_XIP_UINT8:
- *((uint8_t*)(item.iv_imageData)) = (uint8_t)i_data;
- break;
-
- case P9_XIP_UINT16:
- *((uint16_t*)(item.iv_imageData)) = htobe16((uint16_t)i_data);
- break;
-
- case P9_XIP_UINT32:
- *((uint32_t*)(item.iv_imageData)) = htobe32((uint32_t)i_data);
- break;
-
- case P9_XIP_UINT64:
- *((uint64_t*)(item.iv_imageData)) = htobe64((uint64_t)i_data);
- break;
-
- case P9_XIP_INT8:
- *((int8_t*)(item.iv_imageData)) = (int8_t)i_data;
- break;
-
- case P9_XIP_INT16:
- *((int16_t*)(item.iv_imageData)) = htobe16((int16_t)i_data);
- break;
-
- case P9_XIP_INT32:
- *((int32_t*)(item.iv_imageData)) = htobe32((int32_t)i_data);
- break;
-
- case P9_XIP_INT64:
- *((int64_t*)(item.iv_imageData)) = htobe64((int64_t)i_data);
- break;
-
- default:
- rc = TRACE_ERROR(P9_XIP_TYPE_ERROR);
- break;
- }
- }
-
- return rc;
-}
-
-
-int
-p9_xip_set_element(void* i_image,
- const char* i_id,
- const uint32_t i_index,
- const uint64_t i_data)
-{
- int rc;
- P9XipItem item;
-
- do
- {
- rc = p9_xip_find(i_image, i_id, &item);
-
- if (rc)
- {
- break;
- }
-
- if ((item.iv_elements != 0) && (i_index >= item.iv_elements))
- {
- rc = TRACE_ERROR(P9_XIP_BOUNDS_ERROR);
- break;
- }
-
- switch (item.iv_type)
- {
- case P9_XIP_UINT8:
- ((uint8_t*)(item.iv_imageData))[i_index] = (uint8_t)i_data;
- break;
-
- case P9_XIP_UINT16:
- ((uint16_t*)(item.iv_imageData))[i_index] =
- htobe16((uint16_t)i_data);
- break;
-
- case P9_XIP_UINT32:
- ((uint32_t*)(item.iv_imageData))[i_index] =
- htobe32((uint32_t)i_data);
- break;
-
- case P9_XIP_UINT64:
- ((uint64_t*)(item.iv_imageData))[i_index] =
- htobe64((uint64_t)i_data);
- break;
-
- case P9_XIP_INT8:
- ((int8_t*)(item.iv_imageData))[i_index] = (int8_t)i_data;
- break;
-
- case P9_XIP_INT16:
- ((int16_t*)(item.iv_imageData))[i_index] =
- htobe16((uint16_t)i_data);
- break;
-
- case P9_XIP_INT32:
- ((int32_t*)(item.iv_imageData))[i_index] =
- htobe32((uint32_t)i_data);
- break;
-
- case P9_XIP_INT64:
- ((int64_t*)(item.iv_imageData))[i_index] =
- htobe64((uint64_t)i_data);
- break;
-
- default:
- rc = TRACE_ERROR(P9_XIP_TYPE_ERROR);
- break;
- }
-
- if (rc)
- {
- break;
- }
-
- }
- while (0);
-
- return rc;
-}
-
-
-int
-p9_xip_set_string(void* i_image, const char* i_id, const char* i_data)
-{
- int rc;
- P9XipItem item;
- char* dest;
-
- rc = p9_xip_find(i_image, i_id, &item);
-
- if (!rc)
- {
- switch (item.iv_type)
- {
- case P9_XIP_STRING:
- dest = (char*)(item.iv_imageData);
-
- if (strlen(dest) < strlen(i_data))
- {
- memcpy(dest, i_data, strlen(dest));
- }
- else
- {
- strcpy(dest, i_data);
- }
-
- break;
-
- default:
- rc = TRACE_ERROR(P9_XIP_TYPE_ERROR);
- break;
- }
- }
-
- return rc;
-}
-
-
-int
-p9_xip_write_uint64(void* io_image,
- const uint64_t i_imageAddress,
- const uint64_t i_data)
-{
- int rc;
-
- do
- {
- rc = xipQuickCheck(io_image, 0);
-
- if (rc)
- {
- break;
- }
-
- rc = xipValidateImageAddress(io_image, i_imageAddress, 8);
-
- if (rc)
- {
- break;
- }
-
- if (i_imageAddress % 8)
- {
- rc = TRACE_ERROR(P9_XIP_ALIGNMENT_ERROR);
- break;
- }
-
- *((uint64_t*)xipImage2Host(io_image, i_imageAddress)) =
- htobe64(i_data);
-
- }
- while(0);
-
- return rc;
-}
-
-
-int
-p9_xip_delete_section(void* io_image,
- void* o_imageBuf,
- const uint32_t i_imageBufSize,
- const int i_sectionId)
-{
- int rc, final;
- P9XipSection section;
- size_t imageSize;
- uint8_t bImageChanged = 0; // Tracks if io_image has been modified.
-
- do
- {
-
- // Get image size. We'll need it a lot.
-
- imageSize = xipImageSize(io_image);
-
- // Parm check 1: imageBufSize
- // - Must be >=imageSize for a valid imageBuf buffer
-
- if (i_imageBufSize < imageSize && o_imageBuf != NULL)
- {
- rc = TRACE_ERRORX(P9_XIP_WOULD_OVERFLOW,
- "xip_delete_section(): imageBufSize too small");
- break;
- }
-
- // Parm check 2: sectionId
- // - It is illegal to remove the .header. It would kill the image.
-
- if (i_sectionId == P9_XIP_SECTION_HEADER)
- {
- rc = TRACE_ERRORX(P9_XIP_SECTION_ERROR,
- "xip_delete_section(): It is illegal to remove .header");
- break;
- }
-
- // Copy io_image to o_imageBuf if a valid imageBuf ptr is
- // supplied, i.e., imageBuf!=NULL. We'll need a reference copy
- // of any delected section to be re-appended after the section
- // delete process is done.
- if (o_imageBuf != NULL)
- {
- // We always return a copy of the original input image.
- memcpy(o_imageBuf, io_image, imageSize);
- }
-
- // Check the image
-
- rc = xipQuickCheck(io_image, 1);
-
- if (rc)
- {
- break;
- }
-
- // Deleting an empty section is a NOP. Otherwise the section must be
- // the final section of the image. Update the sizes and re-establish
- // the final image alignment.
-
- rc = p9_xip_get_section(io_image, i_sectionId, &section);
-
- if (rc)
- {
- break;
- }
-
- if (section.iv_size == 0)
- {
- break;
- }
-
- // Determine last image section.
-
- rc = xipFinalSection(io_image, &final);
-
- if (rc)
- {
- break;
- }
-
- // Now, delete necessary sections in order of highest section offset
- // to the offset of the section, i_sectionId, to be removed.
-
- if (final == i_sectionId)
- {
- rc = xipDeleteLastSection(io_image, i_sectionId);
-
- bImageChanged = 1;
-
- break;
- }
- else
- {
- // Check for imageBuf ptr violation. If this fails, this is
- // catastrophic since we don't have a reference copy of the input
- // image (i.e, the memcpy of the image earlier wasn't executed.)
-
- if (o_imageBuf == NULL)
- {
- rc = TRACE_ERRORX(P9_XIP_NULL_BUFFER,
- "xip_delete_section(): Can't copy image into NULL buffer\n");
- break;
- }
-
- // Delete sections, in order, that have offset addresses higher
- // than i_sectionId and make a note of the order which is to
- // be used when re-appending. Then delete i_sectionId.
-
- uint8_t sectionOrder[P9_XIP_SECTIONS];
- uint8_t orderIdx = 0;
-
- do
- {
-
- rc = xipFinalSection(io_image, &final);
-
- if (rc)
- {
- break;
- }
-
- // It is illegal to remove .header. It would kill the image.
- if (final == P9_XIP_SECTION_HEADER)
- {
- rc = TRACE_ERRORX(P9_XIP_SECTION_ERROR,
- "xip_delete_section(): Code bug: Attempt to remove .header");
- break;
- }
-
- if (final != i_sectionId)
- {
- sectionOrder[orderIdx] = final;
- orderIdx++;
- }
-
- rc = xipDeleteLastSection(io_image, final);
-
- bImageChanged = 1;
-
- if (rc)
- {
- break;
- }
-
- }
- while (final != i_sectionId);
-
- if (rc)
- {
- break;
- }
-
- // Reappend previously deleted sections in original order
-
- do
- {
-
- orderIdx--;
- rc = p9_xip_get_section(o_imageBuf, sectionOrder[orderIdx], &section);
-
- if (rc)
- {
- break;
- }
-
- rc = p9_xip_append( io_image,
- sectionOrder[orderIdx],
- (void*)(((uint8_t*)o_imageBuf) + section.iv_offset),
- (const uint32_t)section.iv_size,
- (const uint32_t)imageSize,
- NULL );
-
- if (rc)
- {
- break;
- }
-
- }
- while (orderIdx);
-
- break;
- }
-
- }
- while (0);
-
- // Restore broken input image in case of rc!=0. But only do so if input
- // image has changed.
-
- if (rc && bImageChanged)
- {
- memcpy(io_image, o_imageBuf, imageSize);
- }
-
- return rc;
-}
-
-
-#ifndef PPC_HYP
-
-// This API is not needed by PHYP procedures, and is elided since PHYP does
-// not support malloc().
-
-int
-p9_xip_duplicate_section(const void* i_image,
- const int i_sectionId,
- void** o_duplicate,
- uint32_t* o_size)
-{
- P9XipSection section;
- int rc;
-
- *o_duplicate = 0;
-
- do
- {
- rc = xipQuickCheck(i_image, 0);
-
- if (rc)
- {
- break;
- }
-
- rc = p9_xip_get_section(i_image, i_sectionId, &section);
-
- if (rc)
- {
- break;
- }
-
- if (section.iv_size == 0)
- {
- rc = TRACE_ERRORX(P9_XIP_SECTION_ERROR,
- "Attempt to duplicate empty section %d\n",
- i_sectionId);
- break;
- }
-
- *o_duplicate = malloc(section.iv_size);
- *o_size = section.iv_size;
-
- if (*o_duplicate == 0)
- {
- rc = TRACE_ERROR(P9_XIP_NO_MEMORY);
- break;
- }
-
- memcpy(*o_duplicate,
- xipHostAddressFromOffset(i_image, section.iv_offset),
- section.iv_size);
-
-
- }
- while (0);
-
- if (rc)
- {
- free(*o_duplicate);
- *o_duplicate = 0;
- *o_size = 0;
- }
-
- return rc;
-}
-
-#endif // PPC_HYP
-
-
-// The append must be done in such a way that if the append fails, the image
-// is not modified. This behavior is required by applications that
-// speculatively append until the allocation fails, but still require the
-// final image to be valid. To accomplish this the initial image size and
-// section statistics are captured at entry, and restored in the event of an
-// error.
-
-int
-p9_xip_append(void* io_image,
- const int i_sectionId,
- const void* i_data,
- const uint32_t i_size,
- const uint32_t i_allocation,
- uint32_t* o_sectionOffset)
-{
- P9XipSection section, initialSection;
- int rc, final, restoreOnError;
- void* hostAddress;
- uint32_t pad, initialSize;
-
- do
- {
- restoreOnError = 0;
-
- rc = xipQuickCheck(io_image, 1);
-
- if (rc)
- {
- break;
- }
-
- rc = p9_xip_get_section(io_image, i_sectionId, &section);
-
- if (rc)
- {
- break;
- }
-
- if (i_size == 0)
- {
- break;
- }
-
- initialSection = section;
- initialSize = xipImageSize(io_image);
- restoreOnError = 1;
-
- if (section.iv_size == 0)
- {
-
- // The section is empty, and now becomes the final section. Pad
- // the image to the specified section alignment. Note that the
- // size of the previously final section does not change.
-
- rc = xipPadImage(io_image, i_allocation, section.iv_alignment,
- &pad);
-
- if (rc)
- {
- break;
- }
-
- section.iv_offset = xipImageSize(io_image);
-
- }
- else
- {
-
- // Otherwise, the section must be the final section in order to
- // continue. Remove any padding from the image.
-
- rc = xipFinalSection(io_image, &final);
-
- if (rc)
- {
- break;
- }
-
- if (final != i_sectionId)
- {
- rc = TRACE_ERRORX(P9_XIP_SECTION_ERROR,
- "Attempt to append to non-final section "
- "%d\n", i_sectionId);
- break;
- }
-
- xipSetImageSize(io_image, section.iv_offset + section.iv_size);
- }
-
-
- // Make sure the allocated space won't overflow. Set the return
- // parameter o_sectionOffset and copy the new data into the image (or
- // simply clear the space).
-
- if ((xipImageSize(io_image) + i_size) > i_allocation)
- {
- rc = TRACE_ERROR(P9_XIP_WOULD_OVERFLOW);
- break;
- }
-
- if (o_sectionOffset != 0)
- {
- *o_sectionOffset = section.iv_size;
- }
-
- hostAddress =
- xipHostAddressFromOffset(io_image, xipImageSize(io_image));
-
- if (i_data == 0)
- {
- memset(hostAddress, 0, i_size);
- }
- else
- {
- memcpy(hostAddress, i_data, i_size);
- }
-
-
- // Update the image size and section table. Note that the final
- // alignment may push out of the allocation.
-
- xipSetImageSize(io_image, xipImageSize(io_image) + i_size);
- xipFinalAlignment(io_image);
-
- if (xipImageSize(io_image) > i_allocation)
- {
- rc = TRACE_ERROR(P9_XIP_WOULD_OVERFLOW);
- break;
- }
-
- section.iv_size += i_size;
-
- if (xipPutSection(io_image, i_sectionId, &section) != 0)
- {
- rc = TRACE_ERROR(P9_XIP_BUG); /* Can't happen */
- break;
- }
-
-
- // Special case
-
- if (i_sectionId == P9_XIP_SECTION_TOC)
- {
- ((P9XipHeader*)io_image)->iv_tocSorted = 0;
- }
-
- }
- while (0);
-
- if (rc && restoreOnError)
- {
- if (xipPutSection(io_image, i_sectionId, &initialSection) != 0)
- {
- rc = TRACE_ERROR(P9_XIP_BUG); /* Can't happen */
- }
-
- xipSetImageSize(io_image, initialSize);
- }
-
- return rc;
-}
-
-
-int
-p9_xip_section2image(const void* i_image,
- const int i_sectionId,
- const uint32_t i_offset,
- uint64_t* o_imageAddress)
-{
- int rc;
- P9XipSection section;
-
- do
- {
- rc = xipQuickCheck(i_image, 0);
-
- if (rc)
- {
- break;
- }
-
- rc = p9_xip_get_section(i_image, i_sectionId, &section);
-
- if (rc)
- {
- break;
- }
-
- if (section.iv_size == 0)
- {
- rc = TRACE_ERROR(P9_XIP_SECTION_ERROR);
- break;
- }
-
- if (i_offset > (section.iv_offset + section.iv_size))
- {
- rc = TRACE_ERROR(P9_XIP_INVALID_ARGUMENT);
- break;
- }
-
- *o_imageAddress = xipLinkAddress(i_image) + section.iv_offset + i_offset;
-
- if (*o_imageAddress % 4)
- {
- rc = TRACE_ERROR(P9_XIP_ALIGNMENT_ERROR);
- break;
- }
-
- }
- while(0);
-
- return rc;
-}
-
-
-int
-p9_xip_image2section(const void* i_image,
- const uint64_t i_imageAddress,
- int* i_section,
- uint32_t* i_offset)
-{
- int rc;
-
- do
- {
- rc = xipQuickCheck(i_image, 0);
-
- if (rc)
- {
- break;
- }
-
- rc = xipImage2Section(i_image, i_imageAddress, i_section, i_offset);
-
- }
- while(0);
-
- return rc;
-}
-
-
-int
-p9_xip_image2host(const void* i_image,
- const uint64_t i_imageAddress,
- void** o_hostAddress)
-{
- int rc;
-
- do
- {
- rc = xipQuickCheck(i_image, 0);
-
- if (rc)
- {
- break;
- }
-
- if ((i_imageAddress < xipLinkAddress(i_image)) ||
- (i_imageAddress >
- (xipLinkAddress(i_image) + xipImageSize(i_image))))
- {
- rc = TRACE_ERROR(P9_XIP_INVALID_ARGUMENT);
- break;
- }
-
- *o_hostAddress =
- xipHostAddressFromOffset(i_image,
- i_imageAddress - xipLinkAddress(i_image));
- }
- while(0);
-
- return rc;
-}
-
-
-int
-p9_xip_host2image(const void* i_image,
- void* i_hostAddress,
- uint64_t* o_imageAddress)
-{
- int rc;
-
- do
- {
- rc = xipQuickCheck(i_image, 0);
-
- if (rc)
- {
- break;
- }
-
- if ((i_hostAddress < i_image) ||
- (i_hostAddress >
- xipHostAddressFromOffset(i_image, xipImageSize(i_image))))
- {
- rc = TRACE_ERROR(P9_XIP_INVALID_ARGUMENT);
- break;
- }
-
- *o_imageAddress = xipLinkAddress(i_image) +
- ((unsigned long)i_hostAddress - (unsigned long)i_image);
-
- if (*o_imageAddress % 4)
- {
- rc = TRACE_ERROR(P9_XIP_ALIGNMENT_ERROR);
- break;
- }
- }
- while(0);
-
- return rc;
-}
-
-
-void
-p9_xip_translate_header(P9XipHeader* o_dest, const P9XipHeader* i_src)
-{
-#ifndef _BIG_ENDIAN
- int i;
- P9XipSection* destSection;
- const P9XipSection* srcSection;
-
-#if P9_XIP_HEADER_VERSION != 9
-#error This code assumes the P9-XIP header version 9 layout
-#endif
-
- o_dest->iv_magic = htobe64(i_src->iv_magic);
- o_dest->iv_L1LoaderAddr = htobe64(i_src->iv_L1LoaderAddr);
- o_dest->iv_L2LoaderAddr = htobe64(i_src->iv_L2LoaderAddr);
- o_dest->iv_kernelAddr = htobe64(i_src->iv_kernelAddr);
- o_dest->iv_linkAddress = htobe64(i_src->iv_linkAddress);
-
- memset(o_dest->iv_reserved64, 0, sizeof(i_src->iv_reserved64));
-
- for (i = 0, destSection = o_dest->iv_section,
- srcSection = i_src->iv_section;
- i < P9_XIP_SECTIONS;
- i++, destSection++, srcSection++)
- {
- xipTranslateSection(destSection, srcSection);
- }
-
- o_dest->iv_imageSize = htobe32(i_src->iv_imageSize);
- o_dest->iv_buildDate = htobe32(i_src->iv_buildDate);
- o_dest->iv_buildTime = htobe32(i_src->iv_buildTime);
- memcpy(o_dest->iv_buildTag, i_src->iv_buildTag,
- sizeof(i_src->iv_buildTag));
-
- o_dest->iv_headerVersion = i_src->iv_headerVersion;
- o_dest->iv_normalized = i_src->iv_normalized;
- o_dest->iv_tocSorted = i_src->iv_tocSorted;
-
- memset(o_dest->iv_reserved8, 0, sizeof(i_src->iv_reserved8));
-
- memcpy(o_dest->iv_buildUser, i_src->iv_buildUser,
- sizeof(i_src->iv_buildUser));
- memcpy(o_dest->iv_buildHost, i_src->iv_buildHost,
- sizeof(i_src->iv_buildHost));
- memcpy(o_dest->iv_reservedChar, i_src->iv_reservedChar,
- sizeof(i_src->iv_reservedChar));
-#else
-
- if (o_dest != i_src)
- {
- *o_dest = *i_src;
- }
-
-#endif /* _BIG_ENDIAN */
-}
-
-
-int
-p9_xip_map_toc(void* io_image,
- int (*i_fn)(void* io_image,
- const P9XipItem* i_item,
- void* io_arg),
- void* io_arg)
-{
- int rc;
- P9XipToc* imageToc;
- P9XipItem item;
- size_t entries;
-
- do
- {
- rc = xipQuickCheck(io_image, 0);
-
- if (rc)
- {
- break;
- }
-
- rc = p9_xip_get_toc(io_image, &imageToc, &entries, 0, 0);
-
- if (rc)
- {
- break;
- }
-
- for (; entries--; imageToc++)
- {
- rc = xipDecodeToc(io_image, imageToc, &item);
-
- if (rc)
- {
- break;
- }
-
- rc = i_fn(io_image, &item, io_arg);
-
- if (rc)
- {
- break;
- }
- }
- }
- while(0);
-
- return rc;
-}
OpenPOWER on IntegriCloud