talm
84 строки · 2.0 Кб
1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
5package uki
6
7import (
8"debug/pe"
9"errors"
10"fmt"
11"os"
12"os/exec"
13"path/filepath"
14)
15
16// assemble the UKI file out of sections.
17func (builder *Builder) assemble() error {
18peFile, err := pe.Open(builder.SdStubPath)
19if err != nil {
20return err
21}
22
23defer peFile.Close() //nolint: errcheck
24
25// find the first VMA address
26lastSection := peFile.Sections[len(peFile.Sections)-1]
27
28// align the VMA to 512 bytes
29// https://github.com/saferwall/pe/blob/main/helper.go#L22-L26
30const alignment = 0x1ff
31
32header, ok := peFile.OptionalHeader.(*pe.OptionalHeader64)
33if !ok {
34return errors.New("failed to get optional header")
35}
36
37baseVMA := header.ImageBase + uint64(lastSection.VirtualAddress) + uint64(lastSection.VirtualSize)
38baseVMA = (baseVMA + alignment) &^ alignment
39
40// calculate sections size and VMA
41for i := range builder.sections {
42if !builder.sections[i].Append {
43continue
44}
45
46st, err := os.Stat(builder.sections[i].Path)
47if err != nil {
48return err
49}
50
51builder.sections[i].Size = uint64(st.Size())
52builder.sections[i].VMA = baseVMA
53
54baseVMA += builder.sections[i].Size
55baseVMA = (baseVMA + alignment) &^ alignment
56}
57
58// create the output file
59args := []string{}
60
61for _, section := range builder.sections {
62if !section.Append {
63continue
64}
65
66args = append(args, "--add-section", fmt.Sprintf("%s=%s", section.Name, section.Path), "--change-section-vma", fmt.Sprintf("%s=0x%x", section.Name, section.VMA))
67}
68
69builder.unsignedUKIPath = filepath.Join(builder.scratchDir, "unsigned.uki")
70
71args = append(args, builder.SdStubPath, builder.unsignedUKIPath)
72
73objcopy := "/usr/x86_64-alpine-linux-musl/bin/objcopy"
74
75if builder.Arch == "arm64" {
76objcopy = "/usr/aarch64-alpine-linux-musl/bin/objcopy"
77}
78
79cmd := exec.Command(objcopy, args...)
80cmd.Stdout = os.Stdout
81cmd.Stderr = os.Stderr
82
83return cmd.Run()
84}
85