From c2c5d0e657f6229b9d248fde3195708e303adce1 Mon Sep 17 00:00:00 2001 From: "Richard J. Knight" Date: Tue, 27 Jun 2017 12:16:16 -0500 Subject: p9_xip_tool support for DD level section parsing - Currently supports only .overlays section. - Fixed an heap problem causing segmentation fault after repetitive use of malloc in rs4_decompress() and rs4_extract_cmsk(). Now allocating buffers locally and calling _rs4_decompress() and _rs4_extract_cmsk() instead so only have to use malloc once. - Fixed a bug in the usage of the ringBlockPtr which got moved away from pointing to its initially allocated buffer after the first CMSK ring is processed. - Even though malloc() can be used in a C++ context, we really should be using the new() operator. So, I replaced all malloc() and free() with new() and delete() instead in both p9_xip_tool.C and p9_scan_compression.C. Change-Id: I2da7509ed7aaa13345185dc07bce57f71c3740fd Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/42531 Tested-by: FSP CI Jenkins Tested-by: Jenkins Server Tested-by: HWSV CI Tested-by: PPE CI Tested-by: Hostboot CI Reviewed-by: Richard J. Knight Reviewed-by: Sumit Kumar Reviewed-by: Jennifer A. Stofer Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/42803 Tested-by: Jenkins OP Build CI Tested-by: Jenkins OP HW Reviewed-by: Christian R. Geddes --- .../p9/utils/imageProcs/p9_infrastruct_help.H | 4 + .../p9/utils/imageProcs/p9_scan_compression.C | 157 +++++++++++++-------- .../p9/utils/imageProcs/p9_scan_compression.H | 63 ++++++--- 3 files changed, 151 insertions(+), 73 deletions(-) (limited to 'src/import/chips/p9/utils') diff --git a/src/import/chips/p9/utils/imageProcs/p9_infrastruct_help.H b/src/import/chips/p9/utils/imageProcs/p9_infrastruct_help.H index 284765273..bb8ab5c1f 100644 --- a/src/import/chips/p9/utils/imageProcs/p9_infrastruct_help.H +++ b/src/import/chips/p9/utils/imageProcs/p9_infrastruct_help.H @@ -43,6 +43,10 @@ const uint32_t MAX_SEEPROM_IMAGE_SIZE = 4 * ((64 * 1024) / 9 * 8) - 256; // Max Seeprom image size, excl ECC bits (4 banks). const uint32_t MAX_RT_IMAGE_SIZE = 1024 * 1024; // Max Runtime size. const uint32_t MAX_RING_BUF_SIZE = 60000; // Max ring buffer size. +const uint32_t MAX_RING_BUF_SIZE_TOOL = 200000; // Max ring buf size for tools. +// (i.e., n3_fure.bin.srd is some +// 346,000B x 4b/B = 1,384,000b = +// 173,000B binary w 8b/B) const uint32_t MAX_OVERRIDES_SIZE = 2 * 1024; // Max overrides section size. const uint32_t MAX_HBBL_SIZE = 20 * 1024; // Max hbbl section size. diff --git a/src/import/chips/p9/utils/imageProcs/p9_scan_compression.C b/src/import/chips/p9/utils/imageProcs/p9_scan_compression.C index f5332b8c6..50c6c627f 100644 --- a/src/import/chips/p9/utils/imageProcs/p9_scan_compression.C +++ b/src/import/chips/p9/utils/imageProcs/p9_scan_compression.C @@ -674,7 +674,7 @@ rs4_compress(CompressedScanData** o_rs4, uint32_t nibbles = rs4_max_compressed_nibbles(i_length); uint32_t bytes = rs4_max_compressed_bytes(nibbles); - *o_rs4 = (CompressedScanData*)malloc(bytes); + *o_rs4 = (CompressedScanData*)(operator new(bytes)); if (*o_rs4 == 0) { @@ -693,15 +693,15 @@ rs4_compress(CompressedScanData** o_rs4, // Returns a scan compression return code. static int -__rs4_decompress(uint8_t* io_data_str, - uint8_t* io_care_str, +__rs4_decompress(uint8_t* o_data_str, + uint8_t* o_care_str, uint32_t i_size, uint32_t* o_length, const uint8_t* i_rs4_str) { int state; /* 0 : Rotate, 1 : Scan */ uint32_t i; /* Nibble index in i_rs4_str */ - uint32_t j; /* Nibble index in io_data_str/io_care_str */ + uint32_t j; /* Nibble index in o_data_str/o_care_str */ uint32_t k; /* Loop index */ uint32_t bits; /* Number of output bits decoded so far */ uint32_t count; /* Count of rotate nibbles */ @@ -715,7 +715,6 @@ __rs4_decompress(uint8_t* io_data_str, state = 0; // Decompress the bulk of the string - do { if (state == 0) @@ -757,9 +756,9 @@ __rs4_decompress(uint8_t* io_data_str, for (k = 0; k < nibbles; k++) { - rs4_set_nibble(io_care_str, j, rs4_get_nibble(i_rs4_str, i)); + rs4_set_nibble(o_care_str, j, rs4_get_nibble(i_rs4_str, i)); i = (masked ? i + 1 : i); - rs4_set_nibble(io_data_str, j, rs4_get_nibble(i_rs4_str, i)); + rs4_set_nibble(o_data_str, j, rs4_get_nibble(i_rs4_str, i)); i++; j++; } @@ -785,9 +784,9 @@ __rs4_decompress(uint8_t* io_data_str, if (r != 0) { - rs4_set_nibble(io_care_str, j, rs4_get_nibble(i_rs4_str, i)); + rs4_set_nibble(o_care_str, j, rs4_get_nibble(i_rs4_str, i)); i = (masked ? i + 1 : i); - rs4_set_nibble(io_data_str, j, rs4_get_nibble(i_rs4_str, i)); + rs4_set_nibble(o_data_str, j, rs4_get_nibble(i_rs4_str, i)); } *o_length = bits; @@ -796,8 +795,8 @@ __rs4_decompress(uint8_t* io_data_str, int -_rs4_decompress(uint8_t* io_data_str, - uint8_t* io_care_str, +_rs4_decompress(uint8_t* o_data_str, + uint8_t* o_care_str, uint32_t i_size, uint32_t* o_length, const CompressedScanData* i_rs4) @@ -814,10 +813,10 @@ _rs4_decompress(uint8_t* io_data_str, return BUG(SCAN_COMPRESSION_VERSION_ERROR); } - memset(io_data_str, 0, i_size); - memset(io_care_str, 0, i_size); + memset(o_data_str, 0, i_size); + memset(o_care_str, 0, i_size); - return __rs4_decompress(io_data_str, io_care_str, i_size, + return __rs4_decompress(o_data_str, o_care_str, i_size, o_length, rs4_str); } @@ -828,21 +827,21 @@ rs4_decompress(uint8_t** o_data_str, uint32_t* o_length, const CompressedScanData* i_rs4) { - uint32_t size = 400000; + uint32_t size = MAX_RING_BUF_SIZE_TOOL; int rc; - *o_data_str = (uint8_t*)malloc(size); + *o_data_str = (uint8_t*)(operator new(size)); if (*o_data_str == NULL) { return BUG(SCAN_COMPRESSION_NO_MEMORY); } - *o_care_str = (uint8_t*)malloc(size); + *o_care_str = (uint8_t*)(operator new(size)); if (*o_care_str == NULL) { - free(*o_data_str); + operator delete(*o_data_str); *o_data_str = NULL; return BUG(SCAN_COMPRESSION_NO_MEMORY); } @@ -851,8 +850,8 @@ rs4_decompress(uint8_t** o_data_str, if (rc != SCAN_COMPRESSION_OK) { - free(*o_data_str); - free(*o_care_str); + operator delete(*o_data_str); + operator delete(*o_care_str); *o_data_str = NULL; *o_care_str = NULL; } @@ -905,7 +904,7 @@ rs4_redundant(const CompressedScanData* i_data, int* o_redundant) // Check for RS4 contains CMSK ring int -rs4_is_cmsk(CompressedScanData* i_rs4) +rs4_is_cmsk(const CompressedScanData* i_rs4) { return(i_rs4->iv_type == RS4_SCAN_DATA_TYPE_CMSK); } @@ -915,16 +914,17 @@ rs4_is_cmsk(CompressedScanData* i_rs4) // |------RS4 Header------| // |-----CMSK Header------| // |-----CMSK RS4 Data----| -// |-------RS4 Data-------| +// |----Stump RS4 Data----| int -rs4_embed_cmsk(CompressedScanData** io_rs4, CompressedScanData* i_rs4_cmsk) +rs4_embed_cmsk( CompressedScanData** io_rs4, + CompressedScanData* i_rs4Cmsk ) { - char* embedded_addr = (char*)(*io_rs4 + 1); - size_t embedded_size = be16toh(i_rs4_cmsk->iv_size); - size_t total_size = be16toh((*io_rs4)->iv_size) + embedded_size; + char* embeddedAddr = (char*)(*io_rs4 + 1); + size_t embeddedSize = be16toh(i_rs4Cmsk->iv_size); + size_t totalSize = be16toh((*io_rs4)->iv_size) + embeddedSize; // Enlarge RS4 container to accomodate cmsk ring - *io_rs4 = (CompressedScanData*)realloc(*io_rs4, total_size); + *io_rs4 = (CompressedScanData*)realloc(*io_rs4, totalSize); if (!*io_rs4) { @@ -932,66 +932,113 @@ rs4_embed_cmsk(CompressedScanData** io_rs4, CompressedScanData* i_rs4_cmsk) } // Make space for cmsk ring - memmove(embedded_addr + embedded_size, - embedded_addr, + memmove(embeddedAddr + embeddedSize, + embeddedAddr, be16toh((*io_rs4)->iv_size) - sizeof(CompressedScanData)); // Copy cmsk ring into rs4 - memcpy(embedded_addr, - i_rs4_cmsk, - embedded_size); + memcpy(embeddedAddr, + i_rs4Cmsk, + embeddedSize); // Update header fields - (*io_rs4)->iv_size = htobe16(total_size); + (*io_rs4)->iv_size = htobe16(totalSize); (*io_rs4)->iv_type = RS4_SCAN_DATA_TYPE_CMSK; return SCAN_COMPRESSION_OK; } -// Extract Stump & Cmsk ring containers +// Extract Stump & Cmsk ring containers (assumes pre-allocation of ring buffers) int -rs4_extract_cmsk(CompressedScanData* i_rs4, - CompressedScanData** io_rs4_stump, - CompressedScanData** io_rs4_cmsk) +_rs4_extract_cmsk( const CompressedScanData* i_rs4, + size_t i_size, + CompressedScanData* o_rs4Stump, + CompressedScanData* o_rs4Cmsk ) { - CompressedScanData* embedded_addr = (CompressedScanData*)(i_rs4 + 1); + if (be16toh(i_rs4->iv_magic) != RS4_MAGIC) + { + return BUG(SCAN_DECOMPRESSION_MAGIC_ERROR); + } - // Get size of Stump and Cmsk rings - size_t embedded_size = be16toh(embedded_addr->iv_size); - size_t stump_size = be16toh(i_rs4->iv_size) - embedded_size; + if (i_rs4->iv_version != RS4_VERSION) + { + return BUG(SCAN_COMPRESSION_VERSION_ERROR); + } - // Allocate memory for Stump and Cmsk rings - *io_rs4_stump = (CompressedScanData*)malloc(stump_size); - *io_rs4_cmsk = (CompressedScanData*)malloc(embedded_size); + memset((uint8_t*)o_rs4Stump, 0, i_size); + memset((uint8_t*)o_rs4Cmsk, 0, i_size); + + const CompressedScanData* embeddedAddr = i_rs4 + 1; + + // Get size of Stump and Cmsk rings + size_t embeddedSize = be16toh(embeddedAddr->iv_size); + size_t stumpSize = be16toh(i_rs4->iv_size) - embeddedSize; - if (!*io_rs4_stump || !*io_rs4_cmsk) + if (stumpSize > i_size || embeddedSize > i_size) { - return BUG(SCAN_COMPRESSION_NO_MEMORY); + return BUG(SCAN_COMPRESSION_BUFFER_OVERFLOW); } // Copy Cmsk ring - (header+data) - memcpy(*io_rs4_cmsk, - embedded_addr, - embedded_size); + memcpy(o_rs4Cmsk, + embeddedAddr, + embeddedSize); // Copy Stump ring - header - memcpy(*io_rs4_stump, + memcpy(o_rs4Stump, i_rs4, sizeof(CompressedScanData)); // Copy Stump ring - data - memcpy(((CompressedScanData*)(*io_rs4_stump) + 1), - (uint8_t*)embedded_addr + embedded_size, - stump_size - sizeof(CompressedScanData)); + memcpy(o_rs4Stump + 1, + (uint8_t*)embeddedAddr + embeddedSize, + stumpSize - sizeof(CompressedScanData)); // Update header fields - stump - (*io_rs4_stump)->iv_size = htobe16(stump_size); - (*io_rs4_stump)->iv_type = RS4_SCAN_DATA_TYPE_NON_CMSK; + o_rs4Stump->iv_size = htobe16(stumpSize); + o_rs4Stump->iv_type = RS4_SCAN_DATA_TYPE_NON_CMSK; return SCAN_COMPRESSION_OK; } + +// Extract Stump & Cmsk ring containers (local allocation of ring buffers) +int +rs4_extract_cmsk( const CompressedScanData* i_rs4, + CompressedScanData** o_rs4Stump, + CompressedScanData** o_rs4Cmsk ) +{ + int rc; + uint32_t size = MAX_RING_BUF_SIZE_TOOL; + + // Allocate memory for Stump and Cmsk rings + *o_rs4Stump = (CompressedScanData*)(operator new(size)); + *o_rs4Cmsk = (CompressedScanData*)(operator new(size)); + + if (!*o_rs4Stump || !*o_rs4Cmsk) + { + operator delete(*o_rs4Stump); + operator delete(*o_rs4Cmsk); + *o_rs4Stump = NULL; + *o_rs4Cmsk = NULL; + return BUG(SCAN_COMPRESSION_NO_MEMORY); + } + + rc = _rs4_extract_cmsk(i_rs4, size, *o_rs4Stump, *o_rs4Cmsk); + + if (rc != SCAN_COMPRESSION_OK) + { + operator delete(*o_rs4Stump); + operator delete(*o_rs4Cmsk); + *o_rs4Stump = NULL; + *o_rs4Cmsk = NULL; + } + + return rc; +} + + // Prints out the raw decompressed RS4 ring content void print_raw_ring( uint8_t* data, uint32_t bits ) diff --git a/src/import/chips/p9/utils/imageProcs/p9_scan_compression.H b/src/import/chips/p9/utils/imageProcs/p9_scan_compression.H index 158e5ec14..2a76c3088 100644 --- a/src/import/chips/p9/utils/imageProcs/p9_scan_compression.H +++ b/src/import/chips/p9/utils/imageProcs/p9_scan_compression.H @@ -123,8 +123,9 @@ compressed_scan_data_translate(CompressedScanData* o_data, /// ring ID header files for more info.) /// /// This API is required for integration with PHYP which does not support -/// malloc(). Applications in environments supporting malloc() can use -/// rs4_compress() instead. +/// local memory allocation, like malloc() and new(). Applications in +/// environments supporting local memory allocation can use rs4_compress() +/// instead. /// /// We always require the worst-case amount of memory including the header and /// any rounding required to guarantee that the data size is a multiple of 8 @@ -145,7 +146,7 @@ _rs4_compress(CompressedScanData* io_rs4, /// Compress a scan string using the RS4 compression algorithm /// -/// \param[out] o_rs4 This algorithm uses malloc() to allocate memory for the +/// \param[out] o_rs4 This algorithm uses new() to allocate memory for the /// compressed data, and returns a pointer to this memory in \a o_rs4. After /// the call this memory is owned by the caller who is responsible for /// free()-ing the data area once it is no longer required. Note that the @@ -189,7 +190,9 @@ rs4_compress(CompressedScanData** o_rs4, /// the decompressed care mask, which is the size of the original string in /// bits rounded up to the nearest byte. /// -/// \param[in] i_size The size in \e bytes of \a io_data_str and \a io_care_str. +/// \param[in] i_size The size in \e bytes of \a o_data_str and \a o_care_str +/// buffers and which represents the max number of raw ring bits x 8 that may +/// fit into the two raw ring buffers. /// /// \param[out] o_length The length of the decompressed string in \e bits. /// @@ -197,13 +200,14 @@ rs4_compress(CompressedScanData** o_rs4, /// decompressed. /// /// This API is required for integration with PHYP which does not support -/// malloc(). Applications in environments supporting malloc() can use -/// rs4_decompress() instead. +/// local memory allocation, such as malloc() and new(). Applications in +/// environments supporting local memory allocation can use rs4_decompress() +/// instead. /// /// \returns See \ref scan_compression_codes int -_rs4_decompress(uint8_t* io_data_str, - uint8_t* io_care_str, +_rs4_decompress(uint8_t* o_data_str, + uint8_t* o_care_str, uint32_t i_size, uint32_t* o_length, const CompressedScanData* i_rs4); @@ -211,11 +215,11 @@ _rs4_decompress(uint8_t* io_data_str, /// Decompress a scan string compressed using the RS4 compression algorithm /// -/// \param[out] o_data_str The API malloc()-s this data area to contain the +/// \param[out] o_data_str The API new() allocs this data area to contain the /// decompressed string. After this call the caller owns \a o_data_str and is /// responsible for free()-ing this data area once it is no longer required. /// -/// \param[out] o_care_str The API malloc()-s this data area to contain the +/// \param[out] o_care_str The API new() allocs this data area to contain the /// decompressed care mask. After this call the caller owns \a o_care_str and /// is responsible for free()-ing this data area once it is no longer required. /// @@ -251,7 +255,7 @@ rs4_redundant(const CompressedScanData* i_data, int* o_redundant); /// \param[in] i_rs4 A pointer to the RS4 CompressedScanData [header + data] /// /// \returns 1 if CMSK ring found, 0 otherwise -int rs4_is_cmsk(CompressedScanData* i_rs4); +int rs4_is_cmsk(const CompressedScanData* i_rs4); /// Embed CMSK ring into an RS4 ring @@ -265,18 +269,41 @@ int rs4_embed_cmsk(CompressedScanData** io_rs4, CompressedScanData* i_rs4_cmsk); -/// Extract Stump & CMSK rings from an RS4 ring +/// Extract Stump & CMSK rings from an RS4 ring (assumes pre-allocated ring buffers) /// -/// \param[in] i_rs4 A pointer to the CompressedScanData [header + data] +/// \param[in] i_rs4 A pointer to the input hybrid CMSK RS4 ring and which must contain +/// boto CompressedScanData header + RS4 encoded data string. /// -/// \param[inout] i_rs4_stump A pointer to the Stump CompressedScanData [header + data] +/// \param[in] i_size Size of buffers to hold the output Stump and CMSK RS4 rings. /// -/// \param[inout] i_rs4_cmsk A pointer to the Cmsk CompressedScanData [header + data] +/// \param[out] o_rs4_stump A pointer to a pre-allocated buffer that must be big +/// enough to hold the Stump CompressedScanData [header + data]. +/// +/// \param[out] o_rs4_cmsk A pointer to a pre-allocated buffer that must be big +/// enough to hold the Cmsk CompressedScanData [header + data]. +/// +/// \returns See \ref scan_compression_codes +int _rs4_extract_cmsk( const CompressedScanData* i_rs4, + size_t i_size, + CompressedScanData* o_rs4_stump, + CompressedScanData* o_rs4_cmsk ); + + +/// Extract Stump & CMSK rings from an RS4 ring (local allocation of ring buffers) +/// +/// \param[in] i_rs4 A pointer to the input hybrid CMSK RS4 ring and which must contain +/// boto CompressedScanData header + RS4 encoded data string. +/// +/// \param[out] o_rs4_stump A pointer to a locally allocated buffer that holds the +/// Stump CompressedScanData [header + data]. The calling code must free the buffer. +/// +/// \param[out] o_rs4_cmsk A pointer to a locally allocated buffer that holds the +/// Cmsk CompressedScanData [header + data]. The calling code must free the buffer. /// /// \returns See \ref scan_compression_codes -int rs4_extract_cmsk(CompressedScanData* i_rs4, - CompressedScanData** io_rs4_stump, - CompressedScanData** io_rs4_cmsk); +int rs4_extract_cmsk( const CompressedScanData* i_rs4, + CompressedScanData** o_rs4_stump, + CompressedScanData** o_rs4_cmsk ); #endif // __ASSEMBLER__ -- cgit v1.2.1