diff options
author | Claus Michael Olsen <cmolsen@us.ibm.com> | 2016-08-10 15:13:32 -0500 |
---|---|---|
committer | Sachin Gupta <sgupta2m@in.ibm.com> | 2016-08-24 11:36:34 -0400 |
commit | f98936ce13c5e2087d335f30cbf81e70776e15dd (patch) | |
tree | f61786811b6d430cd4e88f2b71426d5889161049 /import | |
parent | bb68965f35de82a0bb6fc5680c6aab6b4b5b227b (diff) | |
download | talos-sbe-f98936ce13c5e2087d335f30cbf81e70776e15dd.tar.gz talos-sbe-f98936ce13c5e2087d335f30cbf81e70776e15dd.zip |
p9_xip_delete_section: Modified API
This API has been updated to remove any random section, not just the
last section.
Also, an update has been made to p9_xip_tool, which uses this API.
Change-Id: I0acdcd24d860093322cf13abf98511032e5b3eb1
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/28125
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: PPE CI <ppe-ci+hostboot@us.ibm.com>
Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com>
Reviewed-by: Richard J. Knight <rjknight@us.ibm.com>
Reviewed-by: Prachi Gupta <pragupta@us.ibm.com>
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/28130
Reviewed-by: Hostboot Team <hostboot@us.ibm.com>
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Reviewed-by: Sachin Gupta <sgupta2m@in.ibm.com>
Diffstat (limited to 'import')
-rw-r--r-- | import/chips/p9/xip/p9_xip_image.c | 223 | ||||
-rw-r--r-- | import/chips/p9/xip/p9_xip_image.h | 47 | ||||
-rw-r--r-- | import/chips/p9/xip/p9_xip_tool.C | 14 |
3 files changed, 243 insertions, 41 deletions
diff --git a/import/chips/p9/xip/p9_xip_image.c b/import/chips/p9/xip/p9_xip_image.c index 19474172..0f9ce1f7 100644 --- a/import/chips/p9/xip/p9_xip_image.c +++ b/import/chips/p9/xip/p9_xip_image.c @@ -51,7 +51,6 @@ #include <endian.h> #include "p9_xip_image.h" - //////////////////////////////////////////////////////////////////////////// // Local Functions //////////////////////////////////////////////////////////////////////////// @@ -101,7 +100,6 @@ XIP_STATIC P9_XIP_ERROR_STRINGS(p9_xip_error_strings); (x); \ }) - // Uncomment these if required for debugging, otherwise we get warnings from // GCC as they are not otherwise used. @@ -640,6 +638,53 @@ xipImage2Section(const void* i_image, } +// 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, §ion); + + 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. @@ -2477,62 +2522,79 @@ p9_xip_write_uint64(void* io_image, int -p9_xip_delete_section(void* io_image, const int i_sectionId) +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 { - rc = xipQuickCheck(io_image, 1); - if (rc) + // 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; } - rc = p9_xip_get_section(io_image, i_sectionId, §ion); + // Parm check 2: sectionId + // - It is illegal to remove the .header. It would kill the image. - if (rc) + 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); + } - // 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. + // Check the image - if (section.iv_size == 0) + rc = xipQuickCheck(io_image, 1); + + if (rc) { break; } - rc = xipFinalSection(io_image, &final); + // 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, §ion); if (rc) { break; } - if (final != i_sectionId) + if (section.iv_size == 0) { - rc = TRACE_ERRORX(P9_XIP_SECTION_ERROR, - "Attempt to delete non-final section %d\n", - i_sectionId); break; } - 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. + // Determine last image section. rc = xipFinalSection(io_image, &final); @@ -2541,19 +2603,120 @@ p9_xip_delete_section(void* io_image, const int i_sectionId) break; } - rc = p9_xip_get_section(io_image, final, §ion); + // Now, delete necessary sections in order of highest section offset + // to the offset of the section, i_sectionId, to be removed. - if (rc) + 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.) - xipSetImageSize(io_image, section.iv_offset + section.iv_size); - xipFinalAlignment(io_image); + 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], §ion); + + 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; } diff --git a/import/chips/p9/xip/p9_xip_image.h b/import/chips/p9/xip/p9_xip_image.h index 92fb45ca..09bc1aa5 100644 --- a/import/chips/p9/xip/p9_xip_image.h +++ b/import/chips/p9/xip/p9_xip_image.h @@ -1035,23 +1035,38 @@ p9_xip_find(void* i_image, -/// Delete a section from a P9-XIP image in host memory +/// Delete any section, except .header, from a P9-XIP image in host memory, +/// even in-between sections, i.e. non-final sections. /// /// \param[in,out] io_image A pointer to a P9-XIP image in host memory. The /// image is assumed to be consistent with the information contained in the /// header regarding the presence of and sizes of all sections. The image is -/// also required to have been normalized. +/// also required to have been normalized. In case of failure in this +/// funtion, the io_image will get restored to its input value. +/// +/// \param[out] o_imageBuf A pointer to a pre-allocated buffer that MUST +/// BE greater than or equal to the size of the \a io_image. The size of +/// this buffer must be supplied in \a i_imageBufSize. If \a o_imageBuf +/// is NULL, the supplied \a i_sectionId must be the final section in the +/// image or this function will fail at deleting the section. On return +/// from this function, o_imageBuf contains a copy of the initial input +/// image \a io_image, but only if it's a valid buffer. +/// +/// \param[in] i_imageBufSize The size of \a o_imageBuf buffer. It MUST +/// BE greater than or equal to the size of \a io_image. However, if \a +/// o_imageBuf is NULL, then this arg is ignored. /// /// \param[in] i_sectionId Identifies the section to be deleted. See \ref /// p9_xip_sections. /// /// This API effectively deletes a section from a P9-XIP image held in host -/// memory. Unless the requested section \a i_section is already empty, only -/// the final (highest address offset) section of the image may be deleted. -/// Deleting the final section of the image means that the section size is set -/// to 0, and the size of the image recorded in the header is reduced by the -/// section size. Any alignment padding of the now-last section is also -/// removed. +/// memory. Deleting a section of the image means that the section size is +/// set to 0, and the size of the image recorded in the header is reduced by +/// the section size. Any alignment padding of the in-between section is +/// also handled, i.e. removed if final section and re-applied upon +/// re-appending sections. In the special case where \a o_imageBuf is +/// NULL, unless the requested \a i_sectionId is already empty, only the final +/// section (highest address offset) of the image may be deleted. /// /// \note This API does not check for or warn if other sections in the image /// reference the deleted section. @@ -1060,7 +1075,11 @@ p9_xip_find(void* i_image, /// /// \retval non-0 See \ref p9_xip_image_errors int -p9_xip_delete_section(void* io_image, const int i_sectionId); +p9_xip_delete_section(void* io_image, + void* o_imageBuf, + const uint32_t i_imageBufSize, + const int i_sectionId); + #ifndef PPC_HYP @@ -1422,9 +1441,15 @@ p9_xip_decode_toc_dump(void* i_image, void* i_dump, /// Error associated with the disassembler occured. #define P9_XIP_DISASSEMBLER_ERROR 15 -/// hash collision creating the .fixed_toc section +/// Hash collision creating the .fixed_toc section #define P9_XIP_HASH_COLLISION 16 +/// Invalid buffer. It had a NULL ptr. +#define P9_XIP_NULL_BUFFER 17 + +/// Image has been broken and unable to restore original image. +#define P9_XIP_CANT_RESTORE_IMAGE 18 + /// Applications can expand this macro to declare an array of string forms of /// the error codes if desired. #define P9_XIP_ERROR_STRINGS(var) \ @@ -1446,6 +1471,8 @@ p9_xip_decode_toc_dump(void* i_image, void* i_dump, "P9_XIP_WOULD_OVERFLOW", \ "P9_XIP_DISASSEMBLER_ERROR", \ "P9_XIP_HASH_COLLISION", \ + "P9_XIP_NULL_BUFFER", \ + "P9_XIP_CANT_RESTORE_IMAGE", \ } /// Applications can use this macro to safely index the array of error diff --git a/import/chips/p9/xip/p9_xip_tool.C b/import/chips/p9/xip/p9_xip_tool.C index e35c4e8b..dd48e250 100644 --- a/import/chips/p9/xip/p9_xip_tool.C +++ b/import/chips/p9/xip/p9_xip_tool.C @@ -1454,6 +1454,7 @@ deleteSection(const char* i_imageFile, const int i_imageFd, void* io_image, const char* section; const char** argv; void* newImage; + void* tempImage; uint32_t size; P9XipHeader header; @@ -1491,6 +1492,17 @@ deleteSection(const char* i_imageFile, const int i_imageFd, void* io_image, exit(1); } + // Create a temporary place holder for image + + tempImage = malloc(size); + + if (tempImage == 0) + { + fprintf(stderr, "Can't malloc() a buffer for the temporary image\n"); + exit(1); + } + + p9_xip_translate_header(&header, (P9XipHeader*)io_image); // Delete the sections in argument order @@ -1512,7 +1524,7 @@ deleteSection(const char* i_imageFile, const int i_imageFd, void* io_image, // Delete the section - rc = p9_xip_delete_section(newImage, sectionId); + rc = p9_xip_delete_section(newImage, tempImage, size, sectionId); if (rc) { |