1#!/bin/bash
2set -eo pipefail
3
4help=$'Generate Tarball with Bios image and MANIFEST Script
5
6Generates a Bios image tarball from given file as input.
7Creates a MANIFEST for image verification and recreation
8Packages the image and MANIFEST together in a tarball
9
10usage: gen-bios-tar [OPTION] <Bios FILE>...
11
12Options:
13   -o, --out <file>       Specify destination file. Defaults to
14                          `pwd`/obmc-bios.tar.gz if unspecified.
15   -s, --sign <path>      Sign the image. The optional path argument specifies
16                          the private key file. Defaults to the bash variable
17                          PRIVATE_KEY_PATH if available, or else uses the
18                          open-source private key in this script.
19   -m, --machine <name>   Optionally specify the target machine name of this
20                          image.
21   -v, --version <name>   Specify the version of bios image file
22   -h, --help             Display this help text and exit.
23'
24
25#################################################################
26# It's the OpenBMC "public" private key (currently under
27# meta-phosphor/recipes-phosphor/flash/files/OpenBMC.priv):
28# https://gerrit.openbmc-project.xyz/c/openbmc/openbmc/+/8949/15/
29# meta-phosphor/common/recipes-phosphor/flash/files/OpenBMC.priv
30#
31#################################################################
32private_key=$'-----BEGIN PRIVATE KEY-----
33MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAPvSDLu6slkP1gri
34PaeQXL9ysD69J/HjbBCIQ0RPfeWBb75US1tRTjPP0Ub8CtH8ExVf8iF1ulsZA78B
35zIjBYZVp9pyD6LbpZ/hjV7rIH6dTNhoVpdA+F8LzmQ7cyhHG8l2JMvdunwF2uX5k
36D4WDcZt/ITKZNQNavPtmIyD5HprdAgMBAAECgYEAuQkTSi5ZNpAoWz76xtGRFSwU
37zUT4wQi3Mz6tDtjKTYXasiQGa0dHC1M9F8fDu6BZ9W7W4Dc9hArRcdzEighuxoI/
38nZI/0uL89iUEywnDEIHuS6D5JlZaj86/nx9YvQnO8F/seM+MX0EAWVrd5wC7aAF1
39h6Fu7ykZB4ggUjQAWwECQQD+AUiDOEO+8btLJ135dQfSGc5VFcZiequnKWVm6uXt
40rX771hEYjYMjLqWGFg9G4gE3GuABM5chMINuQQUivy8tAkEA/cxfy19XkjtqcMgE
41x/UDt6Nr+Ky/tk+4Y65WxPRDas0uxFOPk/vEjgVmz1k/TAy9G4giisluTvtmltr5
42DCLocQJBAJnRHx9PiD7uVhRJz6/L/iNuOzPtTsi+Loq5F83+O6T15qsM1CeBMsOw
43cM5FN5UeMcwz+yjfHAsePMkcmMaU7jUCQHlg9+N8upXuIo7Dqj2zOU7nMmkgvSNE
445yuNImRZabC3ZolwaTdd7nf5r1y1Eyec5Ag5yENV6JKPe1Xkbb1XKJECQDngA0h4
456ATvfP1Vrx4CbP11eKXbCsZ9OGPHSgyvVjn68oY5ZP3uPsIattoN7dE2BRfuJm7m
46F0nIdUAhR0yTfKM=
47-----END PRIVATE KEY-----
48'
49
50do_sign=false
51private_key_path="${PRIVATE_KEY_PATH}"
52outfile=""
53machine=""
54version=""
55
56while [[ $# -gt 0 ]]; do
57  key="$1"
58  case $key in
59    -o|--out)
60      outfile="$2"
61      shift 2
62      ;;
63    -s|--sign)
64      do_sign=true
65      if [[ ! -z "${2}"  && "${2}" != -* ]]; then
66        private_key_path="$2"
67        shift 2
68      else
69        shift 1
70      fi
71      ;;
72    -m|--machine)
73      machine="$2"
74      shift 2
75      ;;
76    -v|--version)
77      version="$2"
78      shift 2
79      ;;
80    -h|--help)
81      echo "$help"
82      exit
83      ;;
84    -*)
85      echo "Unrecognised option $1"
86      echo "$help"
87      exit
88      ;;
89    *)
90      file="$1"
91      shift 1
92      ;;
93  esac
94done
95
96if [ ! -f "${file}" ]; then
97  echo "${file} not found, Please enter a valid Bios image file"
98  echo "$help"
99  exit 1
100fi
101
102if [[ -z $version ]]; then
103  echo "Please provide version of image with -v option"
104  exit 1
105fi
106
107if [[ -z $outfile ]]; then
108  outfile=`pwd`/obmc-bios.tar.gz
109else
110  if [[ $outfile != /* ]]; then
111    outfile=`pwd`/$outfile
112  fi
113fi
114
115scratch_dir=`mktemp -d`
116# Remove the temp directory on exit.
117# The files in the temp directory may contain read-only files, so add
118# --interactive=never to skip the prompt.
119trap "{ rm -r --interactive=never ${scratch_dir}; }" EXIT
120
121if [[ "${do_sign}" == true ]]; then
122  if [[ -z "${private_key_path}" ]]; then
123    private_key_path=${scratch_dir}/OpenBMC.priv
124    echo "${private_key}" > "${private_key_path}"
125    echo "Image is NOT secure!! Signing with the open private key!"
126  else
127    if [[ ! -f "${private_key_path}" ]]; then
128      echo "Couldn't find private key ${private_key_path}."
129      exit 1
130    fi
131
132    echo "Signing with ${private_key_path}."
133  fi
134
135  public_key_file=publickey
136  public_key_path=${scratch_dir}/$public_key_file
137  openssl pkey -in "${private_key_path}" -pubout -out ${public_key_path}
138fi
139
140manifest_location="MANIFEST"
141files_to_sign="$manifest_location $public_key_file"
142
143# Go to scratch_dir
144cp ${file} ${scratch_dir}
145cd "${scratch_dir}"
146files_to_sign+=" $(basename ${file})"
147
148echo "Creating MANIFEST for the image"
149echo -e "purpose=xyz.openbmc_project.Software.Version.VersionPurpose.Host\n\
150version=$version" > $manifest_location
151
152if [[ ! -z "${machine}" ]]; then
153    echo -e "MachineName=${machine}" >> $manifest_location
154fi
155
156if [[ "${do_sign}" == true ]]; then
157  private_key_name=$(basename "${private_key_path}")
158  key_type="${private_key_name%.*}"
159  echo KeyType="${key_type}" >> $manifest_location
160  echo HashType="RSA-SHA256" >> $manifest_location
161
162  for file in $files_to_sign; do
163    openssl dgst -sha256 -sign ${private_key_path} -out "${file}.sig" $file
164  done
165
166  additional_files="*.sig"
167fi
168
169tar -czvf $outfile $files_to_sign $additional_files
170echo "Bios image tarball is at $outfile"
171