Create Dump Header for IBM Systems

Creating a dump header for IBM systems involves adding a new script to
generate these headers specifically for IBM. This change only impacts
IBM-specific systems and does not alter the existing dump package format
for other systems. For IBM systems, the generated header will be
appended to the dump, ensuring compatibility with the existing dump
process. Non-IBM systems will continue to use the current dump format
without any modifications. This enhancement maintains the integrity and
format of dumps across different systems while providing a consistent
and specific dump format for IBM systems.

Change-Id: Id6540c90d7519cdd3a96af691a32d906c5e5b63e
Signed-off-by: Dhruvaraj Subhashchandran <dhruvaraj@in.ibm.com>
diff --git a/.shellcheck-ignore b/.shellcheck-ignore
new file mode 100644
index 0000000..fccc1d9
--- /dev/null
+++ b/.shellcheck-ignore
@@ -0,0 +1 @@
+dump/tools/common/include/gendumpheader
\ No newline at end of file
diff --git a/dump/tools/common/include/gendumpheader b/dump/tools/common/include/gendumpheader
new file mode 100644
index 0000000..9c92e9f
--- /dev/null
+++ b/dump/tools/common/include/gendumpheader
@@ -0,0 +1,549 @@
+#!/bin/bash
+#
+#Header for BMC DUMP
+#This script will create header file only for IBM systems.
+#This script will generate generic IBM dump header format.
+#
+#Note: The dump header will be imposed on the dump file i.e
+#<dump name>.tar.xz/gz only on IBM specific systems, user needs to
+#separate out the header before extracting the dump.
+#
+
+#Constants
+declare -rx DUMP_HEADER_ENTRY_SIZE='516'
+declare -rx SIZE_4='4'
+declare -rx SIZE_8='8'
+declare -rx SIZE_12='12'
+declare -rx SIZE_32='32'
+#Dump Summary size without header
+declare -rx DUMP_SUMMARY_SIZE='1024'
+declare -rx HW_DUMP='00'
+declare -rx HB_DUMP='20'
+declare -rx SBE_DUMP='30'
+declare -rx OP_DUMP="opdump"
+declare -rx INVENTORY_MANAGER='xyz.openbmc_project.Inventory.Manager'
+declare -rx INVENTORY_PATH='/xyz/openbmc_project/inventory/system'
+declare -rx INVENTORY_ASSET_INT='xyz.openbmc_project.Inventory.Decorator.Asset'
+declare -rx INVENTORY_BMC_BOARD='/xyz/openbmc_project/inventory/system/chassis/motherboard'
+declare -rx PHOSPHOR_LOGGING='xyz.openbmc_project.Logging'
+declare -rx PEL_ENTRY='org.open_power.Logging.PEL.Entry'
+declare -rx PEL_ID_PROP='PlatformLogID'
+
+#Variables
+declare -x modelNo
+modelNo=$(busctl get-property $INVENTORY_MANAGER $INVENTORY_PATH \
+    $INVENTORY_ASSET_INT Model | cut -d " " -f 2 | sed "s/^\(\"\)\(.*\)\1\$/\2/g")
+#Variables
+declare -x serialNo
+serialNo=$(busctl get-property $INVENTORY_MANAGER $INVENTORY_PATH \
+    $INVENTORY_ASSET_INT SerialNumber | cut -d " " -f 2 | sed "s/^\(\"\)\(.*\)\1\$/\2/g")
+declare -x dDay
+dDay=$(date -d @"$EPOCHTIME" +'%Y%m%d%H%M%S')
+declare -x bmcSerialNo
+bmcSerialNo=$(busctl call $INVENTORY_MANAGER $INVENTORY_BMC_BOARD \
+        org.freedesktop.DBus.Properties Get ss $INVENTORY_ASSET_INT \
+    SerialNumber | cut -d " " -f 3 | sed "s/^\(\"\)\(.*\)\1\$/\2/g")
+
+#Function to add NULL
+function add_null() {
+    local a=$1
+    printf '%*s' $a | tr ' ' "\0" >> $FILE
+}
+
+#Function to is to convert the EPOCHTIME collected
+#from dreport into hex values and write the same in
+#header.
+function dump_time() {
+    x=${#dDay}
+    msize=`expr $x / 2`
+    msize=`expr $SIZE_8 - $msize`
+    for ((i=0;i<$x;i+=2));
+    do
+        printf \\x${dDay:$i:2} >> $FILE
+    done
+    add_null $msize
+}
+
+#Function to fetch the size of the dump
+function dump_size() {
+    #Adding 516 bytes as the total dump size is dump tar size
+    #plus the dump header entry in this case
+    #dump_header and dump_entry
+    # shellcheck disable=SC2154 # name_dir comes from elsewhere.
+    dumpSize=$(stat -c %s "$name_dir.bin")
+    sizeDump=$(( dumpSize + DUMP_HEADER_ENTRY_SIZE ))
+    printf -v hex "%x" "$sizeDump"
+    x=${#hex}
+    if [ $(($x % 2)) -eq 1 ]; then
+        hex=0$hex
+        x=${#hex}
+    fi
+    msize=`expr $x / 2`
+    msize=`expr $SIZE_8 - $msize`
+    add_null $msize
+    for ((i=0;i<$x;i+=2));
+    do
+        printf \\x${hex:$i:2} >> $FILE
+    done
+}
+
+#Function to set dump id to 8 bytes format
+function get_dump_id() {
+    # shellcheck disable=SC2154
+    size=${#dump_id}
+    if [ "$1" == "$OP_DUMP" ]; then
+        nulltoadd=$(( SIZE_4 - size / 2 - size % 2 ))
+        add_null "$nulltoadd"
+        for ((i=0;i<size;i+=2));
+        do
+            # shellcheck disable=SC2059
+            printf "\\x${dump_id:$i:2}" >> "$FILE"
+        done
+    else
+        nulltoadd=$(( SIZE_8 - size ))
+        printf '%*s' "$nulltoadd" | tr ' ' "0" >> "$FILE"
+        printf "%s" "$dump_id" >> "$FILE"
+    fi
+}
+
+#Function to get the bmc serial number
+function getbmc_serial() {
+    x=${#bmcSerialNo}
+    nulltoadd=`expr $SIZE_12 - $x`
+    printf $bmcSerialNo >> $FILE
+    printf '%*s' $nulltoadd | tr ' ' "0" >> $FILE
+}
+
+#Function to fetch the hostname
+function system_name() {
+    name=$(hostname)
+    len=${#name}
+    nulltoadd=$(( SIZE_32 - len ))
+    printf "%s" "$name" >> "$FILE"
+    add_null "$nulltoadd"
+}
+
+#Function to get the errorlog ID
+function get_eid() {
+    # shellcheck disable=SC2154 # dump_type comes from elsewhere
+    if [ "$dump_type" = "$OP_DUMP" ]; then
+        # shellcheck disable=SC2154 # elog_id comes from elsewhere
+        x=${#elog_id}
+        if [ "$x" = 8 ]; then
+            msize=$(( x / 2 ))
+            msize=$(( SIZE_4 - msize ))
+            for ((i=0;i<x;i+=2));
+            do
+                printf "\\x${elog_id:$i:2}" >> "$FILE"
+            done
+            add_null "$msize"
+        else
+            add_null 4
+        fi
+    else
+        if ! { [[ $dump_type = "$TYPE_ELOG" ]] || \
+                [[ $dump_type = "$TYPE_CHECKSTOP" ]]; }; then
+            x=${#elog_id}
+            if [ "$x" = 8 ]; then
+                for ((i=0;i<x;i+=2));
+                do
+                    printf "\\x${elog_id:$i:2}" >> "$FILE"
+                done
+            else
+                add_null 4
+            fi
+        else
+            strpelid=$(busctl get-property $PHOSPHOR_LOGGING \
+                $optional_path $PEL_ENTRY $PEL_ID_PROP | cut -d " " -f 2)
+            decpelid=$(expr "$strpelid" + 0)
+            hexpelid=$(printf "%x" "$decpelid")
+            x=${#hexpelid}
+            if [ "$x" = 8 ]; then
+                for ((i=0;i<x;i+=2));
+                do
+                    printf "\\x${hexpelid:$i:2}" >> "$FILE"
+                done
+            else
+                add_null 4
+            fi
+        fi
+    fi
+}
+
+#Function to get the tar size of the dump
+function tar_size() {
+    printf -v hex "%x" "$size_dump"
+    x=${#hex}
+    if [ $((x % 2)) -eq 1 ]; then
+        hex=0$hex
+        x=${#hex}
+    fi
+    msize=$(( x / 2 ))
+    msize=$(( SIZE_4 - msize ))
+    add_null "$msize"
+    for ((i=0;i<x;i+=2));
+    do
+        # shellcheck disable=SC2059 # using 'hex' as a variable is safe here.
+        printf "\\x${hex:$i:2}" >> "$FILE"
+    done
+}
+
+#Function will get the total size of the dump without header
+# i.e. Dump summary size i.e. 1024 bytes + the tar file size
+function total_size() {
+    size_dump=$(( size_dump + DUMP_SUMMARY_SIZE ))
+    printf -v hex "%x" "$size_dump"
+    x=${#hex}
+    if [ $((x % 2)) -eq 1 ]; then
+        hex=0$hex
+        x=${#hex}
+    fi
+    msize=$(( x / 2 ))
+    msize=$(( SIZE_8 - msize ))
+    add_null "$msize"
+    for ((i=0;i<x;i+=2));
+    do
+        # shellcheck disable=SC2059 # using 'hex' as a variable is safe here.
+        printf "\\x${hex:$i:2}" >> "$FILE"
+    done
+}
+
+#Function to populate content type based on dump type
+function content_type() {
+    type="00000000"
+    # content type:
+    # Hostboot dump = "20"
+    # Hardware dump = "00"
+    # SBE dump = "30"
+    if [ "$dump_content_type" = "$HB_DUMP" ]; then
+        type="00000200"
+    elif [ "$dump_content_type" = "$HW_DUMP" ]; then
+        type="40000000"
+    elif [ "$dump_content_type" = "$SBE_DUMP" ]; then
+        type="02000000"
+    fi
+    x=${#type}
+    for ((i=0;i<$x;i+=2));
+    do
+        # shellcheck disable=SC2059 # using 'type' as a variable is safe here.
+        printf "\\x${type:$i:2}" >> "$FILE"
+    done
+}
+
+# @brief Fetching model number and serial number property from inventory
+#  If the busctl command fails, populating the model and serial number
+#  with default value i.e. 0
+function get_bmc_model_serial_number() {
+    modelNo=$(busctl get-property $INVENTORY_MANAGER $INVENTORY_PATH \
+        $INVENTORY_ASSET_INT Model | cut -d " " -f 2 | sed "s/^\(\"\)\(.*\)\1\$/\2/g")
+
+    if [ -z "$modelNo" ]; then
+        modelNo="00000000"
+    fi
+
+    bmcSerialNo=$(busctl call $INVENTORY_MANAGER $INVENTORY_BMC_BOARD \
+            org.freedesktop.DBus.Properties Get ss $INVENTORY_ASSET_INT \
+        SerialNumber | cut -d " " -f 3 | sed "s/^\(\"\)\(.*\)\1\$/\2/g")
+
+    if [ -z "$bmcSerialNo" ]; then
+        bmcSerialNo="000000000000"
+    fi
+}
+
+#Function to add virtual file directory entry, consists of below entries
+####################FORMAT################
+#Name              Size(bytes)  Value
+#Entry Header      8            FILE
+#Entry Size        2            0x0040
+#Reserved          10           NULL
+#Entry Type        2            0x0001
+#File Name Prefix  2            0x000F
+#Dump File Type    7            BMCDUMP/SYSDUMP/NAGDUMP
+#Separator         1            .
+#System Serial No  7            System serial number fetched from system
+#Dump Identifier   8            Dump Identifier value fetched from dump
+#Separator         1            .
+#Time stamp        14           Form should be yyyymmddhhmmss
+#Null Terminator   1            0x00
+function dump_file_entry() {
+    printf "FILE    " >> $FILE
+    add_null 1
+    printf '\x40' >> $FILE #Virtual file directory entry size
+    add_null 11
+    printf '\x01' >> $FILE
+    add_null 1
+    printf '\x0F' >> "$FILE"
+    if [ "$dump_type" = "$OP_DUMP" ]; then
+        printf "SYSDUMP.%s." "$serialNo" >> "$FILE"
+    else
+        printf "%s.%s." "$header_dump_name" "$serialNo" >> "$FILE"
+    fi
+    get_dump_id
+    printf "." >> $FILE
+    printf $dDay >> $FILE  #UTC time stamp
+    add_null 1
+}
+
+#Function section directory entry, consists of below entries
+####################FORMAT################
+#Name              Size(bytes)  Value
+#Entry Header      8            SECTION
+#Entry Size        2            0x0030
+#Section Priority  2            0x0000
+#Reserved          4            NULL
+#Entry Flags       4            0x00000001
+#Entry Types       2            0x0002
+#Reserved          2            NULL
+#Dump Size         8            Dump size in hex + dump header
+#Optional Section  16           BMCDUMP/NAGDUMP/DUMP SUMMARY
+function dump_section_entry() {
+    printf "SECTION " >> $FILE
+    add_null 1
+    printf '\x30' >> "$FILE" #Section entry size
+    add_null 9
+    if [ "$dump_type" = "$OP_DUMP" ]; then
+        add_null 1
+    else
+        printf '\x01' >> "$FILE"
+    fi
+    add_null 1
+    printf '\x02' >> "$FILE"
+    add_null 2
+    if [ "$dump_type" = "$OP_DUMP" ]; then
+        add_null 6
+        printf '\x04' >> "$FILE"
+        add_null 1
+        printf "DUMP SUMMARY" >> "$FILE"
+        add_null 4
+    else
+        dump_size    #Dump size
+        printf "%s" "$header_dump_name" >> "$FILE"
+        add_null 9
+    fi
+}
+
+#Function to add dump header, consists of below entries
+####################FORMAT################
+#Name              Size(bytes)  Value
+#Dump type         8            BMC/NAG DUMP
+#Dump Request time 8            Dump request time stamp (in BCD)
+#Dump Identifier   4            Dump identifer fetched from dump
+#Dump version      2            0x0210
+#Dump header       2            0x200
+#Total dump size   8            Dump size + dump header
+#Panel function    32           System model, feature, type and IPL mode
+#System Name       32           System Name (in ASCII)
+#Serial number     7            System serial number
+#Reserved          1            NULL
+#PLID              4            Comes from errorlog
+#File Header Size  2            0x70
+#Dump SRC Size     2            Dump SRC Size. Currently NULL
+#DUMP SRC          320          DUMP SRC. Currently NULL
+#Dump Req Type     4            Dump requester user interface type.
+#Dump Req ID       32           Dump requester user interface ID
+#Dump Req user ID  32           Dump requester user ID.
+#
+#TODO: Github issue #2639, to populate the unpopulated elements.
+#Note: Unpopulated elements are listed below are set as NULL
+#PLID
+#SRC size
+#SRC dump
+#Dump requestor type
+#Dump Req ID
+#Dump Req user ID
+function dump_header() {
+    if [ $dump_type = "$TYPE_FAULTDATA" ]; then
+        printf "FLT DUMP" >> $FILE
+    else
+        printf "BMC DUMP" >> $FILE
+    fi
+    dump_time
+    add_null 4 #Dump Identifier
+    printf '\x02' >> $FILE #Dump version 0x0210
+    printf '\x10' >> $FILE
+    printf '\x02' >> $FILE #Dump header size 0x0200
+    add_null 1
+    dump_size  #dump size
+    printf "$modelNo" >> "$FILE"
+    add_null 24
+    printf "Server-%s-SN%s" "$modelNo" "$serialNo" >> "$FILE"
+    add_null 7
+    printf "$serialNo" >> "$FILE"
+    add_null 1
+    get_eid
+    add_null 1
+    printf '\x70' >> "$FILE" #File header size
+    add_null 2 # SRC size
+    add_null 320 # SRC dump
+    getbmc_serial
+    add_null 68 # Dump requester details
+}
+
+#Function to add Dump entry, consists of below entries
+####################FORMAT################
+#Name               Size(bytes)  Value
+#Dump Entry Version 1            0x01
+#BMC Dump Valid     1            0x01
+#No of Dump Entry   2            Number of Dump Entry
+#
+function dump_entry() {
+    printf '\x01' >> $FILE #Dump entry version
+    printf '\x01' >> $FILE #Dump valid
+    add_null 1
+    printf '\x10' >> $FILE #Dump entry
+}
+
+#Function to Hardware Dump Section
+####################FORMAT##################
+#Name            Size(bytes)    Value
+#HWDumpHeader      8            SECTION
+#HWDumpEntrySize   2            0x0030
+#HWDumpPriority    2            0x02
+#reserve6          4            NULL
+#HWDumpEntryFlag   4            0x0001
+#HWDumpEntryType   2            0x02
+#reserve7          2            NULL
+#reserve7a         4            NULL
+#HWDumpSize        4            NULL
+#HWDumpName[16]    16           HARDWARE DATA
+function hw_dump_section() {
+    printf "SECTION " >> "$FILE"
+    add_null 1
+    printf '\x30' >> "$FILE" #Section entry size
+    add_null 1
+    printf '\x02' >> "$FILE"
+    add_null 7
+    printf '\x00' >> "$FILE"
+    add_null 1
+    printf '\x02' >> "$FILE"
+    add_null 6
+    tar_size
+    printf "HARDWARE DATA" >> "$FILE"
+    add_null 3
+}
+
+#Function to Mainstore Dump Section
+######################FORMAT###################
+#Name                Size(in bytes)   Value
+#MainstoreHeader         8            SECTION
+#MainstoreEntrySize      2            0x30
+#MainstorePriority       2            0x02
+#reserve8                4            NULL
+#MainstoreEntryFlag      4            NULL
+#MainstoreEntryType      2            0x01
+#reserve9                2            NULL
+#MainstoreSize           8            NULL
+#MainstoreName           16           HYPERVISOR DATA
+function mainstore_dump_section() {
+    printf "SECTION " >> "$FILE"
+    add_null 1
+    printf '\x30' >> "$FILE" #Section entry size
+    add_null 1
+    printf '\x02' >> "$FILE"
+    add_null 7
+    printf '\x01' >> "$FILE"
+    add_null 1
+    printf '\x02' >> "$FILE"
+    add_null 10
+    printf "HYPERVISOR DATA" >> "$FILE"
+    add_null 1
+}
+
+#Function for platform system dump header
+######################FORMAT##################
+#Name                Size(in bytes)   Value
+#eyeCatcher              8            SYS DUMP
+#requestTimestamp        8            BCD time
+#dumpIdentifier          4
+#dumpVersion             2
+#headerSize              2
+#totalDumpSize           8
+#machineInfo             32
+#systemName              32
+#systemSerialNumber      7
+#Dump Creator BMC        1
+#eventLogId              4
+#fileHeaderSize          2
+####################DATA NOT AVAIABLE##########
+#srcSize                 2
+#dumpSrc                 332
+#toolType                4
+#clientId                32
+#userId                  32
+#systemDumpFlags         2
+#hardwareErrorFlags      2
+#processorChipEcid       2
+#hardwareObjectModel     1
+#chUnused                1
+#cecMemoryErrorFlags     8
+#memoryDumpStartTime     8
+#memoryDumpCompleteTime  8
+#hypVerRelMod            8
+#Reserved4HysrInfo       2
+#hypMode                 1
+#hypDumpContentPolicy    1
+#Reserved4HWDInfo        2
+#hardwareNodalCount      2
+#hardwareDumpTableSize   4
+#hardwareDumpDataSize    4
+#totalHardwareDumpDataSize   4
+#mdrtTableSize           4
+#mdrtTableAddress        8
+#memoryDumpDataSize      8
+#hypModLoadMapTime       8
+#hardwareCollectionEndTime   8
+#contentType             4
+#failingUnitId           4
+#failingCappChipId       2
+#failingCappUnitId       1
+#reserve02               5
+#hypHRMOR                8
+#hypNACAAddress          8
+#hardwareCollectionStartTime  8
+#mdstTableSize           4
+#payloadState            4
+#creator BMC             1
+#reservedForCreator      169
+function plat_dump_header() {
+    printf "SYS DUMP" >> "$FILE"
+    dump_time
+    get_dump_id "$OP_DUMP"   #Dump identifier
+    printf '\x02' >> "$FILE"
+    printf '\x21' >> "$FILE" #Need to cross check
+    printf '\x04' >> "$FILE" #Dump header size 0x0400
+    add_null 1
+    total_size
+    printf "%s" "$modelNo" >> "$FILE"
+    add_null 24
+    system_name
+    printf "%s" "$serialNo" >> "$FILE"
+    printf '\x01' >> "$FILE"   #Dump Creator BMC
+    get_eid
+    add_null 1
+    printf '\xd0' >> "$FILE" #File Header size
+    add_null 498
+    content_type # 4 bytes
+    add_null 44
+    printf '\x01' >> "$FILE"  # BMC indicator
+    add_null 367
+}
+
+
+#main function
+function gen_header_package() {
+    dump_file_entry
+    dump_section_entry
+    if [ "$dump_type" = "$OP_DUMP" ]; then
+        hw_dump_section
+        mainstore_dump_section
+        plat_dump_header
+    else
+        dump_header
+        dump_entry
+    fi
+}
+
+get_bmc_model_serial_number
+
+#Run gen_header_package
+gen_header_package
\ No newline at end of file
diff --git a/dump/tools/common/include/meson.build b/dump/tools/common/include/meson.build
new file mode 100644
index 0000000..449a172
--- /dev/null
+++ b/dump/tools/common/include/meson.build
@@ -0,0 +1 @@
+include_scripts += meson.current_source_dir() / 'gendumpheader'
\ No newline at end of file