| #!/bin/bash | 
 | # shellcheck disable=SC2034  # Variable is used elsewhere | 
 |  | 
 | help=$(cat << EOF | 
 |         opdreport creates an archive consisting of the following: | 
 |                 * host dump files and header applied on top of it | 
 |         The type parameter controls the content of the data. The generated | 
 |         archive is stored in the user specified location. | 
 |  | 
 | usage: opdreport [OPTION] | 
 |  | 
 | Options: | 
 |         -n, --name <name>     Name to be used for the archive. | 
 |                               Default name format | 
 |                               SYSDUMP.<serial number>.<dump_id>.<time> | 
 |                               Optional parameter. | 
 |         -d, --dir <directory> Archive directory to copy the compressed report. | 
 |                               Default output directory is current working | 
 |                               directory. Optional parameter. | 
 |         -i, --dumpid <id>     Dump identifier to associate with the archive. | 
 |                               Identifiers include numeric characters. | 
 |                               Default dump identifier is 0 | 
 |         -s, --size <size>     Maximum allowed size (in KB) of the archive. | 
 |                               Report will be truncated if size exceeds | 
 |                               this limit. Default size is unlimited. | 
 |         -f, --failingunit     The id of the failed unit | 
 |         -e, --eid             Error log associated with the failure | 
 |         -t, --type            Type of the dump to be collected | 
 |                               1  -  Hardware dump | 
 |                               3  -  Performance dump | 
 |                               5  -  Hostboot dump | 
 |                               10 -  SBE Dump | 
 |         -h, --help            Display this help and exit. | 
 | EOF | 
 | ) | 
 |  | 
 | # Constants | 
 | readonly OP_DUMP="opdump" | 
 | readonly DREPORT_SOURCE="/usr/share/dreport.d" | 
 | readonly TRUE=1 | 
 | readonly FALSE=0 | 
 | readonly TIME_STAMP="date -u" | 
 | readonly UNLIMITED="unlimited" | 
 | readonly DREPORT_INCLUDE="$DREPORT_SOURCE/include.d" | 
 | readonly INVENTORY_MANAGER='xyz.openbmc_project.Inventory.Manager' | 
 | readonly INVENTORY_PATH='/xyz/openbmc_project/inventory/system' | 
 | readonly INVENTORY_ASSET_INT='xyz.openbmc_project.Inventory.Decorator.Asset' | 
 | readonly INVENTORY_BMC_BOARD='/xyz/openbmc_project/inventory/system/chassis/motherboard' | 
 | readonly HEADER_EXTENSION="$DREPORT_INCLUDE/gendumpheader" | 
 | readonly FILE_SCRIPT="$DREPORT_SOURCE/include.d/gendumpinfo" | 
 |  | 
 | # Error Codes | 
 | readonly SUCCESS=0 | 
 | readonly INTERNAL_FAILURE=1 | 
 | readonly RESOURCE_UNAVAILABLE=2 | 
 |  | 
 | # Variables | 
 | declare -x dump_type="$OP_DUMP" | 
 | declare -x dump_sbe_type=100 | 
 | declare -x size_dump="" | 
 | declare -x elog_id="00000000" | 
 | declare -x EPOCHTIME | 
 | EPOCHTIME=$(date +"%s") | 
 | declare -x name="" | 
 | declare -x dump_dir="/tmp" | 
 | declare -x dump_id="00000000" | 
 | declare -x dump_size="unlimited" | 
 | declare -x content_path="" | 
 | declare -x name_dir="" | 
 | declare -x serialNo="0000000" | 
 | declare -x dDay | 
 | dDay=$(date -d @"$EPOCHTIME" +'%Y%m%d%H%M%S') | 
 | declare -x dump_content_type="" | 
 | declare -x FILE="" | 
 |  | 
 | # @brief Get serial number property from inventory | 
 | function fetch_serial_number() { | 
 |     serialNo=$(busctl get-property "$INVENTORY_MANAGER" "$INVENTORY_PATH" \ | 
 |             "$INVENTORY_ASSET_INT" SerialNumber | cut -d " " -f 2 | \ | 
 |         sed 's/^"\(.*\)"$/\1/') | 
 |  | 
 |     if [ -z "$serialNo" ]; then | 
 |         serialNo="0000000" | 
 |     fi | 
 | } | 
 |  | 
 | # @brief Check the validity of user inputs and initialize global variables | 
 | function initialize() { | 
 |     # shellcheck disable=SC2154 # name comes from elsewhere | 
 |     if [ -z "$name" ]; then | 
 |         name="SYSDUMP" | 
 |     fi | 
 |     fetch_serial_number | 
 |     # shellcheck disable=SC2154 # dump_id comes from elsewhere | 
 |     name="${name}.${serialNo}.${dump_id}.${dDay}" | 
 |  | 
 |     if [ -z "$dump_sbe_type" ]; then | 
 |         echo "Error: Dump type is not provided." | 
 |         return "$RESOURCE_UNAVAILABLE" | 
 |     fi | 
 |  | 
 |     if [ -z "$dump_dir" ]; then | 
 |         dump_dir=$PWD | 
 |     fi | 
 |  | 
 |     if [[ "$dump_size" =~ ^[0-9]+$ ]]; then | 
 |         dump_size=$((dump_size * 1024)) | 
 |     else | 
 |         dump_size=$UNLIMITED | 
 |     fi | 
 |  | 
 |     return "$SUCCESS" | 
 | } | 
 |  | 
 | # @brief Collect the dump | 
 | function collect() { | 
 |     content_path="/tmp/dump_${dump_id}_${EPOCHTIME}" | 
 |     dump_outpath="$content_path/plat_dump" | 
 |     if ! mkdir -p "$dump_outpath"; then | 
 |         echo "Could not create the destination directory $dump_outpath" | 
 |         return "$INTERNAL_FAILURE" | 
 |     fi | 
 |  | 
 |     dump-collect --type "$dump_sbe_type" --id "0x$dump_id" \ | 
 |         --failingunit "$failing_unit" --path "$dump_outpath" | 
 | } | 
 |  | 
 | # @brief Package the dump and transfer to dump location | 
 | function package() { | 
 |     FILE="/tmp/dumpheader_${dump_id}_${EPOCHTIME}" | 
 |     if ! mkdir -p "$dump_dir"; then | 
 |         echo "Could not create the destination directory $dump_dir" | 
 |         dump_dir="/tmp" | 
 |     fi | 
 |  | 
 |     cd "$content_path" || exit "$INTERNAL_FAILURE" | 
 |  | 
 |     dump_content_type=${dump_id:0:2} | 
 |     "$FILE_SCRIPT" | 
 |     elog_id=$eid | 
 |  | 
 |     if ! tar -cvzf "$name" plat_dump/*Sbe* info.yaml; then | 
 |         echo "$($TIME_STAMP)" "Could not create the compressed tar file" | 
 |         return "$INTERNAL_FAILURE" | 
 |     fi | 
 |  | 
 |     size_dump=$(stat -c %s "$name") | 
 |  | 
 |     if [ "$dump_size" != "$UNLIMITED" ] && \ | 
 |         [ "$size_dump" -gt "$dump_size" ]; then | 
 |         rm "$name" | 
 |         return "$RESOURCE_UNAVAILABLE" | 
 |     fi | 
 |  | 
 |     echo "Adding Dump Header: $HEADER_EXTENSION" | 
 |     "$HEADER_EXTENSION" | 
 |  | 
 |     if ! tee -a "$FILE" < "$name" > /dev/null; then | 
 |         echo "$($TIME_STAMP)" "Could not create the compressed file" | 
 |         rm -rf "$name" "$FILE" | 
 |         return "$INTERNAL_FAILURE" | 
 |     fi | 
 |  | 
 |     if ! mv "$FILE" "$name"; then | 
 |         echo "$($TIME_STAMP)" "Could not create the compressed file" | 
 |         rm -rf "$name" "$FILE" | 
 |         return "$INTERNAL_FAILURE" | 
 |     fi | 
 |  | 
 |     mv "$name" "$dump_dir" | 
 |  | 
 |     rm -rf "$content_path" | 
 |     rm -rf "$FILE" "$name" | 
 |  | 
 |     return "$SUCCESS" | 
 | } | 
 |  | 
 | # @brief Initiate BMC dump | 
 | function initiate_bmc_dump() { | 
 |     bmcDumpPath=$(busctl call xyz.openbmc_project.Dump.Manager \ | 
 |             /xyz/openbmc_project/dump/bmc \ | 
 |         xyz.openbmc_project.Dump.Create CreateDump a\{sv\} 0) | 
 |     result=$? | 
 |     if [[ $result -ne $SUCCESS ]]; then | 
 |         echo "Error in creating BMC dump associated with system dump" | 
 |     else | 
 |         echo "BMC dump initiated $bmcDumpPath" | 
 |     fi | 
 | } | 
 |  | 
 | # @brief Main function | 
 | function main() { | 
 |     initialize | 
 |     result=$? | 
 |     if [[ $result -ne $SUCCESS ]]; then | 
 |         echo "$($TIME_STAMP)" "Error: Failed to initialize, Exiting" | 
 |         return "$INTERNAL_FAILURE" | 
 |     fi | 
 |  | 
 |     collect | 
 |     result=$? | 
 |     if [[ $result -ne $SUCCESS ]]; then | 
 |         echo "$($TIME_STAMP)" "Error: Failed to collect dump, Exiting" | 
 |         return "$INTERNAL_FAILURE" | 
 |     fi | 
 |  | 
 |     package | 
 |     result=$? | 
 |     if [[ $result -ne $SUCCESS ]]; then | 
 |         echo "$($TIME_STAMP)" "Error: Failed to package, Exiting" | 
 |         return "$INTERNAL_FAILURE" | 
 |     else | 
 |         echo "$($TIME_STAMP)" "Successfully completed" | 
 |     fi | 
 |  | 
 |     initiate_bmc_dump | 
 |     return "$SUCCESS" | 
 | } | 
 |  | 
 | if ! TEMP=$(getopt -o n:d:i:s:t:e:f:h \ | 
 |         --long name:,dir:,dumpid:,size:,type:,eid:,failingunit:,help \ | 
 |         -- "$@"); then | 
 |     echo "Error: Invalid options" | 
 |     exit 1 | 
 | fi | 
 |  | 
 | eval set -- "$TEMP" | 
 |  | 
 | while [[ $# -gt 1 ]]; do | 
 |     key="$1" | 
 |     case $key in | 
 |         -n|--name) | 
 |             name=$2 | 
 |             shift 2 ;; | 
 |         -d|--dir) | 
 |             dump_dir=$2 | 
 |             shift 2 ;; | 
 |         -i|--dumpid) | 
 |             dump_id=$2 | 
 |             shift 2 ;; | 
 |         -s|--size) | 
 |             dump_size=$2 | 
 |             shift 2 ;; | 
 |         -f|--failingunit) | 
 |             failing_unit=$2 | 
 |             shift 2 ;; | 
 |         -e|--eid) | 
 |             eid=$2 | 
 |             shift 2 ;; | 
 |         -t|--type) | 
 |             dump_sbe_type=$2 | 
 |             shift 2 ;; | 
 |         -h|--help) | 
 |             echo "$help" | 
 |             exit ;; | 
 |         *) # unknown option | 
 |             echo "Unknown argument: $1" | 
 |             echo "$help" | 
 |             exit 1 ;; | 
 |     esac | 
 | done | 
 |  | 
 | main | 
 | exit $? |