File: Filesystems.py

package info (click to toggle)
edk2 2025.11-3
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 338,556 kB
  • sloc: ansic: 2,166,376; asm: 270,725; perl: 235,301; python: 149,839; sh: 34,744; cpp: 23,311; makefile: 3,326; pascal: 1,602; xml: 806; lisp: 35; ruby: 16; sed: 6; tcl: 4
file content (102 lines) | stat: -rw-r--r-- 3,524 bytes parent folder | download | duplicates (2)
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
#
# Copyright 2019-2022 Canonical Ltd.
# Authors:
# - dann frazier <dann.frazier@canonical.com>
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 3, as published
# by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
# SATISFACTORY QUALITY, 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/>.
#

import os
import shutil
import tempfile
from util import dbg_check_call
from util import delete_tempfile


class FatFsImage:
    def __init__(self, size_in_mb):
        self.f = tempfile.NamedTemporaryFile(
            prefix=__class__.__name__,
            delete=delete_tempfile(),
        )
        self.path = self.f.name

        dbg_check_call(
            [
                'dd', 'if=/dev/zero', 'of=%s' % (self.path),
                'count=0', 'bs=1M', 'seek=%d' % (size_in_mb), 'status=none'
            ]
        )
        new_env = os.environ.copy()
        new_env['PATH'] = f"{os.environ['PATH']}:/sbin"
        dbg_check_call(['mkdosfs', '-F', '32', self.path], env=new_env)

    def mkdir(self, dir):
        dbg_check_call(['mmd', '-i', self.path, dir])

    def makedirs(self, dir):
        dirs = dir.split(os.path.sep)
        for dir_idx in range(1, len(dirs)+1):
            next_dir = os.path.sep.join(dirs[:dir_idx])
            self.mkdir(next_dir)

    def insert_file(self, src, dest):
        dbg_check_call(
            [
                'mcopy', '-i', self.path, src, '::%s' % (dest)
            ]
        )


class EfiBootableIsoImage:
    def __init__(self, eltorito_img):
        with tempfile.TemporaryDirectory() as iso_root:
            eltorito_iso_root = 'boot'
            eltorito_iso_path = os.path.join(eltorito_iso_root, 'efi.img')
            eltorito_local_root = os.path.join(iso_root, eltorito_iso_root)
            eltorito_local_path = os.path.join(iso_root, eltorito_iso_path)

            os.makedirs(eltorito_local_root)
            shutil.copyfile(eltorito_img.path, eltorito_local_path)

            self.f = tempfile.NamedTemporaryFile(
                prefix=__class__.__name__,
                delete=delete_tempfile(),
            )
            self.path = self.f.name

            dbg_check_call(
                [
                    'xorriso', '-as', 'mkisofs', '-J', '-l',
                    '-c', 'boot/boot.cat',
                    '-partition_offset', '16', '-append_partition', '2',
                    '0xef', eltorito_local_path,
                    '-e', '--interval:appended_partition_2:all::',
                    '-no-emul-boot', '-o', self.path, iso_root
                ]
            )


class GrubShellBootableIsoImage(EfiBootableIsoImage):
    def __init__(self, efi_arch, shim_path, grub_path):
        efi_img = FatFsImage(64)
        efi_img.makedirs(os.path.join('EFI', 'BOOT'))
        removable_media_path = os.path.join(
            'EFI', 'BOOT', 'BOOT%s.EFI' % (efi_arch.upper())
        )
        grub_dest = os.path.join(
            'EFI', 'BOOT', 'GRUB%s.EFI' % (efi_arch.upper())
        )
        efi_img.insert_file(shim_path, removable_media_path)
        efi_img.insert_file(grub_path, grub_dest)
        super().__init__(efi_img)