aos/tools/harness/efiimage.py
Daniel Schwyn 6d444bf552 Main handout
Signed-off-by: Daniel Schwyn <daniel.schwyn@inf.ethz.ch>
2022-03-03 14:57:51 +01:00

160 lines
5.6 KiB
Python
Executable File

#!/usr/bin/env python3
##########################################################################
# Copyright (c) 2016, 2019 ETH Zurich.
# All rights reserved.
#
# This file is distributed under the terms in the attached LICENSE file.
# If you do not find this file, copies can be found by writing to:
# ETH Zurich D-INFK, Universitaetstr 6, CH-8092 Zurich. Attn: Systems Group.
##########################################################################
import subprocess
import os, argparse, re
class EFIImage:
def __init__(self, image, size):
"""
Size in MiB
"""
self._image = image
# Size of the disk
self._sizeMB= size * 1024 * 1024
# block size
self._blockSize = 512
# size of the disk in blocks
self._sizeBlocks= self._sizeMB // self._blockSize
# first block of partition
self._startBlock = 2048
# size of partition in blocks
self._partSizeBlocks = self._sizeBlocks - self._startBlock
# calculate byte offset to first partition and format as mformat name
self._mformatImage="%s@@%d" % (self._image, self._startBlock*self._blockSize)
self._dirs = None
def _cmd(self, command, **kwargs):
print(" ".join(command))
return subprocess.check_call(command, **kwargs)
def create(self):
self._cmd(["dd", "if=/dev/zero", "of=%s" % self._image,
"bs=%d" % self._blockSize, "count=1",
"seek=%d" % (self._sizeBlocks - 1)])
self._cmd(["/sbin/parted", "-s", self._image, "mktable", "gpt"])
self._cmd(["/sbin/parted", "-s", self._image, "mkpart", "primary", "fat32",
"%ds" % self._startBlock, "%ds" % self._partSizeBlocks])
self._cmd(["/sbin/parted", "-s", self._image, "align-check", "optimal", "1"])
self._cmd(["/sbin/parted", "-s", self._image, "name", "1", "UEFI"])
self._cmd(["mformat", "-i", self._mformatImage, "-T",
str(self._partSizeBlocks), "-h", "1", "-s", "1"])
# mdir fails if the root directory is empty. We create a directory here
# to make sure _initDirCache does not fail.
self._cmd(["mmd", "-i", self._mformatImage, "dummy"])
# reset directory cache
self._dirs = None
def _initDirCache(self):
if not self._dirs is None:
return
self._dirs = set()
cmd = ["mdir", "-i", self._mformatImage, "-/b"]
print(" ".join(cmd))
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
for line in proc.stdout:
if line.endswith(b"/"):
self._dirs.add(line[:-1])
def _createParentDir(self, dirName):
""" Create a parent directory for passed directory name """
parentDir = os.path.dirname(dirName)
if parentDir is "":
return "::"
basename = "::/%s" % parentDir
if not basename in self._dirs:
self._createParentDir(parentDir)
self._cmd(["mmd", "-i", self._mformatImage, basename])
self._dirs.add(basename)
return basename
def addFile(self, inFile, fileName):
if self._dirs is None:
self._initDirCache()
dirName = self._createParentDir(fileName)
targetFile = os.path.join(dirName, os.path.basename(fileName))
self._cmd(["mcopy", "-o", "-s", "-i", self._mformatImage, inFile, targetFile])
def writeFile(self, fileName, contents):
if self._dirs is None:
self._initDirCache()
dirName = self._createParentDir(fileName)
cmd = ["mcopy", "-o", "-s", "-i", self._mformatImage, "-", os.path.join(dirName, os.path.basename(fileName))]
print(" ".join(cmd))
proc = subprocess.Popen(cmd, stdin=subprocess.PIPE)
proc.communicate(bytes(contents, 'utf-8'))
proc.stdin.close()
#
# Command line and interface functions
#
def build_bf_efi_img(img_file, build_dir, modules, menulst, hagfish):
hagfish_default = os.path.abspath(os.path.join(
os.path.dirname(os.path.realpath(__file__)),
"..","hagfish","Hagfish.efi"))
if hagfish is None:
hagfish = hagfish_default
efi = EFIImage(img_file, 200)
efi.create()
for module in modules:
if module[0] == "/":
module = module[1:]
efi.addFile(os.path.join(build_dir, module), module)
efi.writeFile("startup.nsh", "Hagfish.efi hagfish.cfg")
efi.addFile(hagfish, "Hagfish.efi")
efi.addFile(menulst, "hagfish.cfg")
def parse_menu_lst(menulst):
with open(menulst) as f:
res = []
for line in f.readlines():
line = line.strip()
if line=="" or line[0] == "#": continue
parts = re.split("\s+", line, 2)
if len(parts) < 1:
print("Ignoring line: %s" % line)
continue
if parts[0] in ["stack"]:
# no module
continue
res.append(parts[1])
return res
def parse_args():
p = argparse.ArgumentParser(
description='Build EFI image for ARMv8')
p.add_argument('menulst', help='the menu.lst')
p.add_argument('build', help='build directory')
p.add_argument('file', help='output image')
p.add_argument('--hagfish', help='hagfish location', default=None)
return p.parse_args()
if __name__ == "__main__":
print("Barrelfish EFI Image Builder")
args = parse_args()
print("Image File: %s" % args.file)
print("menu.lst: %s" % args.menulst)
modules = parse_menu_lst(args.menulst)
print("Modules: %s" % ",".join(modules))
build_bf_efi_img(args.file, args.build, modules, args.menulst, args.hagfish)