summaryrefslogtreecommitdiff
path: root/vmdebootstrap/uefi.py
blob: 215e97e0cabcfdd5e12118f839fbbbceddd3d0cd (plain)
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
"""
  Wrapper for UEFI operations
"""
# -*- coding: utf-8 -*-
#
#  uefi.py
#
#  Copyright 2015 Neil Williams <codehelp@debian.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.


# pylint: disable=missing-docstring,duplicate-code


import os
import cliapp
import logging
from vmdebootstrap.base import (
    Base,
    runcmd,
    mount_wrapper,
    umount_wrapper,
)
from vmdebootstrap.constants import arch_table


class Uefi(Base):

    name = 'uefi'

    def __init__(self):
        super(Uefi, self).__init__()
        self.bootdir = None

    def efi_packages(self):
        packages = []
        pkg = arch_table[self.settings['arch']]['package']
        self.message("Adding %s" % pkg)
        packages.append(pkg)
        extra = arch_table[self.settings['arch']]['extra']
        if extra and isinstance(extra, str):
            bin_pkg = arch_table[str(extra)]['bin_package']
            self.message("Adding support for %s using %s" % (extra, bin_pkg))
            packages.append(bin_pkg)
        return packages

    def copy_efi_binary(self, efi_removable, efi_install):
        logging.debug("using bootdir=%s", self.bootdir)
        logging.debug("moving %s to %s", efi_removable, efi_install)
        if efi_removable.startswith('/'):
            efi_removable = efi_removable[1:]
        if efi_install.startswith('/'):
            efi_install = efi_install[1:]
        efi_output = os.path.join(self.bootdir, efi_removable)
        efi_input = os.path.join(self.bootdir, efi_install)
        if not os.path.exists(efi_input):
            logging.warning("%s does not exist (%s)", efi_input, efi_install)
            raise cliapp.AppException("Missing %s" % efi_install)
        if not os.path.exists(os.path.dirname(efi_output)):
            os.makedirs(os.path.dirname(efi_output))
        logging.debug(
            'Moving UEFI support: %s -> %s', efi_input, efi_output)
        if os.path.exists(efi_output):
            os.unlink(efi_output)
        os.rename(efi_input, efi_output)

    def configure_efi(self, rootdir):
        """
        Copy the bootloader file from the package into the location
        so needs to be after grub and kernel already installed.
        """
        self.message('Configuring EFI')
        mount_wrapper(rootdir)
        efi_removable = str(arch_table[self.settings['arch']]['removable'])
        efi_install = str(arch_table[self.settings['arch']]['install'])
        self.message('Installing UEFI support binary')
        self.copy_efi_binary(efi_removable, efi_install)
        umount_wrapper(rootdir)

    def configure_extra_efi(self, rootdir):
        extra = str(arch_table[self.settings['arch']]['extra'])
        if extra:
            mount_wrapper(rootdir)
            efi_removable = str(arch_table[extra]['removable'])
            efi_install = str(arch_table[extra]['install'])
            self.message('Copying UEFI support binary for %s' % extra)
            self.copy_efi_binary(efi_removable, efi_install)
            umount_wrapper(rootdir)

    def partition_esp(self):
        espsize = self.settings['esp-size'] / (1024 * 1024)
        self.message("Using ESP size: %smib %s bytes" % (espsize, self.settings['esp-size']))
        runcmd(['parted', '-s', self.settings['image'],
                'mkpart', 'primary', 'fat32',
                '1', str(espsize)])
        runcmd(['parted', '-s', self.settings['image'],
                'set', '1', 'boot', 'on'])
        runcmd(['parted', '-s', self.settings['image'],
                'set', '1', 'esp', 'on'])

    def prepare_esp(self, rootdir, bootdev):
        bootdir = '%s/%s/%s' % (rootdir, 'boot', 'efi')
        logging.debug("bootdir:%s", self.bootdir)
        self.mkfs(bootdev, fstype='vfat')
        os.makedirs(bootdir)
        return bootdir