#!/bin/bash # # pvextract_hdr - extract an IBM Secure Execution header from the Image # # Sample: # ./pvextract-hdr -o sehdr.bin se-image.bin # # Copyright IBM Corp. 2022 # # s390-tools is free software; you can redistribute it and/or modify # it under the terms of the MIT license. See LICENSE for details. set -o pipefail set -o nounset set -e XDUMP='od -A x -t x2z -v --endian=big' def_output='sehdr.bin' def_skip=0x14 def_len=0x4 usage() { cat <<-EOF Usage: $(basename "$0") [-o ${def_output}] [-s ${def_skip}] [-l ${def_len}] FILE Extract the header of the SE-image located in FILE. By default ${def_skip} pages will be skipped until starting to search for the header. By default the search will be stopped after ${def_len} pages. '${def_output}' is the default output file name. EOF } function check_file() { [ -e "$1" ] || { echo "ERROR: File '$1' not found" >&2 && exit 1; } } function check_hdr_ver() { local hdr_start="$1" local input="$2" ${XDUMP} --skip-bytes $((hdr_start + 8)) --read-bytes 4 -- "$input" 2>/dev/null | grep -q "000 0100" || { echo -n "WARNING: unknown hdr version " && ${XDUMP} --skip-bytes $((hdr_start + 8)) --read_bytes 4 -- "$input" 2>/dev/null | awk '{print "0x" $2 $3}'; } } function require_command() { local cmd="$1" command -v "$cmd" >/dev/null 2>&1 || \ { echo >&2 "ERROR: $cmd required but not installed."; exit 1; } } require_command od require_command awk require_command grep output=${def_output} parsed_skip=${def_skip} parsed_len=${def_len} # the last argument must be the input file input="${*: -1}" while getopts 'o:s:l:h' OPTION; do case "$OPTION" in o) output="$OPTARG" ;; s) parsed_skip="$OPTARG" ;; l) parsed_len="$OPTARG" ;; h) usage exit 0 ;; :) echo "ERROR: Must supply an argument to -$OPTARG." >&2 exit 1 ;; *) usage exit 1 ;; esac done #argument specify pages; convert to bytes skip=$((parsed_skip * 0x1000)) len=$((parsed_len * 0x1000)) if [ $# -eq 0 ]; then echo "ERROR: Input not set. Use '$(basename "$0") [FILE]' to specify the Input file" >&2 exit 1 fi check_file "$input" hdr_start=$(${XDUMP} --skip-bytes $((skip)) --read-bytes $((len)) -- "${input}" 2>/dev/null | grep IBMSecEx || { echo ERROR: "${input} does not contain an SE header." >&2 && exit 1; }) hdr_start=$(echo "${hdr_start}" | awk '{print "0x" $1}' | cut -c 1-10) echo "SE header found at offset ${hdr_start}" check_hdr_ver "$hdr_start" "$input" size=$(${XDUMP} --skip-bytes $((hdr_start + 12)) --read-bytes 4 -- "${input}" 2>/dev/null | awk 'NR==1 {print "0x" $2 $3}') dd if="${input}" of="${output}" bs=1 count=$((size)) skip=$((hdr_start)) status=none echo "SE header written to '${output}' ($((size)) bytes)"