1*4882a593Smuzhiyun# 2*4882a593Smuzhiyun# Copyright (c) 2014, Intel Corporation. 3*4882a593Smuzhiyun# 4*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0-only 5*4882a593Smuzhiyun# 6*4882a593Smuzhiyun# DESCRIPTION 7*4882a593Smuzhiyun# This implements the 'bootimg-pcbios' source plugin class for 'wic' 8*4882a593Smuzhiyun# 9*4882a593Smuzhiyun# AUTHORS 10*4882a593Smuzhiyun# Tom Zanussi <tom.zanussi (at] linux.intel.com> 11*4882a593Smuzhiyun# 12*4882a593Smuzhiyun 13*4882a593Smuzhiyunimport logging 14*4882a593Smuzhiyunimport os 15*4882a593Smuzhiyunimport re 16*4882a593Smuzhiyun 17*4882a593Smuzhiyunfrom wic import WicError 18*4882a593Smuzhiyunfrom wic.engine import get_custom_config 19*4882a593Smuzhiyunfrom wic.pluginbase import SourcePlugin 20*4882a593Smuzhiyunfrom wic.misc import (exec_cmd, exec_native_cmd, 21*4882a593Smuzhiyun get_bitbake_var, BOOTDD_EXTRA_SPACE) 22*4882a593Smuzhiyun 23*4882a593Smuzhiyunlogger = logging.getLogger('wic') 24*4882a593Smuzhiyun 25*4882a593Smuzhiyunclass BootimgPcbiosPlugin(SourcePlugin): 26*4882a593Smuzhiyun """ 27*4882a593Smuzhiyun Create MBR boot partition and install syslinux on it. 28*4882a593Smuzhiyun """ 29*4882a593Smuzhiyun 30*4882a593Smuzhiyun name = 'bootimg-pcbios' 31*4882a593Smuzhiyun 32*4882a593Smuzhiyun @classmethod 33*4882a593Smuzhiyun def _get_bootimg_dir(cls, bootimg_dir, dirname): 34*4882a593Smuzhiyun """ 35*4882a593Smuzhiyun Check if dirname exists in default bootimg_dir or in STAGING_DIR. 36*4882a593Smuzhiyun """ 37*4882a593Smuzhiyun staging_datadir = get_bitbake_var("STAGING_DATADIR") 38*4882a593Smuzhiyun for result in (bootimg_dir, staging_datadir): 39*4882a593Smuzhiyun if os.path.exists("%s/%s" % (result, dirname)): 40*4882a593Smuzhiyun return result 41*4882a593Smuzhiyun 42*4882a593Smuzhiyun # STAGING_DATADIR is expanded with MLPREFIX if multilib is enabled 43*4882a593Smuzhiyun # but dependency syslinux is still populated to original STAGING_DATADIR 44*4882a593Smuzhiyun nonarch_datadir = re.sub('/[^/]*recipe-sysroot', '/recipe-sysroot', staging_datadir) 45*4882a593Smuzhiyun if os.path.exists(os.path.join(nonarch_datadir, dirname)): 46*4882a593Smuzhiyun return nonarch_datadir 47*4882a593Smuzhiyun 48*4882a593Smuzhiyun raise WicError("Couldn't find correct bootimg_dir, exiting") 49*4882a593Smuzhiyun 50*4882a593Smuzhiyun @classmethod 51*4882a593Smuzhiyun def do_install_disk(cls, disk, disk_name, creator, workdir, oe_builddir, 52*4882a593Smuzhiyun bootimg_dir, kernel_dir, native_sysroot): 53*4882a593Smuzhiyun """ 54*4882a593Smuzhiyun Called after all partitions have been prepared and assembled into a 55*4882a593Smuzhiyun disk image. In this case, we install the MBR. 56*4882a593Smuzhiyun """ 57*4882a593Smuzhiyun bootimg_dir = cls._get_bootimg_dir(bootimg_dir, 'syslinux') 58*4882a593Smuzhiyun mbrfile = "%s/syslinux/" % bootimg_dir 59*4882a593Smuzhiyun if creator.ptable_format == 'msdos': 60*4882a593Smuzhiyun mbrfile += "mbr.bin" 61*4882a593Smuzhiyun elif creator.ptable_format == 'gpt': 62*4882a593Smuzhiyun mbrfile += "gptmbr.bin" 63*4882a593Smuzhiyun else: 64*4882a593Smuzhiyun raise WicError("Unsupported partition table: %s" % 65*4882a593Smuzhiyun creator.ptable_format) 66*4882a593Smuzhiyun 67*4882a593Smuzhiyun if not os.path.exists(mbrfile): 68*4882a593Smuzhiyun raise WicError("Couldn't find %s. If using the -e option, do you " 69*4882a593Smuzhiyun "have the right MACHINE set in local.conf? If not, " 70*4882a593Smuzhiyun "is the bootimg_dir path correct?" % mbrfile) 71*4882a593Smuzhiyun 72*4882a593Smuzhiyun full_path = creator._full_path(workdir, disk_name, "direct") 73*4882a593Smuzhiyun logger.debug("Installing MBR on disk %s as %s with size %s bytes", 74*4882a593Smuzhiyun disk_name, full_path, disk.min_size) 75*4882a593Smuzhiyun 76*4882a593Smuzhiyun dd_cmd = "dd if=%s of=%s conv=notrunc" % (mbrfile, full_path) 77*4882a593Smuzhiyun exec_cmd(dd_cmd, native_sysroot) 78*4882a593Smuzhiyun 79*4882a593Smuzhiyun @classmethod 80*4882a593Smuzhiyun def do_configure_partition(cls, part, source_params, creator, cr_workdir, 81*4882a593Smuzhiyun oe_builddir, bootimg_dir, kernel_dir, 82*4882a593Smuzhiyun native_sysroot): 83*4882a593Smuzhiyun """ 84*4882a593Smuzhiyun Called before do_prepare_partition(), creates syslinux config 85*4882a593Smuzhiyun """ 86*4882a593Smuzhiyun hdddir = "%s/hdd/boot" % cr_workdir 87*4882a593Smuzhiyun 88*4882a593Smuzhiyun install_cmd = "install -d %s" % hdddir 89*4882a593Smuzhiyun exec_cmd(install_cmd) 90*4882a593Smuzhiyun 91*4882a593Smuzhiyun bootloader = creator.ks.bootloader 92*4882a593Smuzhiyun 93*4882a593Smuzhiyun custom_cfg = None 94*4882a593Smuzhiyun if bootloader.configfile: 95*4882a593Smuzhiyun custom_cfg = get_custom_config(bootloader.configfile) 96*4882a593Smuzhiyun if custom_cfg: 97*4882a593Smuzhiyun # Use a custom configuration for grub 98*4882a593Smuzhiyun syslinux_conf = custom_cfg 99*4882a593Smuzhiyun logger.debug("Using custom configuration file %s " 100*4882a593Smuzhiyun "for syslinux.cfg", bootloader.configfile) 101*4882a593Smuzhiyun else: 102*4882a593Smuzhiyun raise WicError("configfile is specified but failed to " 103*4882a593Smuzhiyun "get it from %s." % bootloader.configfile) 104*4882a593Smuzhiyun 105*4882a593Smuzhiyun if not custom_cfg: 106*4882a593Smuzhiyun # Create syslinux configuration using parameters from wks file 107*4882a593Smuzhiyun splash = os.path.join(cr_workdir, "/hdd/boot/splash.jpg") 108*4882a593Smuzhiyun if os.path.exists(splash): 109*4882a593Smuzhiyun splashline = "menu background splash.jpg" 110*4882a593Smuzhiyun else: 111*4882a593Smuzhiyun splashline = "" 112*4882a593Smuzhiyun 113*4882a593Smuzhiyun syslinux_conf = "" 114*4882a593Smuzhiyun syslinux_conf += "PROMPT 0\n" 115*4882a593Smuzhiyun syslinux_conf += "TIMEOUT " + str(bootloader.timeout) + "\n" 116*4882a593Smuzhiyun syslinux_conf += "\n" 117*4882a593Smuzhiyun syslinux_conf += "ALLOWOPTIONS 1\n" 118*4882a593Smuzhiyun syslinux_conf += "SERIAL 0 115200\n" 119*4882a593Smuzhiyun syslinux_conf += "\n" 120*4882a593Smuzhiyun if splashline: 121*4882a593Smuzhiyun syslinux_conf += "%s\n" % splashline 122*4882a593Smuzhiyun syslinux_conf += "DEFAULT boot\n" 123*4882a593Smuzhiyun syslinux_conf += "LABEL boot\n" 124*4882a593Smuzhiyun 125*4882a593Smuzhiyun kernel = "/vmlinuz" 126*4882a593Smuzhiyun syslinux_conf += "KERNEL " + kernel + "\n" 127*4882a593Smuzhiyun 128*4882a593Smuzhiyun syslinux_conf += "APPEND label=boot root=%s %s\n" % \ 129*4882a593Smuzhiyun (creator.rootdev, bootloader.append) 130*4882a593Smuzhiyun 131*4882a593Smuzhiyun logger.debug("Writing syslinux config %s/hdd/boot/syslinux.cfg", 132*4882a593Smuzhiyun cr_workdir) 133*4882a593Smuzhiyun cfg = open("%s/hdd/boot/syslinux.cfg" % cr_workdir, "w") 134*4882a593Smuzhiyun cfg.write(syslinux_conf) 135*4882a593Smuzhiyun cfg.close() 136*4882a593Smuzhiyun 137*4882a593Smuzhiyun @classmethod 138*4882a593Smuzhiyun def do_prepare_partition(cls, part, source_params, creator, cr_workdir, 139*4882a593Smuzhiyun oe_builddir, bootimg_dir, kernel_dir, 140*4882a593Smuzhiyun rootfs_dir, native_sysroot): 141*4882a593Smuzhiyun """ 142*4882a593Smuzhiyun Called to do the actual content population for a partition i.e. it 143*4882a593Smuzhiyun 'prepares' the partition to be incorporated into the image. 144*4882a593Smuzhiyun In this case, prepare content for legacy bios boot partition. 145*4882a593Smuzhiyun """ 146*4882a593Smuzhiyun bootimg_dir = cls._get_bootimg_dir(bootimg_dir, 'syslinux') 147*4882a593Smuzhiyun 148*4882a593Smuzhiyun staging_kernel_dir = kernel_dir 149*4882a593Smuzhiyun 150*4882a593Smuzhiyun hdddir = "%s/hdd/boot" % cr_workdir 151*4882a593Smuzhiyun 152*4882a593Smuzhiyun kernel = get_bitbake_var("KERNEL_IMAGETYPE") 153*4882a593Smuzhiyun if get_bitbake_var("INITRAMFS_IMAGE_BUNDLE") == "1": 154*4882a593Smuzhiyun if get_bitbake_var("INITRAMFS_IMAGE"): 155*4882a593Smuzhiyun kernel = "%s-%s.bin" % \ 156*4882a593Smuzhiyun (get_bitbake_var("KERNEL_IMAGETYPE"), get_bitbake_var("INITRAMFS_LINK_NAME")) 157*4882a593Smuzhiyun 158*4882a593Smuzhiyun cmds = ("install -m 0644 %s/%s %s/vmlinuz" % 159*4882a593Smuzhiyun (staging_kernel_dir, kernel, hdddir), 160*4882a593Smuzhiyun "install -m 444 %s/syslinux/ldlinux.sys %s/ldlinux.sys" % 161*4882a593Smuzhiyun (bootimg_dir, hdddir), 162*4882a593Smuzhiyun "install -m 0644 %s/syslinux/vesamenu.c32 %s/vesamenu.c32" % 163*4882a593Smuzhiyun (bootimg_dir, hdddir), 164*4882a593Smuzhiyun "install -m 444 %s/syslinux/libcom32.c32 %s/libcom32.c32" % 165*4882a593Smuzhiyun (bootimg_dir, hdddir), 166*4882a593Smuzhiyun "install -m 444 %s/syslinux/libutil.c32 %s/libutil.c32" % 167*4882a593Smuzhiyun (bootimg_dir, hdddir)) 168*4882a593Smuzhiyun 169*4882a593Smuzhiyun for install_cmd in cmds: 170*4882a593Smuzhiyun exec_cmd(install_cmd) 171*4882a593Smuzhiyun 172*4882a593Smuzhiyun du_cmd = "du -bks %s" % hdddir 173*4882a593Smuzhiyun out = exec_cmd(du_cmd) 174*4882a593Smuzhiyun blocks = int(out.split()[0]) 175*4882a593Smuzhiyun 176*4882a593Smuzhiyun extra_blocks = part.get_extra_block_count(blocks) 177*4882a593Smuzhiyun 178*4882a593Smuzhiyun if extra_blocks < BOOTDD_EXTRA_SPACE: 179*4882a593Smuzhiyun extra_blocks = BOOTDD_EXTRA_SPACE 180*4882a593Smuzhiyun 181*4882a593Smuzhiyun blocks += extra_blocks 182*4882a593Smuzhiyun 183*4882a593Smuzhiyun logger.debug("Added %d extra blocks to %s to get to %d total blocks", 184*4882a593Smuzhiyun extra_blocks, part.mountpoint, blocks) 185*4882a593Smuzhiyun 186*4882a593Smuzhiyun # dosfs image, created by mkdosfs 187*4882a593Smuzhiyun bootimg = "%s/boot%s.img" % (cr_workdir, part.lineno) 188*4882a593Smuzhiyun 189*4882a593Smuzhiyun label = part.label if part.label else "boot" 190*4882a593Smuzhiyun 191*4882a593Smuzhiyun dosfs_cmd = "mkdosfs -n %s -i %s -S 512 -C %s %d" % \ 192*4882a593Smuzhiyun (label, part.fsuuid, bootimg, blocks) 193*4882a593Smuzhiyun exec_native_cmd(dosfs_cmd, native_sysroot) 194*4882a593Smuzhiyun 195*4882a593Smuzhiyun mcopy_cmd = "mcopy -i %s -s %s/* ::/" % (bootimg, hdddir) 196*4882a593Smuzhiyun exec_native_cmd(mcopy_cmd, native_sysroot) 197*4882a593Smuzhiyun 198*4882a593Smuzhiyun syslinux_cmd = "syslinux %s" % bootimg 199*4882a593Smuzhiyun exec_native_cmd(syslinux_cmd, native_sysroot) 200*4882a593Smuzhiyun 201*4882a593Smuzhiyun chmod_cmd = "chmod 644 %s" % bootimg 202*4882a593Smuzhiyun exec_cmd(chmod_cmd) 203*4882a593Smuzhiyun 204*4882a593Smuzhiyun du_cmd = "du -Lbks %s" % bootimg 205*4882a593Smuzhiyun out = exec_cmd(du_cmd) 206*4882a593Smuzhiyun bootimg_size = out.split()[0] 207*4882a593Smuzhiyun 208*4882a593Smuzhiyun part.size = int(bootimg_size) 209*4882a593Smuzhiyun part.source_file = bootimg 210