summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/image/Makefile124
-rw-r--r--tools/image/p9_image_help_base.H95
-rw-r--r--tools/image/p9_ring_identification.H41
-rw-r--r--tools/image/p9_ring_identification.c122
-rw-r--r--tools/image/p9_scan_compression.H345
-rw-r--r--tools/image/ppeSetFixed.pl192
-rw-r--r--tools/image/sbe_default_tool.c286
-rw-r--r--tools/image/sbe_xip_tool.c2014
8 files changed, 3219 insertions, 0 deletions
diff --git a/tools/image/Makefile b/tools/image/Makefile
new file mode 100644
index 00000000..d5991d5e
--- /dev/null
+++ b/tools/image/Makefile
@@ -0,0 +1,124 @@
+############################################################################
+
+# Makefile for image tools
+# works on X86 Linux hosts.
+
+# Make targets:
+
+# all :
+#
+# utilities : Build utility programs and procedures
+#
+# clean : Removes the bin/ directory and all symbolic links
+#
+
+############################################################################
+
+
+ifeq ($(CTEPATH),)
+$(warning CTEPATH not defined; defaulting to awd)
+CTEPATH = /afs/awd/projects/cte
+endif
+
+
+# Are we setup for eCMD, if so let's get our eCMD Release from there
+ifneq ($(strip $(ECMD_RELEASE)),)
+ ECMD_RELEASE := $(shell ecmdVersion full)
+ # Make sure we got a valid version back
+ ifeq ($(findstring ver,$(ECMD_RELEASE)),)
+ ECMD_RELEASE := rel
+ endif
+else
+ # If not setup for eCMD, default to rel
+ ECMD_RELEASE := rel
+endif
+
+
+# Ok, now set our eCMD Path, if not set already
+ifeq ($(strip $(ECMD_PATH)),)
+ ECMD_PATH := ${CTEPATH}/tools/ecmd/${ECMD_RELEASE}/
+endif
+
+ifeq ($(strip $(ECMD_PLUGIN)),cro)
+# Cronus plugin specific setup
+ CRONUS_PATH := $(shell echo ${ECMD_EXE} | sed -n 's|\([a-zA-Z0-9]*\)\(_*\)\([a-zA-Z0-9]*\)_x86\.exe|prcd_d|p')
+ ifeq ($(strip $(CRONUS_PATH)),)
+ $(error "Error determining CRONUS_PATH from env!")
+ endif
+endif
+
+# We need common up-to-date headers for FAPI - currently using these.
+FAPI = $(ECMD_PATH)ext/fapi
+
+# Locations of required headers.
+INCLUDES += -I. -I../../ -I../../utils
+INCLUDES += -I ../../sbe/image/
+INCLUDES += -I ../../sbe/sbefw/
+INCLUDES += -I ../../sbe/plat/include
+INCLUDES += -I ../../hwpf/plat/include/
+INCLUDES += -I ../../pk/ppe42/
+INCLUDES += -I ../../pk/kernel/
+INCLUDES += -I ../../pk/std/
+INCLUDES += -I ../../pk/trace/
+INCLUDES += -I ../../tools/ppetracepp/
+INCLUDES += -I /afs/apd/u/rembold/ekb/hwpf/fapi2/include
+
+INCLUDES += -I$(CRONUS_PATH)
+INCLUDES += -I$(ECMD_PATH)/capi
+INCLUDES += -I$(FAPI)/capi
+
+# Under Linux the scheme is to use a common compiler to create procedures.
+# However, the common compiler can be VERY slow, so if the system compiler is
+# also 4.1.2 we're using that one instead. Also, the Linux FAPI libraries we
+# link with are 32-bit only so we need to force 32-bit mode.
+
+ifeq ($(wildcard /etc/ldap.conf), )
+ GSACELL = ausgsa
+else
+ GSACELL = $(shell cat /etc/ldap.conf | grep "host " | \
+ cut -d" " -f2 | cut -d. -f1)
+endif
+
+GCC-RELEASE = 4.8.2
+GCC-VERSION = $(shell gcc -v 2>&1 | grep "$(GCC-RELEASE)")
+
+ifeq ($(GCC-VERSION),)
+$(error wrong compiler version. Use $(GCC-RELEASE) compiler. Try to execute scl enable devtoolset-2 bash first)
+else
+CC = gcc
+CXX = g++
+endif
+
+#UTILITIES-SOURCES += ../../sbe/image/sbe_xip_image.c
+UTILITIES-SOURCES = sbe_xip_tool.c sbe_default_tool.c
+
+UTILITIES = sbe_xip_tool sbe_default_tool
+
+# Utility targets
+UTILITIES-OBJc = $(patsubst %.c,bin/%.o,$(UTILITIES-SOURCES))
+UTILITIES-OBJECTS += $(patsubst %.C,bin/%.o,$(UTILITIES-OBJc))
+UTILITIES-DEPENDENCIES = $(patsubst %.o,%.d,$(UTILITIES-OBJECTS))
+UTILITIES-EXECUTABLES = $(patsubst %,bin/%,$(UTILITIES))
+
+
+.PHONY : utilities
+utilities: $(UTILITIES-EXECUTABLES)
+
+bin/%.o: %.c
+ $(CXX) -std=c++11 $(INCLUDES) $(CXXFLAGS) -DDEBUG_SBE_XIP_IMAGE=1 -DFAPI2_NO_FFDC -c -o $@ $<
+
+bin/sbe_xip_image.o: ../../sbe/image/sbe_xip_image.c
+ $(CXX) -std=c++11 $(INCLUDES) $(CXXFLAGS) -DDEBUG_SBE_XIP_IMAGE=1 -DFAPI2_NO_FFDC -c -o $@ $<
+
+bin/sbe_xip_tool: bin/sbe_xip_image.o bin/p9_ring_identification.o bin/sbe_xip_tool.o
+ $(CXX) $(CXXFLAGS) ${INCLUDES} -o $@ $^
+ ln -sf bin/sbe_xip_tool sbe_xip_tool
+
+bin/sbe_default_tool: bin/sbe_xip_image.o bin/sbe_default_tool.o
+ $(CXX) $(CXXFLAGS) ${INCLUDES} -o $@ $^
+ ln -sf bin/sbe_default_tool sbe_default_tool
+
+clean:
+ rm sbe_xip_tool sbe_default_tool
+ rm -rf bin
+ mkdir -p bin \ No newline at end of file
diff --git a/tools/image/p9_image_help_base.H b/tools/image/p9_image_help_base.H
new file mode 100644
index 00000000..9d13b2f4
--- /dev/null
+++ b/tools/image/p9_image_help_base.H
@@ -0,0 +1,95 @@
+#ifndef _P9_IMAGE_HELP_BASE_H_
+#define _P9_IMAGE_HELP_BASE_H_
+
+#include <sbe_xip_image.h>
+
+//
+// Various image/ring buffer sizes. Must be used by all users (VBU, FSP, HB, HBI, Cronus)
+//
+const uint32_t MAX_REF_IMAGE_SIZE = 5000000; // Max reference image size.
+const uint32_t FIXED_SEEPROM_WORK_SPACE= 128*1024; // Max work space for Seeprom img.
+const uint32_t MAX_SEEPROM_IMAGE_SIZE = 56*1024; // Max Seeprom image size.
+const uint32_t FIXED_RING_BUF_SIZE = 60000; // Fixed ring buf size for _fixed.
+
+const uint8_t MAX_VPD_TYPES = 2; // #G and #R, so far.
+#define CHIPLET_ID_MIN 0x00
+#define CHIPLET_ID_MAX 0x1F
+#define CHIPLET_ID_EX_MIN 0x10
+#define CHIPLET_ID_EX_MAX 0x1F
+const uint8_t MAX_CHIPLETS = CHIPLET_ID_MAX-CHIPLET_ID_MIN+1;
+const uint32_t ASM_RS4_LAUNCH_BUF_SIZE = 24; // Byte size of RS4 launch buffer.
+const uint32_t WF_ENCAP_SIZE = 400; // Byte size of WF encapsulation.
+ // (Actually, only 304B but may change.)
+const uint32_t WF_WORST_CASE_SIZE_FAC = 4; // WC WF size = 3x ring length.
+ // (Assumes 12B per write.)
+ // (4x w/waits instructions.)
+const uint32_t LISTING_STRING_SIZE = 256;
+const uint64_t MAX_UINT64_T = (uint64_t)0xFFFFFFFF<<32 | (uint64_t)0xFFFFFFFF;
+
+const uint8_t RING_SECTION_ID[] = {
+ SBE_XIP_SECTION_RINGS,
+ SBE_XIP_SECTION_DCRINGS,
+};
+const uint8_t RING_SECTION_ID_SIZE = sizeof(RING_SECTION_ID) / sizeof(RING_SECTION_ID[0]);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Base (shared) ring layout for both RS4 and Wiggle-flip layouts.
+typedef struct {
+ uint64_t entryOffset;
+ uint64_t backItemPtr;
+ uint32_t sizeOfThis;
+ uint32_t sizeOfMeta; // Exact size of meta data. Arbitrary size. Not null terminated.
+} BaseRingLayout;
+
+// RS4 specific layout.
+typedef struct {
+ uint64_t entryOffset;
+ uint64_t backItemPtr;
+ uint32_t sizeOfThis;
+ uint32_t sizeOfMeta; // Exact size of meta data. Arbitrary size. Not null terminated.
+ uint32_t ddLevel;
+ uint8_t sysPhase;
+ uint8_t override;
+ uint8_t reserved1;
+ uint8_t reserved2;
+} Rs4RingLayout;
+
+// PairingInfo is used for pairing, or matching, a back pointer address of a
+// ring block with its corresponding TOC name.
+typedef struct {
+ uint64_t address; // (in) Holds HOMER backPtr addr of the ring
+ uint8_t vectorpos; // (in) Vector position of fwdPtr [0;31]
+ // max=0 for most VPD rings
+ // max=1 for all non-VPD rings
+ // max=1 for perv_ VPD rings
+ // max=15 for most VPD ex_ rings
+ // max=31 for 16 ex_ chiplets with override
+ char *name; // (out) TOC name
+ uint8_t isvpd; // (out) 0: Non-VPD ring 1: VPD ring
+ uint8_t overridable; // (out) 0: No (most VPD rings) 1: Yes (all non-VPD rings)
+ uint8_t override; // (out) 0: base 1: override
+} PairingInfo;
+
+
+///
+/// ****************************************************************************
+/// Function declares.
+/// ****************************************************************************
+///
+int over_write_ring_data_in_image( void *io_image,
+ const char *i_ringName,
+ const void *i_ringData, // WF or RS4
+ const uint32_t i_sizeRingData, // Byte size
+ const uint8_t i_idxVector,
+ const uint8_t i_override,
+ const uint8_t i_overridable );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //_P8_IMAGE_HELP_BASE_H_
diff --git a/tools/image/p9_ring_identification.H b/tools/image/p9_ring_identification.H
new file mode 100644
index 00000000..e6ab8745
--- /dev/null
+++ b/tools/image/p9_ring_identification.H
@@ -0,0 +1,41 @@
+#ifndef _P9_RING_IDENT_H_
+#define _P9_RING_IDENT_H_
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+// Ring ID list structure.
+typedef struct {
+ const char *ringName;
+ uint8_t ringId;
+ uint8_t chipIdMin; // the min chipletId
+ uint8_t chipIdMax; // the max chipletId
+ const char *ringNameImg; // Ring name in image: ringName + "_ring"
+ uint8_t vpdKeyword;
+ uint8_t bWcSpace; // 0: fitted 1: worst-case space (3 x ring length)
+} RingIdList;
+
+extern const RingIdList RING_ID_LIST_PG[], RING_ID_LIST_PR[];
+extern const uint32_t RING_ID_LIST_PG_SIZE, RING_ID_LIST_PR_SIZE;
+extern const RingIdList RING_ID_LIST[];
+extern const uint32_t RING_ID_LIST_SIZE;
+
+// Enumerated VPD keyword values.
+// Note! This is DIFFERENT from the MvpdKeyword list in fapiMvpdAccess.H which
+// can't be used in this file since it's not, per se, a fapi file. So
+// these values need to be translated in xip_customize when passing the
+// mvpdKeyword to getMvpdRing();
+enum VpdKeyword {
+ VPD_KEYWORD_PDG,
+ VPD_KEYWORD_PDR,
+ NUM_OF_VPD_TYPES
+};
+
+int get_vpd_ring_list_entry(const char *i_ringName,
+ const uint8_t i_ringId,
+ RingIdList **i_ringIdList);
+
+
+#endif
diff --git a/tools/image/p9_ring_identification.c b/tools/image/p9_ring_identification.c
new file mode 100644
index 00000000..0ee5797a
--- /dev/null
+++ b/tools/image/p9_ring_identification.c
@@ -0,0 +1,122 @@
+#include <p9_ring_identification.H>
+
+const RingIdList RING_ID_LIST_PG[] = {
+ /* ringName ringId chipletId ringNameImg mvpdKeyword wc */
+ /* min max */
+ {"ab_gptr_ab", 0xA0, 0x08, 0x08, "ab_gptr_ab_ring", VPD_KEYWORD_PDG, 0},
+ {"ab_gptr_ioa", 0xA1, 0x08, 0x08, "ab_gptr_ioa_ring", VPD_KEYWORD_PDG, 0},
+ {"ab_gptr_perv", 0xA2, 0x08, 0x08, "ab_gptr_perv_ring", VPD_KEYWORD_PDG, 0},
+ {"ab_gptr_pll", 0xA3, 0x08, 0x08, "ab_gptr_pll_ring", VPD_KEYWORD_PDG, 0},
+ {"ab_time", 0xA4, 0x08, 0x08, "ab_time_ring", VPD_KEYWORD_PDG, 0},
+ {"ex_gptr_core", 0xA5, 0xFF, 0xFF, "ex_gptr_core_ring", VPD_KEYWORD_PDG, 0}, //Chip specific
+ {"ex_gptr_dpll", 0xA6, 0xFF, 0xFF, "ex_gptr_dpll_ring", VPD_KEYWORD_PDG, 0}, //Chip specific
+ {"ex_gptr_l2", 0xA7, 0xFF, 0xFF, "ex_gptr_l2_ring", VPD_KEYWORD_PDG, 0}, //Chip specific
+ {"ex_gptr_l3", 0xA8, 0xFF, 0xFF, "ex_gptr_l3_ring", VPD_KEYWORD_PDG, 0}, //Chip specific
+ {"ex_gptr_l3refr", 0xA9, 0xFF, 0xFF, "ex_gptr_l3refr_ring", VPD_KEYWORD_PDG, 0}, //Chip specific
+ {"ex_gptr_perv", 0xAA, 0xFF, 0xFF, "ex_gptr_perv_ring", VPD_KEYWORD_PDG, 0}, //Chip specific
+ {"ex_time_core", 0xAB, 0x10, 0x1F, "ex_time_core_ring", VPD_KEYWORD_PDG, 0}, //Chiplet specfc
+ {"ex_time_eco", 0xAC, 0x10, 0x1F, "ex_time_eco_ring", VPD_KEYWORD_PDG, 0}, //Chiplet specfc
+ {"pb_gptr_dmipll", 0xAD, 0x02, 0x02, "pb_gptr_dmipll_ring", VPD_KEYWORD_PDG, 0},
+ {"pb_gptr_mcr", 0xAE, 0x02, 0x02, "pb_gptr_mcr_ring", VPD_KEYWORD_PDG, 0},
+ {"pb_gptr_nest", 0xAF, 0x02, 0x02, "pb_gptr_nest_ring", VPD_KEYWORD_PDG, 0},
+ {"pb_gptr_nx", 0xB0, 0x02, 0x02, "pb_gptr_nx_ring", VPD_KEYWORD_PDG, 0},
+ {"pb_gptr_pcis", 0xB1, 0x02, 0x02, "pb_gptr_pcis_ring", VPD_KEYWORD_PDG, 0},
+ {"pb_gptr_perv", 0xB2, 0x02, 0x02, "pb_gptr_perv_ring", VPD_KEYWORD_PDG, 0},
+ {"pb_time", 0xB3, 0x02, 0x02, "pb_time_ring", VPD_KEYWORD_PDG, 0},
+ {"pb_time_mcr", 0xB4, 0x02, 0x02, "pb_time_mcr_ring", VPD_KEYWORD_PDG, 0},
+ {"pb_time_nx", 0xB5, 0x02, 0x02, "pb_time_nx_ring", VPD_KEYWORD_PDG, 0},
+ {"pci_gptr_iopci", 0xB6, 0x09, 0x09, "pci_gptr_iopci_ring", VPD_KEYWORD_PDG, 0},
+ {"pci_gptr_pbf", 0xB7, 0x09, 0x09, "pci_gptr_pbf_ring", VPD_KEYWORD_PDG, 0},
+ {"pci_gptr_pci0", 0xB8, 0x09, 0x09, "pci_gptr_pci0_ring", VPD_KEYWORD_PDG, 0},
+ {"pci_gptr_pci1", 0xB9, 0x09, 0x09, "pci_gptr_pci1_ring", VPD_KEYWORD_PDG, 0},
+ {"pci_gptr_pci2", 0xBA, 0x09, 0x09, "pci_gptr_pci2_ring", VPD_KEYWORD_PDG, 0},
+ {"pci_gptr_perv", 0xBB, 0x09, 0x09, "pci_gptr_perv_ring", VPD_KEYWORD_PDG, 0},
+ {"pci_gptr_pll", 0xBC, 0x09, 0x09, "pci_gptr_pll_ring", VPD_KEYWORD_PDG, 0},
+ {"pci_time", 0xBD, 0x09, 0x09, "pci_time_ring", VPD_KEYWORD_PDG, 0},
+ {"perv_gptr_net", 0xBE, 0x00, 0x00, "perv_gptr_net_ring", VPD_KEYWORD_PDG, 0},
+ {"perv_gptr_occ", 0xBF, 0x00, 0x00, "perv_gptr_occ_ring", VPD_KEYWORD_PDG, 0},
+ {"perv_gptr_perv", 0xC0, 0x00, 0x00, "perv_gptr_perv_ring", VPD_KEYWORD_PDG, 0},
+ {"perv_gptr_pib", 0xC1, 0x00, 0x00, "perv_gptr_pib_ring", VPD_KEYWORD_PDG, 0},
+ {"perv_gptr_pll", 0xC2, 0x00, 0x00, "perv_gptr_pll_ring", VPD_KEYWORD_PDG, 0},
+ {"perv_time", 0xC3, 0x00, 0x00, "perv_time_ring", VPD_KEYWORD_PDG, 0},
+ {"xb_gptr_iopci", 0xC4, 0x04, 0x04, "xb_gptr_iopci_ring", VPD_KEYWORD_PDG, 0},
+ {"xb_gptr_iox", 0xC5, 0x04, 0x04, "xb_gptr_iox_ring", VPD_KEYWORD_PDG, 0},
+ {"xb_gptr_pben", 0xC6, 0x04, 0x04, "xb_gptr_pben_ring", VPD_KEYWORD_PDG, 0},
+ {"xb_gptr_perv", 0xC7, 0x04, 0x04, "xb_gptr_perv_ring", VPD_KEYWORD_PDG, 0},
+ {"xb_time", 0xC8, 0x04, 0x04, "xb_time_ring", VPD_KEYWORD_PDG, 0},
+ {"pb_gptr_mcl", 0xC9, 0x02, 0x02, "pb_gptr_mcl_ring", VPD_KEYWORD_PDG, 0},
+ {"pb_time_mcl", 0xCA, 0x02, 0x02, "pb_time_mcl_ring", VPD_KEYWORD_PDG, 0},
+};
+
+const RingIdList RING_ID_LIST_PR[] = {
+ /* ringName ringId chipIdMin chipIdMax ringNameImg mvpdKeyword */
+ {"ab_repr", 0xE0, 0x08, 0x08, "ab_repr_ring", VPD_KEYWORD_PDR, 0},
+ {"ex_repr_core", 0xE1, 0x10, 0x1F, "ex_repr_core_ring", VPD_KEYWORD_PDR, 1},
+ {"ex_repr_eco", 0xE2, 0x10, 0x1F, "ex_repr_eco_ring", VPD_KEYWORD_PDR, 1},
+ {"pb_repr", 0xE3, 0x02, 0x02, "pb_repr_ring", VPD_KEYWORD_PDR, 0},
+ {"pb_repr_mcr", 0xE4, 0x02, 0x02, "pb_repr_mcr_ring", VPD_KEYWORD_PDR, 0},
+ {"pb_repr_nx", 0xE5, 0x02, 0x02, "pb_repr_nx_ring", VPD_KEYWORD_PDR, 0},
+ {"pci_repr", 0xE6, 0x09, 0x09, "pci_repr_ring", VPD_KEYWORD_PDR, 0},
+ {"perv_repr", 0xE7, 0x00, 0x00, "perv_repr_ring", VPD_KEYWORD_PDR, 0},
+ {"perv_repr_net", 0xE8, 0x00, 0x00, "perv_repr_net_ring", VPD_KEYWORD_PDR, 0},
+ {"perv_repr_pib", 0xE9, 0x00, 0x00, "perv_repr_pib_ring", VPD_KEYWORD_PDR, 0},
+ {"xb_repr", 0xEA, 0x04, 0x04, "xb_repr_ring", VPD_KEYWORD_PDR, 0},
+ {"pb_repr_mcl", 0xEB, 0x02, 0x02, "pb_repr_mcl_ring", VPD_KEYWORD_PDR, 0},
+};
+
+const uint32_t RING_ID_LIST_PG_SIZE = sizeof(RING_ID_LIST_PG)/sizeof(RING_ID_LIST_PG[0]);
+const uint32_t RING_ID_LIST_PR_SIZE = sizeof(RING_ID_LIST_PR)/sizeof(RING_ID_LIST_PR[0]);
+
+// get_vpd_ring_list_entry() retrieves the MVPD list entry based on either a ringName
+// or a ringId. If both are supplied, only the ringName is used. If ringName==NULL,
+// then the ringId is used. A pointer to the RingIdList is returned.
+int get_vpd_ring_list_entry(const char *i_ringName,
+ const uint8_t i_ringId,
+ RingIdList **i_ringIdList)
+{
+ int rc=0, NOT_FOUND=1, FOUND=0;
+ uint8_t iVpdType;
+ uint8_t iRing;
+ RingIdList *ring_id_list=NULL;
+ uint8_t ring_id_list_size;
+
+ rc = NOT_FOUND;
+ for (iVpdType=0; iVpdType<NUM_OF_VPD_TYPES; iVpdType++) {
+ if (iVpdType==0) {
+ ring_id_list = (RingIdList*)RING_ID_LIST_PG;
+ ring_id_list_size = (uint32_t)RING_ID_LIST_PG_SIZE;
+ }
+ else {
+ ring_id_list = (RingIdList*)RING_ID_LIST_PR;
+ ring_id_list_size = (uint32_t)RING_ID_LIST_PR_SIZE;
+ }
+ // Search the MVPD reference lists for either a:
+ // - ringName match with or w/o _image in the name, or
+ // - ringId match.
+ if (i_ringName) {
+ // Search for ringName match.
+ for (iRing=0; iRing<ring_id_list_size; iRing++) {
+ if ( strcmp((ring_id_list+iRing)->ringName, i_ringName)==0 ||
+ strcmp((ring_id_list+iRing)->ringNameImg,i_ringName)==0 ) {
+ *i_ringIdList = ring_id_list+iRing;
+ return FOUND;
+ }
+ }
+ }
+ else {
+ // Search for ringId match (since ringName was not supplied).
+ for (iRing=0; iRing<ring_id_list_size; iRing++) {
+ if ((ring_id_list+iRing)->ringId==i_ringId) {
+ *i_ringIdList = ring_id_list+iRing;
+ return FOUND;
+ }
+ }
+ }
+
+ }
+ return rc;
+}
+
+
+
+
diff --git a/tools/image/p9_scan_compression.H b/tools/image/p9_scan_compression.H
new file mode 100644
index 00000000..2f1e285d
--- /dev/null
+++ b/tools/image/p9_scan_compression.H
@@ -0,0 +1,345 @@
+#ifndef __P9_SCAN_COMPRESSION_H__
+#define __P9_SCAN_COMPRESSION_H__
+
+/// This header declares and documents the entry points defined in
+/// p9_scan_compression.C. Some constants are also required by the scan
+/// decompression HOMER assembly procedures.
+
+#include "fapi_sbe_common.H"
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+
+/// Compressed Scan Chain Data Structure Format
+///
+/// The compressed scan ring data structure must be 8-byte aligned in
+/// memory. The container data structure consists of this 24-byte header
+/// followed by an arbitrary number of 8 byte doublewords containing the
+/// compressed scan data. Images are always stored and processed in
+/// big-endian byte order. This container format is common across all
+/// decompression algorithms.
+///
+/// Bytes - Content
+///
+/// 0:3 - A 32-bit "magic number" that identifies and validates the
+/// compression algorithm and algorithm version used to compress the data.
+///
+/// 4:7 - The 32-bit size of the entire data structure in \e bytes. This
+/// consists of this 24-byte header plus the compressed scan data. This value
+/// is always a multiple of 8.
+///
+/// 8:11 - This 32-bit value is reserved to the compression
+/// algorithm. Typically this field is used to record the 'size' of the
+/// compressed string in units specific to each algorithm.
+///
+/// 12:15 - The length of the original scan chain in \e bits.
+///
+/// 16:19 - The 32 high-order bits of the value written to the Scan Select
+/// register to set up the scan. The Scan Select register only defines these
+/// bits.
+///
+/// 20 - The Scan Chain Data Structure version number
+///
+/// 21 - Flush-optimize : Is this byte is non-zero, the ring state to be
+/// modified is the flush state of the ring.
+///
+/// 22 - The ring ID uniquely identifying the repair ring name.
+///
+/// 23 - The 7-bit pervasive chiplet Id + Multicast bit of the chiplet to
+/// scan. This value is loaded directly into P0. The decompression
+/// algorithms provide two entry points - one that uses this value as the
+/// chiplet Id, and another that allows the caller to specify the chiplet Id
+/// in the call.
+
+typedef struct {
+
+ /// Magic number - See \ref scan_compression_magic
+ uint32_t iv_magic;
+
+ /// Total size in bytes, including the container header
+ uint32_t iv_size;
+
+ /// Reserved to the algorithm
+ uint32_t iv_algorithmReserved;
+
+ /// Length of the original scan chain in bits
+ uint32_t iv_length;
+
+ /// The high-order 32 bits of the Scan Select Register
+ ///
+ /// Note that the Scan Select register only defines the high order 32
+ /// bits, so we only need store the 32 high-order bits. This field is
+ /// 8-byte aligned so that the doubleword loaded by the HOMER can be
+ /// directly written to the scan select register.
+ uint32_t iv_scanSelect;
+
+ /// Data structure (header) version
+ uint8_t iv_headerVersion;
+
+ /// Flush-state optimization
+ ///
+ /// Normally, modifying the state of the ring requires XOR-ing the
+ /// difference state (the compressed state) with the current ring state as
+ /// it will appear in the Scan Data Register. If the current state of the
+ /// ring is the scan-0 flush state, then by definition the Scan Data
+ /// Register is always 0. Therefore we can simply write the difference to
+ /// the Scan Data Register rather than using a read-XOR-write.
+ uint8_t iv_flushOptimization;
+
+ /// Ring ID uniquely identifying the repair name. (See the list of ring
+ /// name vs ring IDs in p8_ring_identification.c).
+ uint8_t iv_ringId;
+
+ /// 7-bit pervasive chiplet Id + Multicast bit
+ ///
+ /// This field is right-justified in an 8-byte aligned doubleword so that
+ /// the P0 register can be directly updated from the doubelword value in a
+ /// data register.
+ uint8_t iv_chipletId;
+
+} CompressedScanData;
+
+
+/// Endian-translate a CompressedScanData structure
+///
+/// \param o_data A pointer to a CompressedScanData structure to receive the
+/// endian-translated form of \a i_data.
+///
+/// \param i_data A pointer to the original CompressedScanData structure.
+///
+/// This API performs an endian-converting copy of a CompressedScanData
+/// structure. This copy is guaranteed to be done in such a way that \a i_data
+/// and \a o_data may be the same pointer for in-place conversion. Due to the
+/// symmetry of reverse, translating a structure twice is always guaranteed to
+/// return the origial structure to its original byte order.
+void
+compressed_scan_data_translate(CompressedScanData* o_data,
+ CompressedScanData* i_data);
+
+
+/// Compress a scan string using the RS4 compression algorithm
+///
+/// \param[in,out] io_data This is a pointer to a memory area which must be
+/// large enough to hold the worst-case result of compressing \a i_string (see
+/// below). Note that the CompressedScanData is always created in big-endian
+/// format, however the caller can use compresed_scan_data_translate() to
+/// create a copy of the header in host format.
+///
+/// \param[in] i_dataSize The size of \a io_data in bytes.
+///
+/// \param[out] o_imageSize The effective size of the entire compressed scan
+/// data structure (header + compressed data) created in \a io_data, in bytes.
+/// This value will always be a multiple of 8.
+///
+/// \param[in] i_string The string to compress. Scan data to compress is
+/// left-justified in this input string.
+///
+/// \param[in] i_length The length of the input string in \e bits. It is
+/// assumed the \a i_string contains at least (\a i_length + 7) / 8 bytes.
+///
+/// \param[in] i_scanSelect The 64-bit value written to the Scan Select
+/// register to set up for the scan. Only the 32 high-order bits are actually
+/// stored.
+///
+/// \param[in] i_ringId The ring ID that uniquely identifies the ring name of
+/// a repair ring. (See p8_ring_identification.c for more info.)
+///
+/// \param[in] i_chipletId The 7-bit value for the iv_chipletId field of the
+/// CompressedScanData.
+///
+/// \param[in] i_flushOptimization This input parameter should be set to a
+/// non-0 value if it is known that this ring difference will be applied to a
+/// scan-0 flush state. This will improve the performance of the
+/// decompress-scan routine. If the initial state of the ring is unknown, set
+/// this parameter to 0.
+///
+/// This API is required for integration with PHYP which does not support
+/// malloc(). Applications in environments supporting malloc() can use
+/// rs4_compress() instead.
+///
+/// The worst-case compression for RS4 requires 2 nibbles of control overhead
+/// per 15 nibbles of data (17/15), plus a maximum of 2 nibbles of termination.
+/// We always require this worst-case amount of memory including the header and
+/// any rounding required to guarantee that the data size is a multiple of 8
+/// bytes. The final image size is also rounded up to a multiple of 8 bytes.
+/// If the \a i_dataSize is less than this amount (based on \a i_length) the
+/// call will fail.
+///
+/// \returns See \ref scan_compression_codes
+int
+_rs4_compress(CompressedScanData* io_data,
+ uint32_t i_dataSize,
+ uint32_t* o_imageSize,
+ const uint8_t* i_string,
+ const uint32_t i_length,
+ const uint64_t i_scanSelect,
+ const uint8_t i_ringId,
+ const uint8_t i_chipletId,
+ const uint8_t i_flushOptimization);
+
+
+/// Compress a scan string using the RS4 compression algorithm
+///
+/// \param[out] o_data This algorithm uses malloc() to allocate memory for the
+/// compresed data, and returns a pointer to this memory in \a o_data. 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
+/// CompressedScanData is always created in big-endian format, however the
+/// caller can use compresed_scan_data_translate() to create a copy of the
+/// header in host format.
+///
+/// \param[out] o_size The effective size of the entire compressed scan data
+/// structure (header + compressed data) pointed to by \a o_data, in bytes.
+/// This value will always be a multiple of 8.
+///
+/// \param[in] i_string The string to compress. Scan data to compress is
+/// left-justified in this input string.
+///
+/// \param[in] i_length The length of the input string in \e bits. It is
+/// assumed the \a i_string contains at least (\a i_length + 7) / 8 bytes.
+///
+/// \param[in] i_scanSelect The 64-bit value written to the Scan Select
+/// register to set up for the scan. Only the 32 high-order bits are actually
+/// stored.
+///
+/// \param[in] i_ringId The ring ID that uniquely identifies the ring name of
+/// a repair ring. (See p8_ring_identification.c for more info.)
+///
+/// \param[in] i_chipletId The 7-bit value for the iv_chipletId field of the
+/// CompressedScanData.
+///
+/// \param[in] i_flushOptimization This input parameter should be set to a
+/// non-0 value if it is known that this ring difference will be applied to a
+/// scan-0 flush state. This will improve the performance of the
+/// decompress-scan routine. If the initial state of the ring is unknown, set
+/// this parameter to 0.
+///
+/// \returns See \ref scan_compression_codes
+int
+rs4_compress(CompressedScanData** o_data,
+ uint32_t* o_size,
+ const uint8_t* i_string,
+ const uint32_t i_length,
+ const uint64_t i_scanSelect,
+ const uint8_t i_ringId,
+ const uint8_t i_chipletId,
+ const uint8_t i_flushOptimization);
+
+
+/// Decompress a scan string compressed using the RS4 compression algorithm
+///
+/// \param[in,out] io_string A caller-supplied data area to contain the
+/// decompressed string. The \a i_stringSize must be large enough to contain
+/// the decompressed string, which is the size of the original string in bits
+/// rounded up to the nearest byte.
+///
+/// \param[in] i_stringSize The size (in bytes) of \a i_string.
+///
+/// \param[out] o_length The length of the decompressed string in \e bits.
+///
+/// \param[in] i_data A pointer to the CompressedScanData header + data to be
+/// decompressed.
+///
+/// This API is required for integration with PHYP which does not support
+/// malloc(). Applications in environments supporting malloc() can use
+/// rs4_decompress() instead.
+///
+/// \returns See \ref scan_compression_codes
+int
+_rs4_decompress(uint8_t* i_string,
+ uint32_t i_stringSize,
+ uint32_t* o_length,
+ const CompressedScanData* i_data);
+
+
+/// Decompress a scan string compressed using the RS4 compression algorithm
+///
+/// \param[out] o_string The API malloc()-s this data area to contain the
+/// decompressed string. After this call the caller owns \a o_string and is
+/// responsible for free()-ing this data area once it is no longer required.
+///
+/// \param[out] o_length The length of the decompressed string in \e bits.
+/// The caller may assume that \a o_string contains at least (\a o_length + 7)
+/// / 8 \e bytes.
+///
+/// \param[in] i_data A pointer to the CompressedScanData header + data to be
+/// decompressed.
+///
+/// \returns See \ref scan_compression_codes
+int
+rs4_decompress(uint8_t** o_string,
+ uint32_t* o_length,
+ const CompressedScanData* i_data);
+
+
+/// Determine if an RS4 compressed scan string is all 0
+///
+/// \param[in] i_data A pointer to the CompressedScanData header + data to be
+///
+/// \param[out] o_redundant Set to 1 if the RS4 string is the compressed form
+/// of a scan string that is all 0; Otherwise set to 0.
+///
+/// \returns See \ref scan _compression_code
+int
+rs4_redundant(const CompressedScanData* i_data, int* o_redundant);
+
+
+#endif // __ASSEMBLER__
+
+
+/// The current version of the CompressedScanData structure
+///
+/// This constant is required to be a #define to guarantee consistency between
+/// the header format and cmopiled code.
+#define COMPRESSED_SCAN_DATA_VERSION 1
+
+/// The size of the CompressedScanData structure
+CONST_UINT8_T(COMPRESSED_SCAN_DATA_SIZE, 24);
+
+
+/// \defgroup scan_compression_magic Scan Compression Magic Numbers
+///
+/// @ {
+
+/// RS4 Magic
+CONST_UINT32_T(RS4_MAGIC, 0x52533401); /* "RS4" + Version 0x01 */
+
+/// @}
+
+
+/// \defgroup scan_compression_codes Scan Compression Return Codes
+///
+/// @{
+
+/// Normal return code
+CONST_UINT8_T(SCAN_COMPRESSION_OK, 0);
+
+/// The (de)compression algorithm could not allocate enough memory for the
+/// (de)compression.
+CONST_UINT8_T(SCAN_COMPRESSION_NO_MEMORY, 1);
+
+/// Magic number mismatch on scan decompression
+CONST_UINT8_T(SCAN_DECOMPRESSION_MAGIC_ERROR, 2);
+
+/// Decompression size error
+///
+/// Decompression produced a string of a size different than indicated in the
+/// header, indicating either a bug or data corruption. Note that the entire
+/// application should be considered corrupted if this error occurs since it
+/// may not be discovered until after the decompression buffer is
+/// overrun. This error may also be returned by rs4_redundant() in the event
+/// of inconsistencies in the compressed string.
+CONST_UINT8_T(SCAN_DECOMPRESSION_SIZE_ERROR, 3);
+
+/// A buffer would overflow
+///
+/// Either the caller-supplied memory buffer to _rs4_decompress() was too
+/// small to contain the decompressed string, or a caller-supplied buffer to
+/// _rs4_compress() was not large enough to hold the worst-case compressed
+/// string.
+CONST_UINT8_T(SCAN_COMPRESSION_BUFFER_OVERFLOW, 4);
+
+/// @}
+
+#endif // __P8_SCAN_COMPRESSION_H__
diff --git a/tools/image/ppeSetFixed.pl b/tools/image/ppeSetFixed.pl
new file mode 100644
index 00000000..cd65761a
--- /dev/null
+++ b/tools/image/ppeSetFixed.pl
@@ -0,0 +1,192 @@
+#!/usr/bin/perl
+# Purpose: This perl script will parse the attribute and default list and
+# and set the default values into the image.
+
+use strict;
+
+#------------------------------------------------------------------------------
+# Print Command Line Help
+#------------------------------------------------------------------------------
+my $numArgs = $#ARGV + 1;
+if ($numArgs < 3)
+{
+ print ("Usage: ppeSetFixed.pl <image> <attributes and default list> <attribute file> ...\n");
+ print (" This perl script will the attributes and default list to lookup the defaults\n");
+ print (" and parse the attribute file to lookup the types.\n");
+ print (" The default values will be set in the image.\n");
+ print ("example:\n");
+ print ("./ppeSetFixed.pl ./sbe_main.bin ../scripts/ppe_attributes.xml \\\n" );
+ print ("../scripts/perv_attributes.xml ../scripts/proc_attributes.xml \\\n" );
+ print ("../scripts/ex_attributes.xml ../scripts/eq_attributes.xml ../scripts/core_attributes.xml \n");
+ exit(1);
+}
+
+#------------------------------------------------------------------------------
+# Specify perl modules to use
+#------------------------------------------------------------------------------
+use XML::Simple;
+my $xml = new XML::Simple (KeyAttr=>[]);
+
+
+my $xmlFiles = 0;
+my $attCount = 0;
+my $numIfAttrFiles = 0;
+my @attrChipIds;
+my @attrExIds;
+my @attrCoreIds;
+my @attrEqIds;
+my @attrPervIds;
+
+
+
+#------------------------------------------------------------------------------
+# Element names
+#------------------------------------------------------------------------------
+my $attribute = 'attribute';
+
+#------------------------------------------------------------------------------
+# For each argument
+#------------------------------------------------------------------------------
+my $image = $ARGV[0];
+my $argfile = $ARGV[1];
+my $entries = $xml->XMLin($argfile, ForceArray => ['entry']);
+
+if ( ! -e $image) {die "ppeSetFixed.pl: $image $!"};
+
+foreach my $entr (@{$entries->{entry}}) {
+
+ my $inname = $entr->{name};
+
+ # read XML file. The ForceArray option ensures that there is an array of
+ # elements even if there is only one such element in the file
+
+ foreach my $argnum (2 .. $#ARGV)
+ {
+ my $infile = $ARGV[$argnum];
+
+ if ( ! -e $infile) {die "ppeSetFixed.pl: $infile $!"};
+
+ my $attributes = $xml->XMLin($infile, ForceArray => ['attribute']);
+
+ #--------------------------------------------------------------------------
+ # For each Attribute
+ #--------------------------------------------------------------------------
+ foreach my $attr (@{$attributes->{attribute}})
+ {
+
+ if($attr->{id} eq $inname) {
+
+ #------------------------------------------------------------------
+ # Check that the AttributeId exists
+ #------------------------------------------------------------------
+ if (! exists $attr->{id})
+ {
+ print ("ppeSbeFixed.pl ERROR. Att 'id' missing\n");
+ exit(1);
+ }
+
+
+ if($attr->{targetType} eq "TARGET_TYPE_PROC_CHIP") {
+
+ push(@attrChipIds, $entr);
+
+ } elsif($attr->{targetType} eq "TARGET_TYPE_CORE") {
+
+ push(@attrCoreIds, $entr);
+
+ } elsif($attr->{targetType} eq "TARGET_TYPE_EQ") {
+
+ push(@attrEqIds, $entr);
+
+ } elsif($attr->{targetType} eq "TARGET_TYPE_EX") {
+
+ push(@attrExIds, $entr);
+
+ } elsif($attr->{targetType} eq "TARGET_TYPE_PERV") {
+
+ push(@attrPervIds, $entr);
+
+ } else {
+
+ print ("ppeSetFixed.pl ERROR. Wrong attribute type: $attr->{targetType}\n");
+ exit(1);
+
+ }
+
+ }
+ }
+ }
+
+}
+
+
+
+setFixed("TARGET_TYPE_PROC_CHIP", @attrChipIds);
+setFixed("TARGET_TYPE_CORE", @attrCoreIds);
+setFixed("TARGET_TYPE_EQ", @attrEqIds);
+setFixed("TARGET_TYPE_EX", @attrExIds);
+setFixed("TARGET_TYPE_PERV", @attrPervIds);
+
+
+
+sub setFixed {
+
+ my ($string, @entries) = @_;
+
+ foreach my $attr (@entries)
+ {
+
+ my $inname = $attr->{name};
+
+ my @values = $attr->{value};
+
+
+ if(scalar @values > 0) {
+
+ foreach my $val (@values)
+ {
+
+ if(defined $val && ref($val) eq "") {
+
+ if ($val =~ /(0x)?[0-9a-fA-F]+/) {
+
+ my $systemRc = system("./sbe_default_tool $image $inname $val $string 0");
+
+ if ($systemRc) {
+ print "sbe_default_tool: error in execution\n";
+ exit 1;
+ }
+
+ } else {
+ print ("ppeSetFixed.pl ERROR. not hex\n");
+ exit(1);
+ }
+
+ } elsif(defined $val && ref($val) eq "ARRAY") {
+
+ my $index = 0;
+
+ foreach my $arr (@{$val}) {
+
+ if(defined $arr && ref($arr) eq "") {
+ if ($arr =~ /(0x)?[0-9a-fA-F]+/) {
+
+ my $systemRc = system("./sbe_default_tool $image $inname $arr $string $index");
+
+ if ($systemRc) {
+ print "sbe_default_tool: error in execution\n";
+ exit 1;
+ }
+
+
+ }
+ }
+ $index++;
+ }
+ }
+ }
+ }
+ }
+}
+
+
diff --git a/tools/image/sbe_default_tool.c b/tools/image/sbe_default_tool.c
new file mode 100644
index 00000000..2b1679ef
--- /dev/null
+++ b/tools/image/sbe_default_tool.c
@@ -0,0 +1,286 @@
+/// \file sbe_default_tool.c
+/// \brief SBE-XIP image setter tool for attributes in fixed section
+///
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <regex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <endian.h>
+
+
+#define __PPE__
+#include "fapi2.H"
+#include "proc_sbe_fixed.H"
+
+const char* g_usage =
+"Usage: sbe_default_tool <image> <attribute> <value> <target type> <index>\n"
+"The 'image' is the binary image with fixed section.\n"
+"\n"
+"The 'attribute' is the attribute to be set.\n"
+"\n"
+"The 'value' is the value of the attribute to be set.\n"
+"\n"
+"The 'target type' is the type of the target. The following targets are defined:\n"
+"TARGET_TYPE_PROC_CHIP: chip target\n"
+"TARGET_TYPE_PERV: pervasive target\n"
+"TARGET_TYPE_CORE: core target\n"
+"TARGET_TYPE_EQ: eq target\n"
+"TARGET_TYPE_EX: ex target\n"
+"\n"
+"The 'index' is the index of the value. Checking is performed.\n"
+"example:\n"
+"./sbe_default_tool ./sbe_main.bin ATTR_PLL_RING 0x33CAFE34 TARGET_TYPE_PERV 0\n"
+"./sbe_default_tool ./sbe_main.bin ATTR_SCRATCH_UINT8_1 12 TARGET_TYPE_PROC_CHIP 0\n"
+ ;
+
+
+void assertTarget(const char* str, unsigned int index)
+{
+
+ if(strcmp(str, "TARGET_TYPE_PROC_CHIP") == 0) {
+ if (index > 0) {
+ fprintf(stderr, "sbe_default_tool: index is larger than 0\n");
+ exit(1);
+ }
+ return;
+ } else if(strcmp(str, "TARGET_TYPE_EX") == 0) {
+ if (index >= EX_TARGET_COUNT) {
+ fprintf(stderr, "sbe_default_tool: index is larger than EX_TARGET_COUNT\n");
+ exit(1);
+ }
+ return;
+ } else if(strcmp(str, "TARGET_TYPE_EQ") == 0) {
+ if (index >= EQ_TARGET_COUNT) {
+ fprintf(stderr, "sbe_default_tool: index is larger than EQ_TARGET_COUNT\n");
+ exit(1);
+ }
+ return;
+ } else if(strcmp(str, "TARGET_TYPE_CORE") == 0) {
+ if (index >= CORE_TARGET_COUNT) {
+ fprintf(stderr, "sbe_default_tool: index is larger than EQ_TARGET_COUNT\n");
+ exit(1);
+ }
+ return;
+ } else if(strcmp(str, "TARGET_TYPE_PERV") == 0) {
+ if (index >= PERV_TARGET_COUNT) {
+ fprintf(stderr, "sbe_default_tool: index is larger than PERV_TARGET_COUNT\n");
+ exit(1);
+ }
+ return;
+ } else {
+
+ if (index >= PERV_TARGET_COUNT) {
+ fprintf(stderr, "sbe_default_tool: target not supported:");
+ fprintf(stderr, " %s\n", str);
+ exit(1);
+ }
+ }
+}
+
+void setAttribute(void* image, const char* attribute, unsigned int index, uint64_t val) {
+
+
+ SbeXipItem item;
+ void *thePointer;
+ int rc;
+
+ rc = sbe_xip_find(image, attribute, &item);
+ if (rc) {
+ fprintf(stderr, "sbe_default_tool: attribute not existing:");
+ fprintf(stderr, " %s", attribute);
+ exit(1);
+ }
+
+ // debug purpose
+ //printf("offset in string section: 0x%x \n", be32toh(item.iv_toc->iv_id));
+ //printf("address: 0x%x \n", item.iv_address);
+
+ sbe_xip_image2host(image, item.iv_address, &thePointer);
+
+ // debug purpose
+ //printf("pointer1: 0x%x \n", thePointer);
+ //printf("val: 0x%llx \n", val);
+
+ if(item.iv_toc->iv_type == SBE_XIP_UINT8) {
+
+ *((uint8_t*)thePointer + index) = (uint8_t)val;
+
+ } else if(item.iv_toc->iv_type == SBE_XIP_INT8) {
+
+ *((int8_t*)thePointer + index) = (int8_t)val;
+
+ } else if(item.iv_toc->iv_type == SBE_XIP_UINT16) {
+
+ *((uint16_t*)thePointer + index) = (uint16_t)val;
+
+ } else if(item.iv_toc->iv_type == SBE_XIP_INT16) {
+
+ *((int16_t*)thePointer + index) = (int16_t)val;
+
+ } else if(item.iv_toc->iv_type == SBE_XIP_UINT32) {
+
+ *((uint32_t*)thePointer + index) = (uint32_t)val;
+
+ } else if(item.iv_toc->iv_type == SBE_XIP_INT32) {
+
+ *((int32_t*)thePointer + index) = (int32_t)val;
+
+ } else if(item.iv_toc->iv_type == SBE_XIP_UINT64) {
+
+ *((uint64_t*)thePointer + index) = (uint64_t)val;
+
+ } else if(item.iv_toc->iv_type == SBE_XIP_INT64) {
+
+ *((int64_t*)thePointer + index) = (int64_t)val;
+
+ } else {
+ fprintf(stderr, "sbe_default_tool: type not available");
+ exit(1);
+ }
+
+
+
+
+ SBE_XIP_SECTION_NAMES(section_name);
+ SBE_XIP_TYPE_STRINGS(type_name);
+
+ // debug purpose
+ //printf("pointer2: 0x%x \n", thePointer);
+ //printf("section id: %s \n", section_name[item.iv_toc->iv_section]);
+ //printf("location in section: 0x%x \n", be32toh(item.iv_toc->iv_data));
+ //printf("type name: %s \n", type_name[item.iv_toc->iv_type]);
+
+ return;
+}
+
+
+uint64_t getAttribute(void* image, const char* attribute, unsigned int index) {
+
+ uint64_t val = 0;
+
+ SbeXipItem item;
+ void *thePointer;
+ int rc;
+
+ rc = sbe_xip_find(image, attribute, &item);
+ if (rc) {
+ fprintf(stderr, "sbe_default_tool: attribute not existing:");
+ fprintf(stderr, " %s", attribute);
+ exit(1);
+ }
+
+ sbe_xip_image2host(image, item.iv_address, &thePointer);
+
+ if(item.iv_toc->iv_type == SBE_XIP_UINT8) {
+
+ val = *((uint8_t*)thePointer + index);
+
+ } else if(item.iv_toc->iv_type == SBE_XIP_INT8) {
+
+ val = *((int8_t*)thePointer + index);
+ val &= 0xFF;
+
+ } else if(item.iv_toc->iv_type == SBE_XIP_UINT16) {
+
+ val = *((uint16_t*)thePointer + index);
+
+ } else if(item.iv_toc->iv_type == SBE_XIP_INT16) {
+
+ val = *((int16_t*)thePointer + index);
+ val &= 0xFFFF;
+
+ } else if(item.iv_toc->iv_type == SBE_XIP_UINT32) {
+
+ val = *((uint32_t*)thePointer + index);
+
+ } else if(item.iv_toc->iv_type == SBE_XIP_INT32) {
+
+ val = *((int32_t*)thePointer + index);
+ val &= 0xFFFFFFFF;
+
+ } else if(item.iv_toc->iv_type == SBE_XIP_UINT64) {
+
+ val = *((uint64_t*)thePointer + index);
+
+ } else if(item.iv_toc->iv_type == SBE_XIP_INT64) {
+
+ val = *((int64_t*)thePointer + index);
+
+ } else {
+ fprintf(stderr, "sbe_default_tool: type not available");
+ exit(1);
+ }
+
+
+
+ return val;
+}
+
+int main(int argc, const char** argv)
+{
+
+ int fileFd, rc;
+ void* image;
+ struct stat buf;
+
+ if(argc != 6) {
+ fprintf(stderr, "sbe_default_tool: argument missing\n");
+ fprintf(stderr, g_usage);
+ exit(1);
+ }
+
+ printf("sbe_default_tool %s %s %s %s %s\n", argv[1], argv[2], argv[3], argv[4], argv[5]);
+
+ fileFd = open(argv[1], O_RDWR);
+ if (fileFd < 0) {
+ fprintf(stderr, "sbe_default_tool: open() of the file to be appended failed");
+ exit(1);
+ }
+
+ rc = fstat(fileFd, &buf);
+ if (rc) {
+ fprintf(stderr, "sbe_default_tool: fstat() of the file to be appended failed");
+ exit(1);
+ }
+
+ image = mmap(0, buf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fileFd, 0);
+ if (image == MAP_FAILED) {
+ fprintf(stderr, "sbe_default_tool: mmap() of the file to be appended failed");
+ exit(1);
+ }
+
+
+ uint64_t val=strtoull(argv[3], 0, 0);
+
+ unsigned int index = strtoul(argv[5], 0, 10);
+
+ assertTarget(argv[4], index);
+
+ setAttribute(image, argv[2], index, val);
+
+ uint64_t check = getAttribute(image, argv[2], index);
+
+ if((check & val) != check) {
+
+ fprintf(stderr, "sbe_default_tool: set and get values not equal");
+ fprintf(stderr, "%lx != %lx\n", check, val);
+ exit(1);
+
+ }
+
+ rc = close(fileFd);
+ if (rc) {
+ fprintf(stderr, "sbe_default_tool: close() of modified image failed");
+ exit(1);
+ }
+
+
+ return 0;
+}
diff --git a/tools/image/sbe_xip_tool.c b/tools/image/sbe_xip_tool.c
new file mode 100644
index 00000000..ae136858
--- /dev/null
+++ b/tools/image/sbe_xip_tool.c
@@ -0,0 +1,2014 @@
+// $Id: sbe_xip_tool.c,v 1.13 2014/06/27 20:50:16 maploetz Exp $
+
+/// \file sbe_xip_tool.c
+/// \brief SBE-XIP image search/edit tool
+///
+/// Note: This file was originally stored under .../procedures/ipl/sbe. It
+/// was moved here at version 1.19.
+
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <regex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+
+
+#define __PPE__
+#include "fapi2.H"
+#include "proc_sbe_fixed.H"
+#include "sbe_xip_image.h"
+
+#include "sbe_link.H"
+#include "p9_image_help_base.H"
+#include "p9_ring_identification.H"
+#include "p9_scan_compression.H"
+
+// Usage: sbe_xip_tool <image> [-<flag> ...] normalize
+// sbe_xip_tool <image> [-<flag> ...] get <item>
+// sbe_xip_tool <image> [-<flag> ...] getv <item> <index>
+// sbe_xip_tool <image> [-<flag> ...] set <item> <value> [ <item1> <value1> ... ]
+// sbe_xip_tool <image> [-<flag> ...] setv <item> <index> <value> [ <item1> <index1> <value1> ... ]
+// sbe_xip_tool <image> [-<flag> ...] report [<regex>]
+// sbe_xip_tool <image> [-<flag> ...] append <section> <file>
+// sbe_xip_tool <image> [-<flag> ...] delete [ <section0> ... <sectionN> ]
+// sbe_xip_tool <image> [-<flag> ...] dis <section or .rings_summary>\n"//
+//
+// This simple application uses the SBE-XIP image APIs to normalize, search
+// update and edit SBE-XIP images. This program encapsulates several commands
+// in a common command framework which requires an image to operate on, a
+// command name, and command arguments that vary by command. Commands that
+// modify the image always rewrite the image in-place in the filesystem;
+// however the original image is only modified if the command has completed
+// without error.
+//
+// The program operates on an SBE-XIP format binary image, which must be
+// normalized - unless the tool is being called to normalize the image in the
+// first place using the 'normalize' command. The tool also validates the
+// image prior to operating on the image.
+//
+// The 'get' command retrieves a scalar value from the image and prints its
+// representation on stdout (followed by a newline). Scalar integer values
+// and image addresses are printed as hex numbers (0x...). Strings are printed
+// verbatim.
+//
+// The 'getv' command retrieves a vector element from the image and prints its
+// representation on stdout (followed by a newline). Integer values
+// and image addresses are printed as hex numbers (0x...). Vectors of strings
+// are not supported.
+//
+// The 'set' command allows setting integer and string values in the image.
+// New integer values can be specified in decimal or hex (0x...). Strings are
+// taken verbatim from the command line. Note that new string values will be
+// silently truncated to the length of the current string if the new value is
+// longer than the current string. Updating address values is currently not
+// supported. Any number of item/value pairs can be specified with a single
+// 'set' command.
+//
+// The 'setv' command is provided to set individual vector elements of
+// integral arrays.
+//
+// The 'report' command prints a report including a dump of the header and
+// section table, a listing of the types and values of all items that appear
+// in the TOC, and a dump of the .halt section. The TOC listing includes the
+// sequence number of the entry in the TOC, the item name, the item type and
+// the item value. The .halt listing displays a map of HALT PC values to the
+// string form of the halt code associated with the HALT address. The optional
+// <regex> expression, if present, is a POSIX Basic Regular Expression. If
+// <regex> is specified, then no header, section table or .halt dumps are
+// provided, and only the TOC entries matching <regex> will be listed.
+//
+// The 'append' command either creates or extends the section named by the
+// section argument, by appending the contents of the named file verbatim.
+// Currently the section must either be the final (highest address) section of
+// the image, or must be empty, in which case the append command creates the
+// section as the final section of the image. The 'append' command writes the
+// relocatable image address where the input file was loaded to stdout.
+//
+// The 'delete' command deletes 0 or more sections, starting with <section0>.
+// Each section to be deleted must either be the final (highest address)
+// section of the image at the time it is deleted, or must be empty. The
+// 'delete' command writes the size of the final modified image to stdout.
+//
+// The 'dis' command disassembles the section named by the section argument.
+// Note that the section name .rings_summary, which is not an actual XIP
+// section name, merely indicates to summarize the .rings section.
+//
+// The following -i<flag> are supported:
+// -ifs
+// causes the validation step to ignore image size check against the file
+// size.
+// -iv
+// causes all validation checking to be ignored. (Skips validation step.)
+
+const char* g_usage =
+"Usage: sbe_xip_tool <image> [-i<flag> ...] normalize\n"
+" sbe_xip_tool <image> [-i<flag> ...] get <item>\n"
+" sbe_xip_tool <image> [-i<flag> ...] getv <item> <index>\n"
+" sbe_xip_tool <image> [-i<flag> ...] set <item> <value> [ <item1> <value1> ... ]\n"
+" sbe_xip_tool <image> [-i<flag> ...] setv <item> <index> <value> [ <item1> <index1> <value1> ... ]\n"
+" sbe_xip_tool <image> [-i<flag> ...] report [<regex>]\n"
+" sbe_xip_tool <image> [-i<flag> ...] append <section> <file>\n"
+" sbe_xip_tool <image> [-i<flag> ...] delete [ <section0> ... <sectionN> ]\n"
+" sbe_xip_tool <image> [-i<flag> ...] dis <section or .rings_summary>\n"//\n"
+"\n"
+"This simple application uses the SBE-XIP image APIs to normalize, search\n"
+"update and edit SBE-XIP images. This program encapsulates several commands\n"
+"in a common command framework which requires an image to operate on, a\n"
+"command name, and command arguments that vary by command. Commands that\n"
+"modify the image always rewrite the image in-place in the filesystem;\n"
+"however the original image is only modified if the command has completed\n"
+"without error.\n"
+"\n"
+"The program operates on an SBE-XIP format binary image, which must be\n"
+"normalized - unless the tool is being called to normalize the image in the\n"
+"first place using the 'normalize' command. The tool also validates the\n"
+"image prior to operating on the image.\n"
+"\n"
+"The 'get' command retrieves a scalar value from the image and prints its\n"
+"representation on stdout (followed by a newline). Scalar integer values\n"
+"and image addresses are printed as hex numbers (0x...). Strings are printed\n"
+"verbatim.\n"
+"\n"
+"The 'getv' command retrieves a vector element from the image and prints its\n"
+"representation on stdout (followed by a newline). Integer values\n"
+"and image addresses are printed as hex numbers (0x...). Vectors of strings\n"
+"are not supported.\n"
+"\n"
+"The 'set' command allows setting integer and string values in the image.\n"
+"New integer values can be specified in decimal or hex (0x...). Strings are\n"
+"taken verbatim from the command line. Note that new string values will be\n"
+"silently truncated to the length of the current string if the new value is\n"
+"longer than the current string. Updating address values is currently not\n"
+"supported. Any number of item/value pairs can be specified with a single\n"
+"'set' command.\n"
+"\n"
+"The 'setv' command is provided to set individual vector elements of\n"
+"integral arrays.\n"
+"\n"
+"The 'report' command prints a report including a dump of the header and\n"
+"section table, a listing of the types and values of all items that appear\n"
+"in the TOC, and a dump of the .halt section. The TOC listing includes the\n"
+"sequence number of the entry in the TOC, the item name, the item type and\n"
+"the item value. The .halt listing displays a map of HALT PC values to the\n"
+"string form of the halt code associated with the HALT address. The optional\n"
+"<regex> expression, if present, is a POSIX Basic Regular Expression. If\n"
+"<regex> is specified, then no header, section table or .halt dumps are\n"
+"provided, and only the TOC entries matching <regex> will be listed.\n"
+"\n"
+"The 'append' command either creates or extends the section named by the\n"
+"section argument, by appending the contents of the named file verbatim.\n"
+"Currently the section must either be the final (highest address) section of\n"
+"the image, or must be empty, in which case the append command creates the\n"
+"section as the final section of the image. The 'append' command writes the\n"
+"relocatable image address where the input file was loaded to stdout.\n"
+"\n"
+"The 'delete' command deletes 0 or more sections, starting with <section0>.\n"
+"Each section to be deleted must either be the final (highest address)\n"
+"section of the image at the time it is deleted, or must be empty. The\n"
+"'delete' command writes the size of the final modified image to stdout.\n"
+"\n"
+"The 'dis' command disassembles the section named by the section argument.\n"
+"Note that the section name .rings_summary, which is not an actual XIP\n"
+"section name, merely indicates to summarize the .rings section.\n"
+"\n"
+"-i<flag>:\n"
+"\t-ifs Causes the validation step to ignore image size check against the\n"
+"\tfile size.\n"
+"\t-iv Causes all validation checking to be ignored.\n"
+ ;
+
+SBE_XIP_ERROR_STRINGS(g_errorStrings);
+SBE_XIP_TYPE_STRINGS(g_typeStrings);
+SBE_XIP_TYPE_ABBREVS(g_typeAbbrevs);
+SBE_XIP_SECTION_NAMES(g_sectionNames);
+// Disassembler error support.
+DIS_ERROR_STRINGS(g_errorStringsDis);
+
+#define ERRBUF_SIZE 60
+
+typedef struct {
+ int index;
+ int regex;
+ regex_t preg;
+} ReportControl;
+
+off_t g_imageSize;
+
+
+// Byte-reverse a 32-bit integer if on an LE machine
+inline uint32_t
+myRev32(const uint32_t i_x)
+{
+ uint32_t rx;
+
+#ifdef _BIG_ENDIAN
+ rx = i_x;
+#else
+ uint8_t *pix = (uint8_t*)(&i_x);
+ uint8_t *prx = (uint8_t*)(&rx);
+
+ prx[0] = pix[3];
+ prx[1] = pix[2];
+ prx[2] = pix[1];
+ prx[3] = pix[0];
+#endif
+
+ return rx;
+}
+
+// Byte-reverse a 64-bit integer if on a little-endian machine
+inline uint64_t
+myRev64(const uint64_t i_x)
+{
+ uint64_t rx;
+
+#ifdef _BIG_ENDIAN
+ rx = i_x;
+#else
+ uint8_t *pix = (uint8_t*)(&i_x);
+ uint8_t *prx = (uint8_t*)(&rx);
+
+ prx[0] = pix[7];
+ prx[1] = pix[6];
+ prx[2] = pix[5];
+ prx[3] = pix[4];
+ prx[4] = pix[3];
+ prx[5] = pix[2];
+ prx[6] = pix[1];
+ prx[7] = pix[0];
+#endif
+
+ return rx;
+}
+
+// Normalize an SBE-XIP image. We normalize a copy of the image first so that
+// the original image will be available for debugging in case the
+// normalization fails, then validate and copy the normalized image back to
+// the mmap()-ed file.
+
+int
+normalize(void* io_image, const int i_argc, const char** i_argv, uint32_t i_maskIgnores)
+{
+ int rc;
+ void *copy;
+
+ do {
+
+ // The 'normalize' command takes no arguments
+
+ if (i_argc != 0) {
+ fprintf(stderr, g_usage);
+ exit(1);
+ }
+
+ copy = malloc(g_imageSize);
+ if (copy == 0) {
+ perror("malloc() failed : ");
+ exit(1);
+ }
+
+ memcpy(copy, io_image, g_imageSize);
+
+ rc = sbe_xip_normalize(copy);
+ if (rc) break;
+
+ if ( !(i_maskIgnores & SBE_XIP_IGNORE_ALL) ) {
+ rc = sbe_xip_validate2(copy, g_imageSize, i_maskIgnores);
+ }
+ if (rc) break;
+
+ memcpy(io_image, copy, g_imageSize);
+
+ } while (0);
+
+ return rc;
+}
+
+
+// Print a line of a report, listing the index, symbol, type and current
+// value.
+
+int
+tocListing(void* io_image,
+ const SbeXipItem* i_item,
+ void* arg)
+{
+ int rc;
+ ReportControl *control;
+ uint64_t data;
+ char* s;
+
+ control = (ReportControl*)arg;
+
+ do {
+ rc = 0;
+
+ if (control->regex) {
+ if (regexec(&(control->preg), i_item->iv_id, 0, 0, 0)) {
+ break;
+ }
+ }
+
+ printf("0x%04x | %-42s | %s | ",
+ control->index, i_item->iv_id,
+ SBE_XIP_TYPE_STRING(g_typeAbbrevs, i_item->iv_type));
+
+ switch (i_item->iv_type) {
+ case SBE_XIP_UINT8:
+ rc = sbe_xip_get_scalar(io_image, i_item->iv_id, &data);
+ if (rc) break;
+ printf("0x%02x", (uint8_t)data);
+ break;
+ case SBE_XIP_UINT32:
+ rc = sbe_xip_get_scalar(io_image, i_item->iv_id, &data);
+ if (rc) break;
+ printf("0x%08x", (uint32_t)data);
+ break;
+ case SBE_XIP_UINT64:
+ rc = sbe_xip_get_scalar(io_image, i_item->iv_id, &data);
+ if (rc) break;
+ printf("0x%016llx", data);
+ break;
+ case SBE_XIP_STRING:
+ rc = sbe_xip_get_string(io_image, i_item->iv_id, &s);
+ if (rc) break;
+ printf("%s", s);
+ break;
+ case SBE_XIP_ADDRESS:
+ rc = sbe_xip_get_scalar(io_image, i_item->iv_id, &data);
+ if (rc) break;
+ printf("0x%04x:0x%08x",
+ (uint16_t)((data >> 32) & 0xffff),
+ (uint32_t)(data & 0xffffffff));
+ break;
+ default:
+ rc = SBE_XIP_BUG;
+ break;
+ }
+ printf("\n");
+ } while (0);
+ control->index += 1;
+ return rc;
+}
+
+
+// Dump the image header, including the section table
+
+int
+dumpHeader(void* i_image)
+{
+ int i;
+ SbeXipHeader header;
+ SbeXipSection* section;
+ char magicString[9];
+
+ SBE_XIP_SECTION_NAMES(section_name);
+
+ // Dump header information. Since the TOC may not exist we need to get
+ // the information from the header explicitly.
+
+ sbe_xip_translate_header(&header, (SbeXipHeader*)i_image);
+
+ memcpy(magicString, (char*)(&(((SbeXipHeader*)i_image)->iv_magic)), 8);
+ magicString[8] = 0;
+
+ printf("Magic Number : 0x%016llx \"%s\"\n",
+ header.iv_magic, magicString);
+ printf("Header Version : 0x%02x\n", header.iv_headerVersion);
+ printf("Link Address : 0x%016llx\n", header.iv_linkAddress);
+ printf("Entry Offset : 0x%08x\n", (uint32_t)header.iv_entryOffset);
+ printf("Image Size : 0x%08x (%d)\n",
+ header.iv_imageSize, header.iv_imageSize);
+ printf("Normalized : %s\n", header.iv_normalized ? "Yes" : "No");
+ printf("TOC Sorted : %s\n", header.iv_tocSorted ? "Yes" : "No");
+ printf("Build Date : %02d/%02d/%04d\n",
+ (header.iv_buildDate / 100) % 100,
+ header.iv_buildDate % 100,
+ header.iv_buildDate / 10000);
+ printf("Build Time : %02d:%02d\n",
+ header.iv_buildTime / 100,
+ header.iv_buildTime % 100);
+ printf("Build User : %s\n", header.iv_buildUser);
+ printf("Build Host : %s\n", header.iv_buildHost);
+ printf("\n");
+
+ printf("Section Table : Offset Size\n");
+ printf("\n");
+
+ for (i = 0; i < SBE_XIP_SECTIONS; i++) {
+ section = &(header.iv_section[i]);
+ printf("%-16s 0x%08x 0x%08x (%d)\n",
+ section_name[i],
+ section->iv_offset, section->iv_size, section->iv_size);
+ }
+
+ printf("\n");
+
+ return 0;
+}
+
+
+// Dump an entry from .halt
+
+int
+haltListing(void* io_image,
+ const uint64_t i_homerAddress,
+ const char* i_rcString,
+ void* io_arg)
+{
+ printf("%016llx : %s\n", i_homerAddress, i_rcString);
+ return 0;
+}
+
+
+// Print a report
+
+int
+report(void* io_image, const int i_argc, const char** i_argv)
+{
+ int rc;
+ ReportControl control;
+ char errbuf[ERRBUF_SIZE];
+
+ do {
+
+ // Basic syntax check : [<regexp>]
+
+ if (i_argc > 1) {
+ fprintf(stderr, g_usage);
+ exit(1);
+ }
+
+ // Compile a regular expression if supplied
+
+ if (i_argc == 1) {
+ rc = regcomp(&(control.preg), i_argv[0], REG_NOSUB);
+ if (rc) {
+ regerror(rc, &(control.preg), errbuf, ERRBUF_SIZE);
+ fprintf(stderr, "Error from regcomp() : %s\n", errbuf);
+ exit(1);
+ }
+ control.regex = 1;
+ } else {
+ control.regex = 0;
+ dumpHeader(io_image);
+ printf("TOC Report\n\n");
+ }
+
+ // Map the TOC with the mapReport() function
+
+ control.index = 0;
+ rc = sbe_xip_map_toc(io_image, tocListing, (void*)(&control));
+ if (rc) break;
+
+ // Dump the .halt section
+
+ if (i_argc == 0) {
+ printf("\nHALT report\n\n");
+ rc = sbe_xip_map_halt(io_image, haltListing, 0);
+ if (rc == SBE_XIP_ITEM_NOT_FOUND) {
+ rc = 0;
+ }
+ if (rc) break;
+ }
+
+ } while (0);
+
+ return rc;
+}
+
+
+// Set a scalar or vector element values in the image. The 'i_setv' argument
+// indicates set/setv (0/1).
+
+int
+set(void* io_image, const int i_argc, const char** i_argv, int i_setv)
+{
+ int rc, arg, base, clause_args, index_val;
+ SbeXipItem item;
+ unsigned long long newValue;
+ const char *key, *index, *value;
+ char *endptr;
+
+ do {
+
+ // Basic syntax check: <item> <value> [ <item1> <value1> ... ]
+ // Basic syntax check: <item> <index> <value> [ <item1> <index1> <value1> ... ]
+
+ clause_args = (i_setv ? 3 : 2);
+
+ if ((i_argc % clause_args) != 0) {
+ fprintf(stderr, g_usage);
+ exit(1);
+ }
+
+ for (arg = 0; arg < i_argc; arg += clause_args) {
+
+ key = i_argv[arg];
+ if (i_setv) {
+ index = i_argv[arg + 1];
+ index_val = strtol(index, 0, 0);
+ value = i_argv[arg + 2];
+ } else {
+ index = "";
+ index_val = 0;
+ value = i_argv[arg + 1];
+ }
+
+ // Search for the item to see what type of data it expects, then
+ // case split on the type.
+
+ rc = sbe_xip_find(io_image, key, &item);
+ if (rc) break;
+
+ if (index_val < 0) {
+ fprintf(stderr,
+ "Illegal negative vector index %s for %s\n",
+ index, key);
+ exit(1);
+ } else if ((item.iv_elements != 0) &&
+ (index_val >= item.iv_elements)) {
+ fprintf(stderr,
+ "Index %s out-of-bounds for %s (%d elements)\n",
+ index, key, item.iv_elements);
+ exit(1);
+ }
+
+ switch (item.iv_type) {
+ case SBE_XIP_UINT8:
+ case SBE_XIP_UINT32:
+ case SBE_XIP_UINT64:
+
+ // We need to do a bit of preprocessing on the string to
+ // determine its format and set the base for strtoull(),
+ // otherwise strtoull() will be confused by leading zeros
+ // e.g. in time strings generated by `date +%H%M`, and try to
+ // process the string as octal.
+
+ if ((strlen(value) >= 2) && (value[0] == '0') &&
+ ((value[1] == 'x') || (value[1] == 'X'))) {
+ base = 16;
+ } else {
+ base = 10;
+ }
+
+ errno = 0;
+ newValue = strtoull(value, &endptr, base);
+ if ((errno != 0) || (endptr != (value + strlen(value)))) {
+ fprintf(stderr,
+ "Error parsing putative integer value : %s\n",
+ value);
+ exit(1);
+ }
+
+ switch (item.iv_type) {
+
+ case SBE_XIP_UINT8:
+ if ((uint8_t)newValue != newValue) {
+ fprintf(stderr,
+ "Value 0x%016llx too large for 8-bit type\n",
+ newValue);
+ exit(1);
+ }
+ break;
+
+ case SBE_XIP_UINT32:
+ if ((uint32_t)newValue != newValue) {
+ fprintf(stderr,
+ "Value 0x%016llx too large for 32-bit type\n",
+ newValue);
+ exit(1);
+ }
+ break;
+
+ case SBE_XIP_UINT64:
+ break;
+
+ default:
+ break;
+ }
+
+ rc = sbe_xip_set_element(io_image, key, index_val, newValue);
+ if (rc) rc = SBE_XIP_BUG;
+ break;
+
+ case SBE_XIP_STRING:
+
+ if (i_setv) {
+ fprintf(stderr, "Can't use 'setv' for string data %s\n",
+ key);
+ exit(1);
+ }
+ rc = sbe_xip_set_string(io_image, key, (char*)value);
+ if (rc) rc = SBE_XIP_BUG;
+ break;
+
+ default:
+ fprintf(stderr,
+ "Item %s has type %s, "
+ "which is not supported for '%s'.\n",
+ i_argv[arg],
+ SBE_XIP_TYPE_STRING(g_typeStrings, item.iv_type),
+ (i_setv ? "setv" : "set"));
+ exit(1);
+ break;
+ }
+
+ if (rc) break;
+
+ }
+ } while (0);
+
+ //if good rc, we need to msync the mmaped file to push contents to
+ //the actual file. Per man page this is required although some
+ //file systems (notably AFS) don't seem to require (GSA does)
+ if(!rc)
+ {
+ uint8_t i = 0;
+ do {
+ rc = msync(io_image, g_imageSize , MS_SYNC);
+ if(rc)
+ {
+ i++;
+ fprintf(stderr,
+ "msync failed with errno %d\n", errno);
+ }
+ } while(rc && i < 5);
+
+ if(rc)
+ {
+ exit(3);
+ }
+ }
+
+ return rc;
+}
+
+
+// Get a value from the image, and return on stdout. The 'i_getv' argument
+// indicates get/getv (0/1)
+
+int
+get(void* i_image, const int i_argc, const char** i_argv, int i_getv)
+{
+ int rc, nargs, index_val;
+ SbeXipItem item;
+ const char *key, *index;
+ uint64_t data;
+ char* s;
+
+ do {
+
+ // Basic syntax check: <item>
+ // Basic syntax check: <item> <index>
+
+ nargs = (i_getv ? 2 : 1);
+
+ if (i_argc != nargs) {
+ fprintf(stderr, g_usage);
+ exit(1);
+ }
+
+ key = i_argv[0];
+ if (i_getv) {
+ index = i_argv[1];
+ index_val = strtol(index, 0, 0);
+ } else {
+ index = "";
+ index_val = 0;
+ }
+
+ // Search for the item to determine its type, then case split on the
+ // type.
+
+ rc = sbe_xip_find(i_image, key, &item);
+ if (rc) break;
+
+ if (index_val < 0) {
+ fprintf(stderr,
+ "Illegal negative vector index %s for %s\n",
+ index, key);
+ exit(1);
+ } else if ((item.iv_elements != 0) &&
+ (index_val >= item.iv_elements)) {
+ fprintf(stderr, "Index %s out-of-bounds for %s (%d elements)\n",
+ index, key, item.iv_elements);
+ exit(1);
+ }
+
+ switch (item.iv_type) {
+
+ case SBE_XIP_UINT8:
+ case SBE_XIP_UINT32:
+ case SBE_XIP_UINT64:
+ rc = sbe_xip_get_element(i_image, key, index_val, &data);
+ if (rc) {
+ rc = SBE_XIP_BUG;
+ break;
+ }
+ switch (item.iv_type) {
+ case SBE_XIP_UINT8:
+ printf("0x%02x\n", (uint8_t)data);
+ break;
+ case SBE_XIP_UINT32:
+ printf("0x%08x\n", (uint32_t)data);
+ break;
+ case SBE_XIP_UINT64:
+ printf("0x%016llx\n", data);
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case SBE_XIP_ADDRESS:
+ if (i_getv) {
+ fprintf(stderr, "Can't use 'getv' for address data : %s\n",
+ key);
+ exit(1);
+ }
+ rc = sbe_xip_get_scalar(i_image, key, &data);
+ if (rc) {
+ rc = SBE_XIP_BUG;
+ break;
+ }
+ printf("0x%012llx\n", data);
+ break;
+
+ case SBE_XIP_STRING:
+ if (i_getv) {
+ fprintf(stderr, "Can't use 'getv' for string data : %s\n",
+ key);
+ exit(1);
+ }
+ rc = sbe_xip_get_string(i_image, key, &s);
+ if (rc) {
+ rc = SBE_XIP_BUG;
+ break;
+ }
+ printf("%s\n", s);
+ break;
+
+ default:
+ fprintf(stderr, "%s%d : Bug, unexpected type %d\n",
+ __FILE__, __LINE__, item.iv_type);
+ exit(1);
+ break;
+ }
+ } while (0);
+
+ return rc;
+}
+
+
+// strtoul() with application-specific error handling
+
+unsigned long
+localStrtoul(const char* s)
+{
+ unsigned long v;
+ char* endptr;
+
+ errno = 0;
+ v = strtoul(s, &endptr, 0);
+ if ((errno != 0) || (endptr != (s + strlen(s)))) {
+ fprintf(stderr,
+ "Error parsing putative integer value : %s\n",
+ s);
+ exit(1);
+ }
+ return v;
+}
+
+
+// Append a file to section
+
+int
+append(const char* i_imageFile, const int i_imageFd, void* io_image,
+ int i_argc, const char** i_argv)
+{
+ int fileFd, newImageFd, sectionId, rc;
+ struct stat buf;
+ const char* section;
+ const char* file;
+ void* appendImage;
+ void* newImage;
+ uint32_t size, newSize, sectionOffset;
+ uint64_t homerAddress;
+
+ do {
+
+ // Basic syntax check: <section> <file>
+
+ if (i_argc != 2) {
+ fprintf(stderr, g_usage);
+ exit(1);
+ }
+ section = i_argv[0];
+ file = i_argv[1];
+
+
+ // Translate the section name to a section Id
+
+ for (sectionId = 0; sectionId < SBE_XIP_SECTIONS; sectionId++) {
+ if (strcmp(section, g_sectionNames[sectionId]) == 0) {
+ break;
+ }
+ }
+ if (sectionId == SBE_XIP_SECTIONS) {
+ fprintf(stderr, "Unrecognized section name : '%s;\n",
+ section);
+ exit(1);
+ }
+
+
+ // Open and mmap the file to be appended
+
+ fileFd = open(file, O_RDONLY);
+ if (fileFd < 0) {
+ perror("open() of the file to be appended failed : ");
+ exit(1);
+ }
+
+ rc = fstat(fileFd, &buf);
+ if (rc) {
+ perror("fstat() of the file to be appended failed : ");
+ exit(1);
+ }
+
+ appendImage = mmap(0, buf.st_size, PROT_READ, MAP_SHARED, fileFd, 0);
+ if (appendImage == MAP_FAILED) {
+ perror("mmap() of the file to be appended failed : ");
+ exit(1);
+ }
+
+
+ // malloc() a buffer for the new image, adding space for alignment
+
+ rc = sbe_xip_image_size(io_image, &size);
+ if (rc) break;
+
+ newSize = size + buf.st_size + SBE_XIP_MAX_SECTION_ALIGNMENT;
+
+ newImage = malloc(newSize);
+
+ if (newImage == 0) {
+ fprintf(stderr, "Can't malloc() a buffer for the new image\n");
+ exit(1);
+ }
+
+
+ // Copy the image. At this point the original image file must be
+ // closed.
+
+ memcpy(newImage, io_image, size);
+
+ rc = close(i_imageFd);
+ if (rc) {
+ perror("close() of the original image file failed : ");
+ exit(1);
+ }
+
+
+ // Do the append and print the image address where the data was loaded.
+ // We will not fail for unaligned addresses, as we have no knowledge
+ // of whether or why the user wants the final image address.
+
+ rc = sbe_xip_append(newImage, sectionId,
+ appendImage, buf.st_size,
+ newSize, &sectionOffset);
+ if (rc) break;
+
+ rc = sbe_xip_section2image(newImage, sectionId, sectionOffset,
+ &homerAddress);
+ if (rc && (rc != SBE_XIP_ALIGNMENT_ERROR)) break;
+
+ printf("0x%016llx\n", homerAddress);
+
+
+ // Now write the new image back to the filesystem
+
+ newImageFd = open(i_imageFile, O_WRONLY | O_TRUNC);
+ if (newImageFd < 0) {
+ perror("re-open() of image file failed : ");
+ exit(1);
+ }
+
+ rc = sbe_xip_image_size(newImage, &size);
+ if (rc) break;
+
+ rc = write(newImageFd, newImage, size);
+ if ((rc < 0) || ((uint32_t)rc != size)) {
+ perror("write() of modified image failed : ");
+ exit(1);
+ }
+
+ rc = close(newImageFd);
+ if (rc) {
+ perror("close() of modified image failed : ");
+ exit(1);
+ }
+ } while (0);
+
+ return rc;
+}
+
+
+// Delete 0 or more sections in order.
+
+int
+deleteSection(const char* i_imageFile, const int i_imageFd, void* io_image,
+ int i_argc, const char** i_argv)
+{
+ int newImageFd, sectionId, rc, argc;
+ const char* section;
+ const char** argv;
+ void* newImage;
+ uint32_t size;
+
+ do {
+
+ // malloc() a buffer for the new image
+
+ rc = sbe_xip_image_size(io_image, &size);
+ if (rc) break;
+
+ newImage = malloc(size);
+
+ if (newImage == 0) {
+ fprintf(stderr, "Can't malloc() a buffer for the new image\n");
+ exit(1);
+ }
+
+
+ // Copy the image. At this point the original image file must be
+ // closed.
+
+ memcpy(newImage, io_image, size);
+
+ rc = close(i_imageFd);
+ if (rc) {
+ perror("close() of the original image file failed : ");
+ exit(1);
+ }
+
+ // Delete the sections in argument order
+
+ for (argc = i_argc, argv = i_argv; argc != 0; argc--, argv++) {
+
+ // Translate the section name to a section Id
+
+ section = *argv;
+
+ for (sectionId = 0; sectionId < SBE_XIP_SECTIONS; sectionId++) {
+ if (strcmp(section, g_sectionNames[sectionId]) == 0) {
+ break;
+ }
+ }
+ if (sectionId == SBE_XIP_SECTIONS) {
+ fprintf(stderr, "Unrecognized section name : '%s;\n",
+ section);
+ exit(1);
+ }
+
+ // Delete the section
+
+ rc = sbe_xip_delete_section(newImage, sectionId);
+ if (rc) break;
+ }
+ if (rc) break;
+
+ // Print the final size of the new image
+
+ rc = sbe_xip_image_size(newImage, &size);
+ if (rc) break;
+
+ printf("%u\n", size);
+
+ // Now write the new image back to the filesystem
+
+ newImageFd = open(i_imageFile, O_WRONLY | O_TRUNC);
+ if (newImageFd < 0) {
+ perror("re-open() of image file failed : ");
+ exit(1);
+ }
+
+ rc = write(newImageFd, newImage, size);
+ if ((rc < 0) || ((uint32_t)rc != size)) {
+ perror("write() of modified image failed : ");
+ exit(1);
+ }
+
+ rc = close(newImageFd);
+ if (rc) {
+ perror("close() of modified image failed : ");
+ exit(1);
+ }
+ } while (0);
+
+ return rc;
+}
+
+
+// 'TEST' is an undocumented command provided to test the APIs. It searches
+// and modifies a copy of the image but puts the image back together as it
+// was, then verifies that the the original image and the copy are identical.
+
+#define BOMB_IF(test) \
+ if (test) { \
+ fprintf(stderr, "%s:%d : Error in TEST\n", \
+ __FILE__, __LINE__); \
+ exit(1); \
+ }
+
+#define BOMB_IF_RC \
+ if (rc) { \
+ fprintf(stderr, "%s:%d : Error in TEST, rc = %s\n", \
+ __FILE__, __LINE__, \
+ SBE_XIP_ERROR_STRING(g_errorStrings, rc)); \
+ exit(1); \
+ }
+
+
+int
+TEST(void* io_image, const int i_argc, const char** i_argv)
+{
+ int rc;
+ uint64_t linkAddress, entryPoint, data, data1, magicKey, entry_offset[2];
+ char *key, *revision, *revdup, *longString, *shortString;
+ void *originalImage, *deleteAppendImage;
+ uint32_t imageSize;
+ SbeXipItem item;
+ SbeXipHeader header;
+ SbeXipSection section;
+ //ProcSbeFixed* fixed;
+ uint32_t tocSize;
+
+ do {
+ rc = sbe_xip_image_size(io_image, &imageSize);
+ BOMB_IF_RC;
+ originalImage = malloc(imageSize);
+ BOMB_IF(originalImage == 0);
+ memcpy(originalImage, io_image, imageSize);
+
+ rc = sbe_xip_get_scalar(io_image, "toc_sorted", &data);
+ BOMB_IF_RC;
+ BOMB_IF(data != 1);
+
+ rc = sbe_xip_get_scalar(io_image, "image_size", &data);
+ BOMB_IF_RC;
+ BOMB_IF(data != (uint64_t)g_imageSize);
+
+ rc = sbe_xip_get_scalar(io_image, "magic", &magicKey);
+ BOMB_IF_RC;
+
+ switch (magicKey) {
+ case SBE_BASE_MAGIC:
+ key = (char*)"proc_sbe_fabricinit_revision";
+ rc = sbe_xip_get_string(io_image, key, &revision);
+ BOMB_IF_RC;
+ BOMB_IF(strncmp(revision, "1.", 2) != 0);
+ break;
+ case SBE_SEEPROM_MAGIC:
+ key = (char*)"";
+ // Can't do this test here as the TOC has been stripped
+ break;
+ case SBE_CENTAUR_MAGIC:
+ key = (char*)"cen_sbe_initf_revision";
+ rc = sbe_xip_get_string(io_image, key, &revision);
+ BOMB_IF_RC;
+ BOMB_IF(strncmp(revision, "1.", 2) != 0);
+ break;
+ default:
+ BOMB_IF(1);
+ break;
+ }
+
+ rc = sbe_xip_get_scalar(io_image, "link_address", &linkAddress);
+ BOMB_IF_RC;
+ if (magicKey != SBE_SEEPROM_MAGIC) {
+ rc = sbe_xip_get_scalar(io_image, "entry_point", &entryPoint);
+ BOMB_IF_RC;
+ }
+ rc = sbe_xip_get_scalar(io_image, "entry_offset", &data);
+ BOMB_IF_RC;
+ BOMB_IF((magicKey != SBE_SEEPROM_MAGIC) && (entryPoint != (linkAddress + data)));
+
+ rc =
+ sbe_xip_set_scalar(io_image, "toc_sorted", 0) ||
+ sbe_xip_set_scalar(io_image, "image_size", 0);
+ BOMB_IF_RC;
+
+ data = 0;
+ data += (rc = sbe_xip_get_scalar(io_image, "toc_sorted", &data), data);
+ BOMB_IF_RC;
+ data += (rc = sbe_xip_get_scalar(io_image, "image_size", &data), data);
+ BOMB_IF_RC;
+ BOMB_IF(data != 0);
+
+ // Write back keys found during read check.
+
+ rc =
+ sbe_xip_set_scalar(io_image, "toc_sorted", 1) ||
+ sbe_xip_set_scalar(io_image, "image_size", g_imageSize);
+ BOMB_IF_RC;
+
+ // We'll rewrite the revision keyword with a long string and a short
+ // string, and verify that rewriting is being done correctly. In the
+ // end we copy the original revision string back in, which is safe
+ // because the memory allocation for strings does not change when they
+ // are modified.
+
+ revdup = strdup(revision);
+ longString = (char*)"A very long string";
+ shortString = (char*)"?";
+
+ if (magicKey != SBE_SEEPROM_MAGIC) {
+ rc =
+ sbe_xip_set_string(io_image, key, longString) ||
+ sbe_xip_get_string(io_image, key, &revision);
+ BOMB_IF_RC;
+ BOMB_IF((strlen(revision) != strlen(revdup)) ||
+ (strncmp(revision, longString, strlen(revdup)) != 0));
+
+ rc =
+ sbe_xip_set_string(io_image, key, shortString) ||
+ sbe_xip_get_string(io_image, key, &revision);
+ BOMB_IF_RC;
+ BOMB_IF(strcmp(revision, shortString) != 0);
+
+ memcpy(revision, revdup, strlen(revdup) + 1);
+ }
+
+ // Use sbe_xip_[read,write]_uint64 to modify the image and restore it
+ // to its original form.
+
+ rc = sbe_xip_find(io_image, "entry_offset", &item);
+ BOMB_IF_RC;
+ rc = sbe_xip_get_scalar(io_image, "entry_offset", &(entry_offset[0]));
+ BOMB_IF_RC;
+
+ rc = sbe_xip_read_uint64(io_image, item.iv_address, &(entry_offset[1]));
+ BOMB_IF_RC;
+ BOMB_IF(entry_offset[0] != entry_offset[1]);
+
+ rc = sbe_xip_write_uint64(io_image, item.iv_address,
+ 0xdeadbeefdeadc0deull);
+ BOMB_IF_RC;
+ rc = sbe_xip_read_uint64(io_image, item.iv_address, &(entry_offset[1]));
+ BOMB_IF_RC;
+ BOMB_IF(entry_offset[1] != 0xdeadbeefdeadc0deull);
+
+ rc = sbe_xip_write_uint64(io_image, item.iv_address, entry_offset[0]);
+ BOMB_IF_RC;
+
+ // Try sbe_xip_get_section against the translated header
+
+ sbe_xip_translate_header(&header, (SbeXipHeader*)io_image);
+ rc = sbe_xip_get_section(io_image, SBE_XIP_SECTION_TOC, &section);
+ BOMB_IF_RC;
+ BOMB_IF((section.iv_size !=
+ header.iv_section[SBE_XIP_SECTION_TOC].iv_size));
+
+
+ // Make sure the .fixed section access compiles and seems to
+ // work. Modify an entry via the .fixed and verify it with normal TOC
+ // access.
+
+ if (magicKey == SBE_SEEPROM_MAGIC) {
+
+ BOMB_IF(0 != 0);
+
+ exit(1);
+
+ rc = sbe_xip_get_scalar(io_image, "proc_sbe_ex_dpll_initf_control",
+ &data);
+ BOMB_IF_RC;
+ //fixed =
+ //(ProcSbeFixed*)((unsigned long)io_image + SBE_XIP_FIXED_OFFSET);
+ //fixed->proc_sbe_ex_dpll_initf_control = 0xdeadbeefdeadc0deull;
+ rc = sbe_xip_get_scalar(io_image, "proc_sbe_ex_dpll_initf_control",
+ &data1);
+ BOMB_IF_RC;
+#ifdef _BIG_ENDIAN
+ BOMB_IF(data1 != 0xdeadbeefdeadc0deull);
+#else
+ BOMB_IF(data1 != 0xdec0addeefbeaddeull);
+#endif
+ rc = sbe_xip_set_scalar(io_image, "proc_sbe_ex_dpll_initf_control",
+ data);
+ BOMB_IF_RC;
+ }
+
+ // Temporarily "delete" the .toc section and try to get/set via the
+ // mini-TOC for .fixed, and make sure that we can't get things that
+ // are not in the mini-toc.
+
+ tocSize =
+ ((SbeXipHeader*)io_image)->iv_section[SBE_XIP_SECTION_TOC].iv_size;
+
+ ((SbeXipHeader*)io_image)->iv_section[SBE_XIP_SECTION_TOC].iv_size =
+ 0;
+
+ rc = sbe_xip_get_scalar(io_image, "proc_sbe_ex_dpll_initf_control",
+ &data);
+ rc = sbe_xip_set_scalar(io_image, "proc_sbe_ex_dpll_initf_control",
+ 0xdeadbeef);
+ rc = sbe_xip_get_scalar(io_image, "proc_sbe_ex_dpll_initf_control",
+ &data1);
+ BOMB_IF(data1 != 0xdeadbeef);
+ rc = sbe_xip_set_scalar(io_image, "proc_sbe_ex_dpll_initf_control",
+ data);
+ BOMB_IF_RC;
+
+ BOMB_IF(sbe_xip_find(io_image, "proc_sbe_ex_dpll_initf", 0) !=
+ SBE_XIP_ITEM_NOT_FOUND);
+
+ ((SbeXipHeader*)io_image)->iv_section[SBE_XIP_SECTION_TOC].iv_size =
+ tocSize;
+
+ if (magicKey != SBE_SEEPROM_MAGIC) {
+ BOMB_IF(sbe_xip_find(io_image, "proc_sbe_ex_dpll_initf", 0) != 0);
+ }
+
+ // Run the embedded delete and append tests. This assumes that the
+ // test image does not contain the .fit and .ffdc sections. We just
+ // append zeros here, we're mostly interested in whether we can handle
+ // errors and return the image back to its original state.
+
+ BOMB_IF((deleteAppendImage = malloc(imageSize + 2000)) == 0);
+ memcpy(deleteAppendImage, io_image, imageSize);
+
+ BOMB_IF(sbe_xip_append(deleteAppendImage, SBE_XIP_SECTION_FIT,
+ 0, 973, imageSize + 2000, 0) != 0);
+ BOMB_IF(sbe_xip_append(deleteAppendImage, SBE_XIP_SECTION_FFDC,
+ 0, 973, imageSize + 2000, 0) != 0);
+
+#ifdef DEBUG_SBE_XIP_IMAGE
+ printf("\nYou will see an expected warning below "
+ "about SBE_XIP_WOULD_OVERFLOW\n"
+ "It means the TEST is working (not failing)\n\n");
+#endif
+
+ BOMB_IF(sbe_xip_append(deleteAppendImage, SBE_XIP_SECTION_FFDC,
+ 0, 973, imageSize + 2000, 0) == 0);
+
+ BOMB_IF(sbe_xip_delete_section(deleteAppendImage, SBE_XIP_SECTION_FFDC) != 0);
+ BOMB_IF(sbe_xip_delete_section(deleteAppendImage, SBE_XIP_SECTION_FIT) != 0);
+
+ memcpy(io_image, deleteAppendImage, imageSize);
+
+ // Finally compare against the original
+
+ BOMB_IF(memcmp(io_image, originalImage, imageSize));
+
+ } while (0);
+
+ return rc;
+}
+
+
+/// Function: pairRingNameAndAddr() to be used w/sbe_xip_map_toc()
+///
+/// Brief: Looks for address match for both base and override rings and
+/// for multi-chiplet rings. Returns the ring name and other good
+/// stuff in the PairingInfo structure upon a match.
+///
+/// \param[in] i_image A pointer to an SBE-XIP image in host memory.
+///
+/// \param[in] i_item A pointer to the "next" SbeXipItem in the TOC.
+///
+/// \param[io] io_pairing A pointer to the structure, PairingInfo.
+///
+/// Assumptions:
+/// - On input, io_pairing contains
+/// - address = the backPtr of the next ring block,
+/// - vectorpos = the next vector position, starting from 0,1,2,..,31 and
+/// which includes possible override pos.
+/// - The TOC is then traversed and each TOC entry is put into i_item.
+/// - The backPtr in io_pairing is kept constant until TOC has been exhausted.
+/// - On output, io_pairing contains
+/// - name = TOC name
+/// - isvpd = whether it's a VPD or non-VPD ring
+/// - overridable = whether it's an overridable ring
+/// - override = whether it's a base or an override ring
+/// - In general, we don't know if a ring is a base or an override of if it is a
+/// multi-chiplet type. Thus, we first look for a match to the vector in
+/// in position zero, then we try position one, then position two, ..., and up
+/// to a max of position 31 (which would be an override for ex chiplet 0x1F).
+///
+static int pairRingNameAndAddr( void *i_image, const SbeXipItem *i_item, void *io_pairing)
+{
+ int rc=0,rcLoc=-1;
+ SbeXipItem tocItem;
+ PairingInfo *pairingInfo;
+ RingIdList *ringIdList;
+
+ SBE_XIP_ERROR_STRINGS(g_errorStrings);
+
+ rcLoc = sbe_xip_find( i_image, i_item->iv_id, &tocItem);
+ if (rcLoc) {
+ fprintf( stderr, "sbe_xip_find() failed : %s\n", SBE_XIP_ERROR_STRING(g_errorStrings, rcLoc));
+ rc = DIS_RING_NAME_ADDR_MATCH_FAILURE;
+ }
+ else {
+ pairingInfo = (PairingInfo*)io_pairing;
+ // Do a sanity check.
+ if (pairingInfo->vectorpos>31) {
+ fprintf( stderr, "vectorpos (=%i) must be between [0;31]\n",pairingInfo->vectorpos);
+ rc = DIS_RING_NAME_ADDR_MATCH_FAILURE;
+ }
+ // Check for match.
+ // - vectorpos is passed in such that first we look for base match, then for override
+ // or chiplet range match.
+ if (tocItem.iv_address == pairingInfo->address-8*pairingInfo->vectorpos &&
+ tocItem.iv_id!=NULL ) {
+ pairingInfo->name = tocItem.iv_id;
+ rcLoc = get_vpd_ring_list_entry(pairingInfo->name,0,&ringIdList);
+ if (!rcLoc) {
+ // It is a VPD ring...and they never have overrides.
+ pairingInfo->isvpd = 1;
+ pairingInfo->overridable = 0;
+ }
+ else {
+ // It is a non-VPD ring...and they all have override capability.
+ pairingInfo->isvpd = 0;
+ pairingInfo->overridable = 1;
+ }
+ if (pairingInfo->vectorpos==0)
+ // This can only be a base match.
+ pairingInfo->override = 0;
+ else {
+ // This is not a base match. Investigating further if override. (Note,
+ // this includes a multi-dim vector with multi-dim override.)
+ if (pairingInfo->overridable &&
+ 2*(pairingInfo->vectorpos/2)!=pairingInfo->vectorpos)
+ pairingInfo->override = 1;
+ else
+ pairingInfo->override = 0;
+ }
+ rc = DIS_RING_NAME_ADDR_MATCH_SUCCESS;
+ }
+ }
+ return rc;
+}
+
+// this function is just defined out, because there is a future need.
+#ifdef BLUBBER
+/// Function: disassembleSection
+///
+/// Brief: Disassembles a section and returns a pointer to a buffer that
+/// contains the listing.
+///
+/// \param[in] i_image A pointer to an SBE-XIP image in host memory.
+///
+/// \param[in] i_argc Additional number of arguments beyond "dis" keyword.
+///
+/// \param[in] i_argv Additional arguments beyond "dis" keyword.
+///
+/// Assumptions:
+///
+int disassembleSection(void *i_image,
+ int i_argc,
+ const char **i_argv)
+{
+ int rc=0, rcSet=0;
+ uint32_t rcCount=0;
+ char *disList=NULL;
+ uint32_t sizeSection=0, nextLinkOffsetBlock=0;
+ uint32_t sizeBlock=0, sizeData=0, sizeCode=0, sizeData2=0;
+ uint32_t sizeDisLine=0, sizeList=0, sizeListMax=0;
+ uint32_t offsetCode=0;
+ uint8_t typeRingsSection=0; // 0: RS4 1: Wiggle-Flip
+ uint8_t bSummary=0, bFoundInToc=0;
+ uint32_t sectionId;
+ uint64_t backPtr=0, fwdPtr=0;
+ PairingInfo pairingInfo;
+ const char *sectionName;
+ char *ringName;
+ uint32_t ringSeqNo=0; // Ring sequence location counter.
+ uint8_t vectorPos,overRidable;
+ void *nextBlock, *nextSection;
+ SbeXipHeader hostHeader;
+ SbeXipSection hostSection;
+ ImageInlineContext ctx;
+ ImageInlineDisassembly dis;
+ char lineDis[LISTING_STRING_SIZE];
+ void *hostRs4Container;
+ uint32_t compressedBits=0, ringLength=0;
+ double compressionPct=0;
+
+ if (i_argc != 1) {
+ fprintf(stderr, g_usage);
+ exit(1);
+ }
+ sectionName = i_argv[0];
+
+ // Determine SBE-XIP section ID from the section name, e.g.
+ // .ipl_text => SBE_XIP_SECTION_IPL_TEXT
+ // .text => SBE_XIP_SECTION_TEXT
+ // .rings => SBE_XIP_SECTION_RINGS
+ if (strcmp(sectionName, ".header")==0)
+ sectionId = SBE_XIP_SECTION_HEADER;
+ else
+ if (strcmp(sectionName, ".fixed")==0)
+ sectionId = SBE_XIP_SECTION_FIXED;
+ else
+ if (strcmp(sectionName, ".fixed_toc")==0)
+ sectionId = SBE_XIP_SECTION_FIXED_TOC;
+ else
+ if (strcmp(sectionName, ".ipl_text")==0)
+ sectionId = SBE_XIP_SECTION_IPL_TEXT;
+ else
+ if (strcmp(sectionName, ".ipl_data")==0)
+ sectionId = SBE_XIP_SECTION_IPL_DATA;
+ else
+ if (strcmp(sectionName, ".text")==0)
+ sectionId = SBE_XIP_SECTION_TEXT;
+ else
+ if (strcmp(sectionName, ".data")==0)
+ sectionId = SBE_XIP_SECTION_DATA;
+ else
+ if (strcmp(sectionName, ".toc")==0)
+ sectionId = SBE_XIP_SECTION_TOC;
+ else
+ if (strcmp(sectionName, ".strings")==0)
+ sectionId = SBE_XIP_SECTION_STRINGS;
+ else
+ if (strcmp(sectionName, ".pibmem0")==0)
+ sectionId = SBE_XIP_SECTION_PIBMEM0;
+ else
+ if (strcmp(sectionName, ".rings")==0)
+ sectionId = SBE_XIP_SECTION_RINGS;
+ else
+ if (strcmp(sectionName, ".rings_summary")==0) {
+ sectionId = SBE_XIP_SECTION_RINGS;
+ bSummary = 1;
+ }
+ else
+ if (strcmp(sectionName, ".dcrings")==0)
+ sectionId = SBE_XIP_SECTION_DCRINGS;
+ else
+ if (strcmp(sectionName, ".halt")==0)
+ sectionId = SBE_XIP_SECTION_HALT;
+ else
+ if (strcmp(sectionName, ".slw")==0)
+ sectionId = SBE_XIP_SECTION_SLW;
+ else
+ if (strcmp(sectionName, ".ffdc")==0)
+ sectionId = SBE_XIP_SECTION_FFDC;
+ else {
+ fprintf(stderr,"ERROR : %s is an invalid section name.\n",sectionName);
+ fprintf(stderr,"Valid <section> names for the 'dis' function are:\n");
+ fprintf(stderr,"\t.header\n");
+ fprintf(stderr,"\t.fixed\n");
+ fprintf(stderr,"\t.fixed_toc\n");
+ fprintf(stderr,"\t.ipl_text\n");
+ fprintf(stderr,"\t.ipl_data\n");
+ fprintf(stderr,"\t.text\n");
+ fprintf(stderr,"\t.data\n");
+ fprintf(stderr,"\t.toc\n");
+ fprintf(stderr,"\t.strings\n");
+ fprintf(stderr,"\t.pibmem0\n");
+ fprintf(stderr,"\t.rings\n");
+ fprintf(stderr,"\t.rings_summary\n");
+ fprintf(stderr,"\t.dcrings\n");
+ fprintf(stderr,"\t.halt\n");
+ fprintf(stderr,"\t.slw\n");
+ fprintf(stderr,"\t.ffdc\n");
+ exit(1);
+ }
+
+ // Get host header and section pointer.
+ //
+ sbe_xip_translate_header( &hostHeader, (SbeXipHeader*)i_image);
+ rc = sbe_xip_get_section( i_image, sectionId, &hostSection);
+ if (rc) {
+ fprintf( stderr, "sbe_xip_get_section() failed : %s\n", SBE_XIP_ERROR_STRING(g_errorStrings, rc));
+ return SBE_XIP_DISASSEMBLER_ERROR;
+ }
+ sizeSection = hostSection.iv_size;
+ nextBlock = (void*)(hostSection.iv_offset + (uintptr_t)i_image);
+ nextSection = (void*)((uint64_t)nextBlock + (uint64_t)sizeSection);
+
+ // Relocatable offset of section at hand.
+ nextLinkOffsetBlock = (uint32_t)hostHeader.iv_linkAddress + hostSection.iv_offset;
+
+ // Allocate buffer to hold disassembled listing. (Start out with minimum 10k buffer size.)
+ //
+ if (sizeSection>10000)
+ sizeListMax = sizeSection; // Just to use something as an initial guess.
+ else
+ sizeListMax = 10000;
+ disList = (char*)malloc(sizeListMax);
+ if (disList==NULL) {
+ fprintf( stderr, "ERROR : malloc() failed.\n");
+ fprintf( stderr, "\tMore info: %s\n", DIS_ERROR_STRING(g_errorStringsDis, DIS_MEMORY_ERROR));
+ return SBE_XIP_DISASSEMBLER_ERROR;
+ }
+ *disList = '\0'; // Make sure the buffer is NULL terminated (though probably not needed.)
+ sizeList = 0;
+
+ // Create context and point it to image section.
+ //
+ rc = image_inline_context_create( &ctx,
+ nextBlock,
+ sizeSection,
+ nextLinkOffsetBlock,
+ 0);
+ if (rc) {
+ fprintf( stderr, "ERROR : %s (rc=%i)\n",image_inline_error_strings[rc],rc);
+ fprintf( stderr, "\tMore info: %s\n", DIS_ERROR_STRING(g_errorStringsDis, DIS_DISASM_ERROR));
+ return SBE_XIP_DISASSEMBLER_ERROR;
+ }
+
+ while ((uint64_t)nextBlock<(uint64_t)nextSection) {
+
+ // Disassemble sections based on their types and intents.
+ //
+ if (sectionId==SBE_XIP_SECTION_RINGS || sectionId==SBE_XIP_SECTION_DCRINGS) {
+ // Ring section (with a mix of data and code.)
+ // ...use BaseRingLayout structure to decode each ring block.
+ offsetCode = (uint32_t)myRev64(((BaseRingLayout*)nextBlock)->entryOffset);
+ sizeBlock = myRev32(((BaseRingLayout*)nextBlock)->sizeOfThis);
+ // ...determine ring type, either RS4 or Wiggle-flip.
+ if (offsetCode-(myRev32(((BaseRingLayout*)nextBlock)->sizeOfMeta)+3)/4*4>28) {
+ typeRingsSection = 0; // RS4 w/32-byte header.
+ sizeData2 = sizeBlock - offsetCode - ASM_RS4_LAUNCH_BUF_SIZE;
+ }
+ else
+ typeRingsSection = 1; // Wiggle-flip w/24-byte header.
+ // ...get the backPtr and fwdPtr and put at top of disasm listing.
+ backPtr = myRev64(((BaseRingLayout*)nextBlock)->backItemPtr);
+ sbe_xip_read_uint64(i_image,
+ backPtr,
+ &fwdPtr);
+
+ // Calculate RS4 compression efficiency if RS4 rings.
+ if (typeRingsSection==0) {
+ hostRs4Container = (void*)( (uintptr_t)nextBlock +
+ offsetCode + ASM_RS4_LAUNCH_BUF_SIZE );
+ compressedBits = myRev32(((CompressedScanData*)hostRs4Container)->iv_algorithmReserved) * 4;
+ ringLength = myRev32(((CompressedScanData*)hostRs4Container)->iv_length);
+ compressionPct = (double)compressedBits / (double)ringLength * 100.0;
+ }
+
+ //
+ // Map over TOC or do a targeted search of FIXED_TOC to pair backPtr addr
+ // with ring name and override and/or vector position (i.e. multi-chiplet).
+ //
+ sbe_xip_get_section( i_image, SBE_XIP_SECTION_TOC, &hostSection);
+ if (hostSection.iv_offset) {
+ // TOC exists.
+ pairingInfo.address = backPtr;
+ // Search for pairing. First exhaust base position (pos=0), then next, then next, ...
+ for (pairingInfo.vectorpos=0;pairingInfo.vectorpos<32;pairingInfo.vectorpos++) {
+ rc = sbe_xip_map_toc( i_image, pairRingNameAndAddr, (void*)(&pairingInfo));
+ if (rc)
+ break;
+ }
+ if (rc==DIS_RING_NAME_ADDR_MATCH_FAILURE) {
+ fprintf( stderr,"ERROR : Error associated with sbe_xip_map_toc().\n");
+ fprintf( stderr, "\tMore info: %s\n", DIS_ERROR_STRING(g_errorStringsDis, DIS_RING_NAME_ADDR_MATCH_FAILURE));
+ return SBE_XIP_DISASSEMBLER_ERROR;
+ }
+ ringSeqNo++;
+ if (rc==DIS_RING_NAME_ADDR_MATCH_SUCCESS) {
+ bFoundInToc = 1;
+ ringName = pairingInfo.name; // The ring name matched in pairRingNameAndAddr()
+ vectorPos = pairingInfo.vectorpos; // The vector position matched in pairRingNameAndAddr()
+ overRidable = pairingInfo.overridable; // Whether the ring supports on override ring.
+ if (pairingInfo.override) {
+ sizeDisLine = snprintf(lineDis,LISTING_STRING_SIZE,
+ "# ------------------------------\n# %i.\n# ringName = %s (override)\n# vectorPos = %i\n# overRidable = %i\n# backPtr = 0x%08x\n# fwdPtr = 0x%08x\n# Compressed Bits = %u\n# Ring Length Bits = %u\n# Compression = %0.2f%%\n",
+ ringSeqNo, ringName,vectorPos,overRidable,(uint32_t)backPtr,(uint32_t)fwdPtr,compressedBits,ringLength,compressionPct);
+ }
+ else {
+ sizeDisLine = snprintf(lineDis,LISTING_STRING_SIZE,
+ "# ------------------------------\n# %i.\n# ringName = %s (base)\n# vectorPos = %i\n# overRidable = %i\n# backPtr = 0x%08x\n# fwdPtr = 0x%08x\n# Compressed Bits = %u\n# Ring Length Bits = %u\n# Compression = %0.2f%%\n",
+ ringSeqNo,ringName,vectorPos,overRidable,(uint32_t)backPtr,(uint32_t)fwdPtr,compressedBits,ringLength,compressionPct);
+ }
+ }
+ else {
+ sizeDisLine = snprintf(lineDis,LISTING_STRING_SIZE,
+ "# ------------------------------\n# %i.\n# ringName = Not found (but TOC's available)\n# backPtr = 0x%08x\n# fwdPtr = 0x%08x\n",
+ ringSeqNo,(uint32_t)backPtr,(uint32_t)fwdPtr);
+ }
+ }
+ else {
+ // TOC doesn't exist. First try targeted search of MVPD ring names in FIXED_TOC.
+ bFoundInToc = 0; // If we find in fixed_toc, then change to 1.
+ // 2012-11-13: CMO TBD. Try using pairRingNameAndAddr by enabling a sequential
+ // traversing of each of the MVPD lists inside that function. You'll
+ // need to call pairRing manually from right here (or from a
+ // sbe_xip_search_fixed_toc()-like function). Maybe you can add a
+ // 4th arg to pairRing that is zero by default, meaning it is to be
+ // used by xip_map_toc(). But if non-zero, it is to be used in a
+ // traversing manner. Or you could add another member to the
+ // PairingInfo struct to indirectly pass this info to the function.
+ // You'd also need to pass two more arguments to get_vpd_ring_list_
+ // entry() to indicate sequence number and the MVPD keyword.
+ // rc = pairRingNameAndAddr();
+ // if (rc==DIS_RING_NAME_ADDR_MATCH_SUCCESS) {
+ // bFoundInToc = 1;
+ // // Do same as in TOC section above.
+ // break;
+ // }
+ // // OK, so ring name wasn't in TOC nor in FIXED_TOC. That happens if the ring
+ // // is a non-Mvpd ring and the TOC has been removed, such as in an IPL or
+ // // Seeprom image.
+ ringSeqNo++;
+ if (typeRingsSection==0) {
+ // RS4 header, which has override info
+ if (((Rs4RingLayout*)nextBlock)->override==0) {
+ sizeDisLine = snprintf(lineDis,LISTING_STRING_SIZE,
+ "# ------------------------------\n# %i.\n# ringName = Not available (base)\n# backPtr = 0x%08x\n# fwdPtr = 0x%08x\n# Compressed Bits = %u\n# Ring Length Bits = %u\n# Compression = %0.2f%%\n",
+ ringSeqNo,(uint32_t)backPtr,(uint32_t)fwdPtr,compressedBits,ringLength,compressionPct);
+ }
+ else {
+ sizeDisLine = snprintf(lineDis,LISTING_STRING_SIZE,
+ "# ------------------------------\n# %i.\n# ringName = Not available (override)\n# backPtr = 0x%08x\n# fwdPtr = 0x%08x\n# Compressed Bits = %u\n# Ring Length Bits = %u\n# Compression = %0.2f%%\n",
+ ringSeqNo,(uint32_t)backPtr,(uint32_t)fwdPtr,compressedBits,ringLength,compressionPct);
+ }
+ }
+ else {
+ // WF header, which doesn't have override info
+ sizeDisLine = snprintf(lineDis,LISTING_STRING_SIZE,
+ "# ------------------------------\n# %i.\n# ringName and override = Not available\n# backPtr = 0x%08x\n# fwdPtr = 0x%08x\n",
+ ringSeqNo,(uint32_t)backPtr,(uint32_t)fwdPtr);
+ }
+ }
+ sizeList = sizeList + sizeDisLine;
+ disList = strcat(disList,lineDis);
+ }
+ else if ( sectionId==SBE_XIP_SECTION_IPL_TEXT ||
+ sectionId==SBE_XIP_SECTION_TEXT) {
+ // Sections that have only code.
+ offsetCode = 0;
+ sizeBlock = sizeSection;
+ }
+ else {
+ // Sections that have only data.
+ offsetCode = sizeSection;
+ sizeBlock = sizeSection;
+ }
+ sizeData = offsetCode;
+ sizeCode = sizeBlock - offsetCode - sizeData2;
+
+ if (sectionId==SBE_XIP_SECTION_RINGS && bSummary) {
+ //
+ // Summarize rings section.
+
+ if (typeRingsSection==0) { // RS4 header.
+ sizeDisLine = snprintf(lineDis,LISTING_STRING_SIZE,
+ "# ddLevel = 0x%02x\n# override= %i\n# sysPhase= %i\n# Block size= %i\n",
+ myRev32(((Rs4RingLayout*)nextBlock)->ddLevel),
+ ((Rs4RingLayout*)nextBlock)->override,
+ ((Rs4RingLayout*)nextBlock)->sysPhase,
+ sizeBlock);
+ }
+ else { // WF header.
+ if (bFoundInToc) {
+ sizeDisLine = snprintf(lineDis,LISTING_STRING_SIZE,
+ "# override= %i\n# Block size= %i\n",
+ pairingInfo.override, sizeBlock);
+ }
+ else {
+ sizeDisLine = snprintf(lineDis,LISTING_STRING_SIZE,
+ "# override= Not available\n# Block size= %i\n",
+ sizeBlock);
+ }
+ }
+ sizeList = sizeList + sizeDisLine;
+ disList = strcat(disList,lineDis);
+ // Readjust list buffer size, if needed.
+ if (sizeList > sizeListMax-1000) {
+ sizeListMax = 2*sizeListMax;
+ disList = (char*)realloc( (void*)(disList), sizeListMax);
+ }
+
+ }
+ else {
+ //
+ // Do disassembly.
+
+ // ...data disassembly
+ if (sizeData>0) {
+ ctx.options = IMAGE_INLINE_LISTING_MODE | IMAGE_INLINE_DISASSEMBLE_DATA;
+ do {
+ rc = image_inline_disassemble( &ctx, &dis);
+ sizeDisLine = snprintf(lineDis,LISTING_STRING_SIZE,"%s\n",dis.s);
+ sizeList = sizeList + sizeDisLine;
+ disList = strcat(disList,lineDis);
+ if (rc) {
+ rcSet = rcSet | 0x1;
+ sizeDisLine = snprintf(lineDis,LISTING_STRING_SIZE,
+ "WARNING: %s (rc=%i) -> Stopping disasm. Check code and sectionID=%i.\n",
+ image_inline_error_strings[rc],rc,sectionId);
+ sizeList = sizeList + sizeDisLine;
+ disList = strcat(disList,lineDis);
+ }
+ // Readjust list buffer size, if needed.
+ if (sizeList > sizeListMax-1000) {
+ sizeListMax = 2*sizeListMax;
+ disList = (char*)realloc( (void*)(disList), sizeListMax);
+ }
+ } while (rc==0 && ctx.lc<nextLinkOffsetBlock+sizeData);
+ }
+ if (rcSet)
+ rc = 0;
+
+ // ...code disassembly
+ if (sizeCode>0) {
+ ctx.options = IMAGE_INLINE_LISTING_MODE;
+ do {
+ rc = image_inline_disassemble( &ctx, &dis);
+ ctx.options = IMAGE_INLINE_LISTING_MODE;
+ sizeDisLine = snprintf(lineDis,LISTING_STRING_SIZE,"%s\n",dis.s);
+ sizeList = sizeList + sizeDisLine;
+ disList = strcat(disList,lineDis);
+ if (rc && rcCount<100) {
+ rcSet = rcSet | 0x2;
+ rcCount++;
+ if (sectionId==SBE_XIP_SECTION_RINGS) {
+ sizeDisLine = snprintf(lineDis,LISTING_STRING_SIZE,
+ "WARNING: %s (rc=%i) -> Trying data disasm mode. Check code, xyzRingLayout structures and image section.\n",
+ image_inline_error_strings[rc],rc);
+ }
+ else {
+ sizeDisLine = snprintf(lineDis,LISTING_STRING_SIZE,
+ "WARNING: %s (rc=%i) -> Trying data disasm mode.\n",
+ image_inline_error_strings[rc],rc);
+ }
+ sizeList = sizeList + sizeDisLine;
+ disList = strcat(disList,lineDis);
+ ctx.options = IMAGE_INLINE_LISTING_MODE | IMAGE_INLINE_DISASSEMBLE_DATA;
+ rc = 0;
+ }
+ else {
+ if (rc && rcCount>=1000) {
+ fprintf(stderr, "Too many disasm warnings. Check output listing.\n");
+ fprintf( stderr, "\tMore info: %s\n", DIS_ERROR_STRING(g_errorStringsDis, DIS_TOO_MANY_DISASM_WARNINGS));
+ return SBE_XIP_DISASSEMBLER_ERROR;
+ }
+ }
+ // Readjust list buffer size, if needed.
+ if (sizeList > sizeListMax-1000) {
+ sizeListMax = 2*sizeListMax;
+ disList = (char*)realloc( (void*)(disList), sizeListMax);
+ }
+ } while (rc==0 && ctx.lc<nextLinkOffsetBlock+sizeData+sizeCode);
+ }
+ if (rcSet)
+ rc = 0;
+
+ // ...data2 disassembly (only done for rings section if RS4 type.)
+ if (sizeData2>0) {
+ ctx.options = IMAGE_INLINE_LISTING_MODE | IMAGE_INLINE_DISASSEMBLE_DATA;
+ do {
+ rc = image_inline_disassemble( &ctx, &dis);
+ sizeDisLine = snprintf(lineDis,LISTING_STRING_SIZE,"%s\n",dis.s);
+ sizeList = sizeList + sizeDisLine;
+ disList = strcat(disList,lineDis);
+ if (rc) {
+ rcSet = rcSet | 0x4;
+ sizeDisLine = snprintf(lineDis,LISTING_STRING_SIZE,
+ "WARNING: %s (rc=%i) -> Stopping disasm. Check code and sectionID=%i.\n",
+ image_inline_error_strings[rc],rc,sectionId);
+ sizeList = sizeList + sizeDisLine;
+ disList = strcat(disList,lineDis);
+ }
+ // Readjust list buffer size, if needed.
+ if (sizeList > sizeListMax-1000) {
+ sizeListMax = 2*sizeListMax;
+ disList = (char*)realloc( (void*)(disList), sizeListMax);
+ }
+ } while (rc==0 && ctx.lc<nextLinkOffsetBlock+sizeBlock);
+ }
+ if (rcSet)
+ rc = 0;
+
+ } // End of if (bSummary) condition.
+
+ nextBlock = (void*)((uint64_t)nextBlock + (uint64_t)sizeBlock);
+ nextLinkOffsetBlock = nextLinkOffsetBlock + sizeBlock;
+
+ } // End of while(nextBlock...) loop.
+
+ // Adjust final buffer size, add 1 for NULL char and print it.
+ if (disList) {
+ disList = (char*)realloc( (void*)(disList), sizeList+1);
+ fprintf(stdout,"%s\n",disList);
+ free(disList);
+ }
+
+ if (rcSet)
+ fprintf( stderr, "INFO : There were some hickups: %s\n", DIS_ERROR_STRING(g_errorStringsDis, DIS_DISASM_TROUBLES));
+
+ return 0;
+
+}
+#endif
+
+// open() and mmap() the file
+
+void
+openAndMap(const char* i_fileName, int i_writable, int* o_fd, void** o_image, const uint32_t i_maskIgnores)
+{
+ int rc, openMode, mmapProt, mmapShared;
+ struct stat buf;
+
+ if (i_writable) {
+ openMode = O_RDWR;
+ mmapProt = PROT_READ | PROT_WRITE;
+ mmapShared = MAP_SHARED;
+ } else {
+ openMode = O_RDONLY;
+ mmapProt = PROT_READ;
+ mmapShared = MAP_PRIVATE;
+ }
+
+ *o_fd = open(i_fileName, openMode);
+ if (*o_fd < 0) {
+ perror("open() of the image failed : ");
+ exit(1);
+ }
+
+ rc = fstat(*o_fd, &buf);
+ if (rc) {
+ perror("fstat() of the image failed : ");
+ exit(1);
+ }
+ g_imageSize = buf.st_size;
+
+ *o_image = mmap(0, g_imageSize, mmapProt, mmapShared, *o_fd, 0);
+ if (*o_image == MAP_FAILED) {
+ perror("mmap() of the image failed : ");
+ exit(1);
+ }
+
+ if ( !(i_maskIgnores & SBE_XIP_IGNORE_ALL) ) {
+ rc = sbe_xip_validate2(*o_image, g_imageSize, i_maskIgnores);
+ if (rc) {
+ fprintf(stderr, "sbe_xip_validate2() failed : %s\n",
+ SBE_XIP_ERROR_STRING(g_errorStrings, rc));
+ exit(1);
+ }
+ }
+
+}
+
+
+static inline void
+openAndMapWritable(const char* i_imageFile, int* o_fd, void** o_image, const uint32_t i_maskIgnores)
+{
+ openAndMap(i_imageFile, 1, o_fd, o_image, i_maskIgnores);
+}
+
+
+static inline void
+openAndMapReadOnly(const char* i_imageFile, int* o_fd, void** o_image, const uint32_t i_maskIgnores)
+{
+ openAndMap(i_imageFile, 0, o_fd, o_image, i_maskIgnores);
+}
+
+
+// Parse and execute a pre-tokenized command
+
+void
+command(const char* i_imageFile, const int i_argc, const char** i_argv, const uint32_t i_maskIgnores)
+{
+ void* image;
+ int fd, rc = 0;
+
+ if (strcmp(i_argv[0], "normalize") == 0) {
+
+ openAndMapWritable(i_imageFile, &fd, &image, i_maskIgnores);
+ rc = normalize(image, i_argc - 1, &(i_argv[1]), i_maskIgnores);
+
+ } else if (strcmp(i_argv[0], "set") == 0) {
+
+ openAndMapWritable(i_imageFile, &fd, &image, i_maskIgnores);
+ rc = set(image, i_argc - 1, &(i_argv[1]), 0);
+
+ } else if (strcmp(i_argv[0], "setv") == 0) {
+
+ openAndMapWritable(i_imageFile, &fd, &image, i_maskIgnores);
+ rc = set(image, i_argc - 1, &(i_argv[1]), 1);
+
+ } else if (strcmp(i_argv[0], "get") == 0) {
+
+ openAndMapReadOnly(i_imageFile, &fd, &image, i_maskIgnores);
+ rc = get(image, i_argc - 1, &(i_argv[1]), 0);
+
+ } else if (strcmp(i_argv[0], "getv") == 0) {
+
+ openAndMapReadOnly(i_imageFile, &fd, &image, i_maskIgnores);
+ rc = get(image, i_argc - 1, &(i_argv[1]), 1);
+
+ } else if (strcmp(i_argv[0], "report") == 0) {
+
+ openAndMapReadOnly(i_imageFile, &fd, &image, i_maskIgnores);
+ rc = report(image, i_argc - 1, &(i_argv[1]));
+
+ } else if (strcmp(i_argv[0], "append") == 0) {
+
+ openAndMapWritable(i_imageFile, &fd, &image, i_maskIgnores);
+ rc = append(i_imageFile, fd, image, i_argc - 1, &(i_argv[1]));
+
+ } else if (strcmp(i_argv[0], "delete") == 0) {
+
+ openAndMapWritable(i_imageFile, &fd, &image, i_maskIgnores);
+ rc = deleteSection(i_imageFile, fd, image, i_argc - 1,
+ &(i_argv[1]));
+
+ } else if (strcmp(i_argv[0], "dis") == 0) {
+
+ //openAndMapReadOnly(i_imageFile, &fd, &image, i_maskIgnores);
+ //rc = disassembleSection(image, i_argc - 1, &(i_argv[1]));
+ fprintf(stderr, "not supported\n");
+ exit(1);
+
+
+ } else if (strcmp(i_argv[0], "TEST") == 0) {
+
+ openAndMapWritable(i_imageFile, &fd, &image, i_maskIgnores);
+ rc = TEST(image, i_argc - 1, &(i_argv[1]));
+
+ } else {
+ fprintf(stderr, g_usage);
+ exit(1);
+ }
+ if (rc) {
+ fprintf(stderr, "Command failed : %s\n",
+ SBE_XIP_ERROR_STRING(g_errorStrings, rc));
+ exit(1);
+ }
+}
+
+
+// Open, map and validate the image, then parse and execute the command. The
+// image is memory-mapped read/write, i.e, it may be modified in-place.
+// Commands that modify the size of the image will close and recreate the
+// file.
+
+int
+main(int argc, const char** argv)
+{
+ uint8_t argcMin, idxArgvFlagsStart;
+ uint8_t numFlags=0, idxArgv, bMoreFlags;
+ uint32_t maskIgnores=0;
+
+ argcMin = 3;
+ idxArgvFlagsStart = argcMin - 1; // -i flags must start after image file name.
+
+ numFlags = 0;
+ bMoreFlags = 1;
+ do {
+ idxArgv = idxArgvFlagsStart + numFlags;
+ if (idxArgv <= (argc-1)) {
+ if (strncmp(argv[idxArgv], "-i", 1) == 0) {
+ numFlags++;
+ bMoreFlags = 1;
+ if (strncmp(argv[idxArgv], "-ifs", 4) == 0) {
+ maskIgnores = maskIgnores | SBE_XIP_IGNORE_FILE_SIZE;
+ }
+ else
+ if (strncmp(argv[idxArgv], "-iv", 3) == 0) {
+ maskIgnores = maskIgnores | SBE_XIP_IGNORE_ALL;
+ }
+ else {
+ fprintf(stderr, g_usage);
+ fprintf(stderr, "\n");
+ fprintf(stderr,"argv[%i]=%s is an unsupported flag.",idxArgv,argv[idxArgv]);
+ fprintf(stderr,"See top of above help menu for supported flags.\n");
+ exit(1);
+ }
+ }
+ else
+ bMoreFlags = 0;
+ }
+ else {
+ bMoreFlags = 0;
+ break;
+ }
+ } while (bMoreFlags);
+
+ if ((argc < (argcMin+numFlags)) ||
+ (strncmp(argv[1], "-h", 2) == 0) ||
+ (strncmp(argv[1], "--h", 3) == 0) ) {
+ fprintf(stderr, g_usage);
+ exit(1);
+ }
+
+ command(argv[1], argc - idxArgv, &(argv[idxArgv]), maskIgnores);
+
+ return 0;
+}
OpenPOWER on IntegriCloud