-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathsetup_stage1_mlxrom.sh
executable file
·199 lines (166 loc) · 5.63 KB
/
setup_stage1_mlxrom.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
#!/bin/bash
#
# setup_stage1.sh generates Mellanox ROMs with per-machine configuration
# embedded in the ROM image (e.g. ipv4 address, gateway, hostname), references
# to the ePoxy server (e.g. boot-api-dot-mlab-staging.appspot.com), and a
# minimal iPXE script to load stage2 of the boot process.
set -x
set -e
SOURCE_DIR=$( realpath $( dirname "${BASH_SOURCE[0]}" ) )
USAGE="$0 <project> <builddir> <output dir> <mlxrom-config> <hostname-pattern> <embed-cert1,embed-cert2>"
PROJECT=${1:?Please specify the GCP project to contact: $USAGE}
BUILD_DIR=${2:?Please specify a build directory: $USAGE}
OUTPUT_DIR=${3:?Please specify an output directory: $USAGE}
CONFIG_DIR=${4:?Please specify a configuration directory: $USAGE}
ROM_VERSION=${5:?Please specify the ROM version as "3.4.8xx": $USAGE}
CERTS=${6:?Please specify trusted certs to embed in ROM: $USAGE}
function generate_stage1_ipxe_scripts() {
local build_dir=$1
local config_dir=$2
local output_dir=$3
# Create all stage1.ipxe scripts.
pushd ${build_dir}
# TODO: replace host set with metadata service.
# TODO: Replace curl with a native go-get once mlabconfig is rewritten in Go.
curl --location "https://raw.githubusercontent.com/m-lab/siteinfo/master/cmd/mlabconfig.py" > \
./mlabconfig.py
mkdir -p ${output_dir}
python3 ./mlabconfig.py --format=server-network-config \
--sites "${SITES}" \
--physical \
--project "${PROJECT}" \
--label "project=${PROJECT}" \
--template_input "${config_dir}/stage1-template.ipxe" \
--template_output "${output_dir}/stage1-{{hostname}}.ipxe"
popd
}
# define reads a heredoc into the named variable. The variable will be global.
function define() {
local varname=$1
# -r Backslash does not act as an escape character.
# -d The first character is used to terminate the input line. We use the
# empty string, so line input is not terminated until "EOF".
# TODO: why do we set IFS?
IFS='\n' read -r -d '' ${varname} || true;
}
function get_extra_flags() {
local target=$1
local version=$2
local device_id=
local major=${version%%.*}
local sub=${version%.*} ; sub=${sub#*.}
local minor=${version##*.}
major=$( printf "%04x" $major )
sub=$( printf "%04x" $sub )
minor=$( printf "%04x" $minor )
case $target in
ConnectX-3)
device_id=0x1003
;;
ConnectX-3Pro)
device_id=0x1007
;;
*)
echo "Error: unsupported target name: $target" 1>&2
exit 1
;;
esac
define extra_flags <<EOM
-DDEVICE_CX3
-D__MLX_0001_MAJOR_VER_=0x0010${major}
-D__MLX_MIN_SUB_MIN_VER_=0x${sub}${minor}
-D__MLX_DEV_ID_00ff=${device_id}00ff
-D__BUILD_VERSION__=\"$version\"
EOM
echo $extra_flags
}
function build_roms() {
local ipxe_src=$1
local stage1_config_dir=$2
local version=$3
local debug=$4
local certs=$5
local rom_output_dir=$6
local extra_cflags=
local procs=`getconf _NPROCESSORS_ONLN`
# 15b3 is the vendor ID for Mellanox Technologies
# 1003 is the device ID for the ConnectX-3
# 1007 is the device ID for the ConnectX-3Pro
for device_name in ConnectX-3 ConnectX-3Pro; do
extra_cflags="$( get_extra_flags $device_name $version )"
pushd ${ipxe_src}
if [[ $device_name == "ConnectX-3" ]]; then
device="15b31003"
else
device="15b31007"
fi
# NOTE: clean the build environment between devices. Without resetting,
# ROMs for the ConnectX-3Pro have the wrong device ID.
make clean
rm -rf bin
for stage1 in `ls ${stage1_config_dir}/*.ipxe` ; do
# Extract the hostname from the filename.
hostname=${stage1##*stage1-}
hostname=${hostname%%.ipxe}
# The generated ROM file is the device name.
make -j ${procs} bin/${device}.mrom \
EXTRA_CFLAGS="${extra_cflags}" \
DEBUG=${debug} \
TRUST=${certs} \
EMBED=${stage1} \
NO_WERROR=1
# Copy it to a structured location.
# Note: the update image depends on this structure to locate an image.
mkdir -p ${rom_output_dir}/${version}/${device_name}/
cp bin/${device}.mrom ${rom_output_dir}/${version}/${device_name}/${hostname}.mrom
done
popd
done
# Remove old files to prevent regenerating ROMs during multiple builds.
rm -f ${stage1_config_dir}/*.ipxe
}
function copy_roms_to_output() {
local build_dir=$1
local output_dir=$2
mkdir -p "${output_dir}"
# Copy files to output.
rsync -ar "${build_dir}" "${output_dir}"
# Assure that the output files are readable.
chmod -R go+r "${output_dir}"
}
# Extra debug symbols.
#
# Debug symbols can be enabled on a per-module bases (i.e. strip ".o" from
# filename).
#
# Note: it's possible to generate a ROM image that is too large if too many
# debug symbols are enabled.
#
# For example, to debug TLS negotiation using the embedded trusted certificates,
# I started with these: DEBUG=tls,x509,certstore
DEBUG=
SCRIPTDIR=$( mktemp -d -t stage1_scripts.XXXXXX )
# Patch iPXE sources (they are a git submodule) in this repo.
git submodule update --init --recursive
ipxe_source=/workspace/ipxe/src
pushd ipxe
# Patches sources and configures build options
git apply ${CONFIG_DIR}/romprefix.S.diff
git apply ${CONFIG_DIR}/config_general.h.diff
popd
generate_stage1_ipxe_scripts \
${BUILD_DIR} \
${CONFIG_DIR} \
"${SCRIPTDIR}"
build_roms \
"${ipxe_source}" \
"${SCRIPTDIR}" \
"${ROM_VERSION}" \
"${DEBUG}" \
"${CERTS}" \
"${BUILD_DIR}/stage1_mlxrom"
rm -rf "${SCRIPTDIR}"
rm -rf "${ipxe_source}"
copy_roms_to_output \
${BUILD_DIR}/stage1_mlxrom/ \
${OUTPUT_DIR}/stage1_mlxrom