1# Copyright (C) 2004, Advanced Micro Devices, Inc. All Rights Reserved 2# Released under the MIT license (see packages/COPYING) 3 4# Creates a bootable image using syslinux, your kernel and an optional 5# initrd 6 7# 8# End result is two things: 9# 10# 1. A .hddimg file which is an msdos filesystem containing syslinux, a kernel, 11# an initrd and a rootfs image. These can be written to harddisks directly and 12# also booted on USB flash disks (write them there with dd). 13# 14# 2. A CD .iso image 15 16# Boot process is that the initrd will boot and process which label was selected 17# in syslinux. Actions based on the label are then performed (e.g. installing to 18# an hdd) 19 20# External variables (also used by syslinux.bbclass) 21# ${INITRD} - indicates a list of filesystem images to concatenate and use as an initrd (optional) 22# ${HDDIMG_ID} - FAT image volume-id 23# ${ROOTFS} - indicates a filesystem image to include as the root filesystem (optional) 24 25inherit live-vm-common image-artifact-names 26 27do_bootimg[depends] += "dosfstools-native:do_populate_sysroot \ 28 mtools-native:do_populate_sysroot \ 29 cdrtools-native:do_populate_sysroot \ 30 virtual/kernel:do_deploy \ 31 ${MLPREFIX}syslinux:do_populate_sysroot \ 32 syslinux-native:do_populate_sysroot \ 33 ${@'%s:do_image_%s' % (d.getVar('PN'), d.getVar('LIVE_ROOTFS_TYPE').replace('-', '_')) if d.getVar('ROOTFS') else ''} \ 34 " 35 36 37LABELS_LIVE ?= "boot install" 38ROOT_LIVE ?= "root=/dev/ram0" 39INITRD_IMAGE_LIVE ?= "${MLPREFIX}core-image-minimal-initramfs" 40INITRD_LIVE ?= "${DEPLOY_DIR_IMAGE}/${INITRD_IMAGE_LIVE}-${MACHINE}.${INITRAMFS_FSTYPES}" 41 42LIVE_ROOTFS_TYPE ?= "ext4" 43ROOTFS ?= "${IMGDEPLOYDIR}/${IMAGE_LINK_NAME}.${LIVE_ROOTFS_TYPE}" 44 45IMAGE_TYPEDEP:live = "${LIVE_ROOTFS_TYPE}" 46IMAGE_TYPEDEP:iso = "${LIVE_ROOTFS_TYPE}" 47IMAGE_TYPEDEP:hddimg = "${LIVE_ROOTFS_TYPE}" 48IMAGE_TYPES_MASKED += "live hddimg iso" 49 50python() { 51 image_b = d.getVar('IMAGE_BASENAME') 52 initrd_i = d.getVar('INITRD_IMAGE_LIVE') 53 if image_b == initrd_i: 54 bb.error('INITRD_IMAGE_LIVE %s cannot use image live, hddimg or iso.' % initrd_i) 55 bb.fatal('Check IMAGE_FSTYPES and INITRAMFS_FSTYPES settings.') 56 elif initrd_i: 57 d.appendVarFlag('do_bootimg', 'depends', ' %s:do_image_complete' % initrd_i) 58} 59 60HDDDIR = "${S}/hddimg" 61ISODIR = "${S}/iso" 62EFIIMGDIR = "${S}/efi_img" 63COMPACT_ISODIR = "${S}/iso.z" 64 65ISOLINUXDIR ?= "/isolinux" 66ISO_BOOTIMG = "isolinux/isolinux.bin" 67ISO_BOOTCAT = "isolinux/boot.cat" 68MKISOFS_OPTIONS = "-no-emul-boot -boot-load-size 4 -boot-info-table" 69 70BOOTIMG_VOLUME_ID ?= "boot" 71BOOTIMG_EXTRA_SPACE ?= "512" 72 73populate_live() { 74 populate_kernel $1 75 if [ -s "${ROOTFS}" ]; then 76 install -m 0644 ${ROOTFS} $1/rootfs.img 77 fi 78} 79 80build_iso() { 81 # Only create an ISO if we have an INITRD and the live or iso image type was selected 82 if [ -z "${INITRD}" ] || [ "${@bb.utils.contains_any('IMAGE_FSTYPES', 'live iso', '1', '0', d)}" != "1" ]; then 83 bbnote "ISO image will not be created." 84 return 85 fi 86 # ${INITRD} is a list of multiple filesystem images 87 for fs in ${INITRD} 88 do 89 if [ ! -s "$fs" ]; then 90 bbwarn "ISO image will not be created. $fs is invalid." 91 return 92 fi 93 done 94 95 populate_live ${ISODIR} 96 97 if [ "${PCBIOS}" = "1" ]; then 98 syslinux_iso_populate ${ISODIR} 99 fi 100 if [ "${EFI}" = "1" ]; then 101 efi_iso_populate ${ISODIR} 102 build_fat_img ${EFIIMGDIR} ${ISODIR}/efi.img 103 fi 104 105 # EFI only 106 if [ "${PCBIOS}" != "1" ] && [ "${EFI}" = "1" ] ; then 107 # Work around bug in isohybrid where it requires isolinux.bin 108 # In the boot catalog, even though it is not used 109 mkdir -p ${ISODIR}/${ISOLINUXDIR} 110 install -m 0644 ${STAGING_DATADIR}/syslinux/isolinux.bin ${ISODIR}${ISOLINUXDIR} 111 fi 112 113 # We used to have support for zisofs; this is a relic of that 114 mkisofs_compress_opts="-r" 115 116 # Check the size of ${ISODIR}/rootfs.img, use mkisofs -iso-level 3 117 # when it exceeds 3.8GB, the specification is 4G - 1 bytes, we need 118 # leave a few space for other files. 119 mkisofs_iso_level="" 120 121 if [ -n "${ROOTFS}" ] && [ -s "${ROOTFS}" ]; then 122 rootfs_img_size=`stat -c '%s' ${ISODIR}/rootfs.img` 123 # 4080218931 = 3.8 * 1024 * 1024 * 1024 124 if [ $rootfs_img_size -gt 4080218931 ]; then 125 bbnote "${ISODIR}/rootfs.img execeeds 3.8GB, using '-iso-level 3' for mkisofs" 126 mkisofs_iso_level="-iso-level 3" 127 fi 128 fi 129 130 if [ "${PCBIOS}" = "1" ] && [ "${EFI}" != "1" ] ; then 131 # PCBIOS only media 132 mkisofs -V ${BOOTIMG_VOLUME_ID} \ 133 -o ${IMGDEPLOYDIR}/${IMAGE_NAME}.iso \ 134 -b ${ISO_BOOTIMG} -c ${ISO_BOOTCAT} \ 135 $mkisofs_compress_opts \ 136 ${MKISOFS_OPTIONS} $mkisofs_iso_level ${ISODIR} 137 else 138 # EFI only OR EFI+PCBIOS 139 mkisofs -A ${BOOTIMG_VOLUME_ID} -V ${BOOTIMG_VOLUME_ID} \ 140 -o ${IMGDEPLOYDIR}/${IMAGE_NAME}.iso \ 141 -b ${ISO_BOOTIMG} -c ${ISO_BOOTCAT} \ 142 $mkisofs_compress_opts ${MKISOFS_OPTIONS} $mkisofs_iso_level \ 143 -eltorito-alt-boot -eltorito-platform efi \ 144 -b efi.img -no-emul-boot \ 145 ${ISODIR} 146 isohybrid_args="-u" 147 fi 148 149 isohybrid $isohybrid_args ${IMGDEPLOYDIR}/${IMAGE_NAME}.iso 150} 151 152build_fat_img() { 153 FATSOURCEDIR=$1 154 FATIMG=$2 155 156 # Calculate the size required for the final image including the 157 # data and filesystem overhead. 158 # Sectors: 512 bytes 159 # Blocks: 1024 bytes 160 161 # Determine the sector count just for the data 162 SECTORS=$(expr $(du --apparent-size -ks ${FATSOURCEDIR} | cut -f 1) \* 2) 163 164 # Account for the filesystem overhead. This includes directory 165 # entries in the clusters as well as the FAT itself. 166 # Assumptions: 167 # FAT32 (12 or 16 may be selected by mkdosfs, but the extra 168 # padding will be minimal on those smaller images and not 169 # worth the logic here to caclulate the smaller FAT sizes) 170 # < 16 entries per directory 171 # 8.3 filenames only 172 173 # 32 bytes per dir entry 174 DIR_BYTES=$(expr $(find ${FATSOURCEDIR} | tail -n +2 | wc -l) \* 32) 175 # 32 bytes for every end-of-directory dir entry 176 DIR_BYTES=$(expr $DIR_BYTES + $(expr $(find ${FATSOURCEDIR} -type d | tail -n +2 | wc -l) \* 32)) 177 # 4 bytes per FAT entry per sector of data 178 FAT_BYTES=$(expr $SECTORS \* 4) 179 # 4 bytes per FAT entry per end-of-cluster list 180 FAT_BYTES=$(expr $FAT_BYTES + $(expr $(find ${FATSOURCEDIR} -type d | tail -n +2 | wc -l) \* 4)) 181 182 # Use a ceiling function to determine FS overhead in sectors 183 DIR_SECTORS=$(expr $(expr $DIR_BYTES + 511) / 512) 184 # There are two FATs on the image 185 FAT_SECTORS=$(expr $(expr $(expr $FAT_BYTES + 511) / 512) \* 2) 186 SECTORS=$(expr $SECTORS + $(expr $DIR_SECTORS + $FAT_SECTORS)) 187 188 # Determine the final size in blocks accounting for some padding 189 BLOCKS=$(expr $(expr $SECTORS / 2) + ${BOOTIMG_EXTRA_SPACE}) 190 191 # mkdosfs will sometimes use FAT16 when it is not appropriate, 192 # resulting in a boot failure from SYSLINUX. Use FAT32 for 193 # images larger than 512MB, otherwise let mkdosfs decide. 194 if [ $(expr $BLOCKS / 1024) -gt 512 ]; then 195 FATSIZE="-F 32" 196 fi 197 198 # mkdosfs will fail if ${FATIMG} exists. Since we are creating an 199 # new image, it is safe to delete any previous image. 200 if [ -e ${FATIMG} ]; then 201 rm ${FATIMG} 202 fi 203 204 if [ -z "${HDDIMG_ID}" ]; then 205 mkdosfs ${FATSIZE} -n ${BOOTIMG_VOLUME_ID} ${MKDOSFS_EXTRAOPTS} -C ${FATIMG} \ 206 ${BLOCKS} 207 else 208 mkdosfs ${FATSIZE} -n ${BOOTIMG_VOLUME_ID} ${MKDOSFS_EXTRAOPTS} -C ${FATIMG} \ 209 ${BLOCKS} -i ${HDDIMG_ID} 210 fi 211 212 # Copy FATSOURCEDIR recursively into the image file directly 213 mcopy -i ${FATIMG} -s ${FATSOURCEDIR}/* ::/ 214} 215 216build_hddimg() { 217 # Create an HDD image 218 if [ "${@bb.utils.contains_any('IMAGE_FSTYPES', 'live hddimg', '1', '0', d)}" = "1" ] ; then 219 populate_live ${HDDDIR} 220 221 if [ "${PCBIOS}" = "1" ]; then 222 syslinux_hddimg_populate ${HDDDIR} 223 fi 224 if [ "${EFI}" = "1" ]; then 225 efi_hddimg_populate ${HDDDIR} 226 fi 227 228 # Check the size of ${HDDDIR}/rootfs.img, error out if it 229 # exceeds 4GB, it is the single file's max size of FAT fs. 230 if [ -f ${HDDDIR}/rootfs.img ]; then 231 rootfs_img_size=`stat -c '%s' ${HDDDIR}/rootfs.img` 232 max_size=`expr 4 \* 1024 \* 1024 \* 1024` 233 if [ $rootfs_img_size -ge $max_size ]; then 234 bberror "${HDDDIR}/rootfs.img rootfs size is greather than or equal to 4GB," 235 bberror "and this doesn't work on a FAT filesystem. You can either:" 236 bberror "1) Reduce the size of rootfs.img, or," 237 bbfatal "2) Use wic, vmdk,vhd, vhdx or vdi instead of hddimg\n" 238 fi 239 fi 240 241 build_fat_img ${HDDDIR} ${IMGDEPLOYDIR}/${IMAGE_NAME}.hddimg 242 243 if [ "${PCBIOS}" = "1" ]; then 244 syslinux_hddimg_install 245 fi 246 247 chmod 644 ${IMGDEPLOYDIR}/${IMAGE_NAME}.hddimg 248 fi 249} 250 251python do_bootimg() { 252 set_live_vm_vars(d, 'LIVE') 253 if d.getVar("PCBIOS") == "1": 254 bb.build.exec_func('build_syslinux_cfg', d) 255 if d.getVar("EFI") == "1": 256 bb.build.exec_func('build_efi_cfg', d) 257 bb.build.exec_func('build_hddimg', d) 258 bb.build.exec_func('build_iso', d) 259 bb.build.exec_func('create_symlinks', d) 260} 261do_bootimg[subimages] = "hddimg iso" 262do_bootimg[imgsuffix] = "." 263 264addtask bootimg before do_image_complete after do_rootfs 265