3 # Copyright (c) 2016 Cisco and/or its affiliates.
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at:
8 # http://www.apache.org/licenses/LICENSE-2.0
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
16 # Note: In order to limit the damage this script can do, it is recommended
20 # 1. Download buildroot
21 # 2. Build buildroot kernel and root file system as per
22 # config files included in this package
23 # 3. Create empty disk image and extract buildroot root
24 # file system onto it, make it bootable
25 # 4. Apply any patches/additions included in this package
27 BUILD_DIR="$(dirname $0)/build"
29 BUILDROOT_NAME='buildroot-2016.02'
30 BUILDROOT_DIR="${BUILD_DIR}/${BUILDROOT_NAME}"
31 BUILDROOT_TARBALL="${BUILDROOT_NAME}.tar.gz"
32 BUILDROOT_URL="https://buildroot.org/downloads/${BUILDROOT_TARBALL}"
33 BUILDROOT_OUTPUT="${BUILDROOT_DIR}/output/images/rootfs.tar"
35 DISK_FREE_SIZE=8388608 # Min. free space on disk (8 MB)
36 DISK_ROUND_TO_NEAREST=16777216 # Round disk size up to nearest (16 MB)
38 VERSION=$(cat $(dirname $0)/CHANGELOG | grep '^## ' | head -1 | sed -e 's/.*\[\(.*\)\].*/\1/')
39 if [ "${VERSION}" = "" ]
41 echo "Unable to determine build version from CHANGELOG file. Make sure"
42 echo "that there is an entry for the most recent version in CHANGELOG,"
43 echo "and that the entry is formated like"
45 echo "## [1.0] - 2016-05-16"
49 echo Building version: ${VERSION}
50 echo $VERSION > ${BUILD_DIR}/VERSION
51 echo "NESTED_VERSION=${VERSION}" > ${BUILD_DIR}/VERSION_HIDDEN
52 img_name="${BUILD_DIR}/csit-nested-${VERSION}.img"
54 # Normally no need to touch the variables below
57 DISK_SECT_PER_TRACK=63
58 DISK_RESERVED_SECTORS=2048
60 MOUNT_TMPDIR="${BUILD_DIR}/tmp-mount"
64 # Download buildroot if not already there
65 wget -P ${BUILD_DIR} -N $BUILDROOT_URL
66 tar -C ${BUILD_DIR} -xzf ${BUILD_DIR}/$BUILDROOT_TARBALL
68 cp -p buildroot-config $BUILDROOT_DIR/.config
69 cp -p kernel-defconfig $BUILDROOT_DIR/kernel-defconfig
70 make -C $BUILDROOT_DIR
72 if [ ! -f ${BUILDROOT_OUTPUT} ]
74 echo "Buildroot compiled OK, but root file system ${BUILDROOT_OUTPUT}"
75 echo "does not exist. Somethig is wrong. Exiting."
79 # If we got here, it means we downloaded (if applicable) and built (if
80 # applicable) buildroot OK.
82 # Now let's calculate the required disk size, and build an empty disk.
84 buildroot_size=$(stat -c%s ${BUILDROOT_OUTPUT})
85 desired_size=$(( ${buildroot_size} + ${DISK_FREE_SIZE} ))
86 rounded_size=$(( ((${desired_size}/${DISK_ROUND_TO_NEAREST})+1) * \
87 ${DISK_ROUND_TO_NEAREST} ))
89 echo "Actual root FS size: ${buildroot_size}"
90 echo "Root FS size + desired free space (${DISK_FREE_SIZE}): ${desired_size}"
91 echo "Root FS size rounded to nearest ${DISK_ROUND_TO_NEAREST}:" \
92 "${rounded_size} ($(( ${rounded_size} / 1024 / 1024 )) MB)"
94 # In a normal world, we'd be creating a full-size empty image with "dd", an
95 # then use fdisk to partition it, and a tool like "kpartx" to map this into
96 # individual partitions. We'd then map the partition we're interested in.
97 # However, in order to avoid messing with /dev/mapper, we can also create
98 # our actual partition first, and then merge it with the MBR+partition table
99 # "prefix" to obtain our full disk.
101 sectors=$(( ${rounded_size} / ${DISK_SECT_SIZE} ))
103 disk_prefix=${img_name}.prefix
104 disk_main=${img_name}.main
106 dd if=/dev/zero of=${disk_prefix} bs=${DISK_SECT_SIZE} \
107 count=${DISK_RESERVED_SECTORS}
108 dd if=/dev/zero of=${disk_main} bs=${DISK_SECT_SIZE} \
109 count=$(( $sectors - ${DISK_RESERVED_SECTORS} ))
111 # Format and mount the root file system
112 mkfs.ext2 -F -L root ${disk_main}
113 mkdir -p ${MOUNT_TMPDIR}
114 sudo mount -o loop ${disk_main} ${MOUNT_TMPDIR}
115 trap "sudo umount ${MOUNT_TMPDIR}" EXIT
117 # Extract the root filesystem
118 echo "Extracting root filesystem..."
119 sudo tar -C ${MOUNT_TMPDIR} -xf ${BUILDROOT_OUTPUT}
122 echo "Applying patches/modifications"
125 sudo run-parts -v ${mydir}/patches
128 # Copy version and changelog
129 sudo cp ${BUILD_DIR}/VERSION ${MOUNT_TMPDIR}/
130 sudo cp ${mydir}/CHANGELOG ${MOUNT_TMPDIR}/
131 # Also embed this into a hidden file that we can easily retrieve with
132 # "cat <disk image> | strings | grep NESTED_VERSION"
133 sudo cp ${BUILD_DIR}/VERSION_HIDDEN ${MOUNT_TMPDIR}/.VERSION.HIDDEN
135 # Unmount root filesystem
136 sudo umount ${MOUNT_TMPDIR}
138 rmdir ${MOUNT_TMPDIR}
140 # Now create our larger disk
141 cat ${disk_prefix} ${disk_main} > ${img_name}
142 rm -f ${disk_prefix} ${disk_main}
144 # Create partition table on the disk
145 sed -e 's/\s*\([\+0-9a-zA-Z]*\).*/\1/' << _EOF | fdisk -H ${DISK_HEADS} -S ${DISK_SECT_PER_TRACK} ${img_name}
146 o # clear the in memory partition table
148 p # primary partition
149 1 # partition number 1
150 ${DISK_RESERVED_SECTORS} # Start a few KB into the disk, leave room for GRUB
151 # Default - all the way through the end of the disk
152 a # make a partition bootable
153 1 # bootable partition is partition 1
154 p # print the in-memory partition table
155 w # write the partition table
159 disk_cylinders=$(fdisk -l -H ${DISK_HEADS} -S ${DISK_SECT_PER_TRACK} ${img_name} | \
161 sed -e 's/.* \([0-9][0-9]*\) cylinders.*/\1/')
163 echo "Disk has ${disk_cylinders} cylinders"
165 # Install GRUB bootloader on the disk image
166 ${BUILDROOT_DIR}/output/host/sbin/grub --device-map=/dev/null <<_EOF
167 device (hd0) ${img_name}
168 geometry (hd0) ${disk_cylinders} ${DISK_HEADS} ${DISK_SECT_PER_TRACK}
177 echo "Your image should be ready in:"