/
assemble.go
84 lines (63 loc) · 2.01 KB
/
assemble.go
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
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package uki
import (
"debug/pe"
"errors"
"fmt"
"os"
"os/exec"
"path/filepath"
)
// assemble the UKI file out of sections.
func (builder *Builder) assemble() error {
peFile, err := pe.Open(builder.SdStubPath)
if err != nil {
return err
}
defer peFile.Close() //nolint: errcheck
// find the first VMA address
lastSection := peFile.Sections[len(peFile.Sections)-1]
// align the VMA to 512 bytes
// https://github.com/saferwall/pe/blob/main/helper.go#L22-L26
const alignment = 0x1ff
header, ok := peFile.OptionalHeader.(*pe.OptionalHeader64)
if !ok {
return errors.New("failed to get optional header")
}
baseVMA := header.ImageBase + uint64(lastSection.VirtualAddress) + uint64(lastSection.VirtualSize)
baseVMA = (baseVMA + alignment) &^ alignment
// calculate sections size and VMA
for i := range builder.sections {
if !builder.sections[i].Append {
continue
}
st, err := os.Stat(builder.sections[i].Path)
if err != nil {
return err
}
builder.sections[i].Size = uint64(st.Size())
builder.sections[i].VMA = baseVMA
baseVMA += builder.sections[i].Size
baseVMA = (baseVMA + alignment) &^ alignment
}
// create the output file
args := []string{}
for _, section := range builder.sections {
if !section.Append {
continue
}
args = append(args, "--add-section", fmt.Sprintf("%s=%s", section.Name, section.Path), "--change-section-vma", fmt.Sprintf("%s=0x%x", section.Name, section.VMA))
}
builder.unsignedUKIPath = filepath.Join(builder.scratchDir, "unsigned.uki")
args = append(args, builder.SdStubPath, builder.unsignedUKIPath)
objcopy := "/usr/x86_64-alpine-linux-musl/bin/objcopy"
if builder.Arch == "arm64" {
objcopy = "/usr/aarch64-alpine-linux-musl/bin/objcopy"
}
cmd := exec.Command(objcopy, args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
return cmd.Run()
}