blob: e6c9c58699e06d5e5984128f94e0163e6d680754 [file] [log] [blame]
Lorenz Brunae0d90d2019-09-05 17:53:56 +02001// Copyright 2020 The Monogon Project Authors.
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
17package main
18
19import (
20 "fmt"
21 "io/ioutil"
22 "os"
23 "smalltown/generated/common"
24 "smalltown/internal/config"
25
26 "github.com/diskfs/go-diskfs"
27 "github.com/diskfs/go-diskfs/disk"
28 "github.com/diskfs/go-diskfs/filesystem"
29 "github.com/diskfs/go-diskfs/partition/gpt"
30 "github.com/naoina/toml"
31)
32
33var SmalltownDataPartition gpt.Type = gpt.Type("9eeec464-6885-414a-b278-4305c51f7966")
34
35func mibToSectors(size uint64) uint64 {
36 return (size * 1024 * 1024) / 512
37}
38
39var cfg = config.Config{
40 NodeName: "smalltown-testing",
41 DataDirectory: "/data",
42 ExternalHost: "",
43 TrustBackend: common.TrustBackend_DUMMY,
44}
45
46func main() {
47 os.Remove("smalltown.img")
48 diskImg, err := diskfs.Create("smalltown.img", 3*1024*1024*1024, diskfs.Raw)
49 if err != nil {
50 fmt.Printf("Failed to create disk: %v", err)
51 os.Exit(1)
52 }
53
54 table := &gpt.Table{
55 // This is appropriate at least for virtio disks. Might need to be adjusted for real ones.
56 LogicalSectorSize: 512,
57 PhysicalSectorSize: 512,
58 ProtectiveMBR: true,
59 Partitions: []*gpt.Partition{
60 {
61 Type: gpt.EFISystemPartition,
62 Name: "ESP",
63 Start: mibToSectors(1),
64 End: mibToSectors(128) - 1,
65 },
66 {
67 Type: SmalltownDataPartition,
68 Name: "SIGNOS-DATA",
69 Start: mibToSectors(128),
70 End: mibToSectors(2560) - 1,
71 },
72 },
73 }
74 if err := diskImg.Partition(table); err != nil {
75 fmt.Printf("Failed to apply partition table: %v", err)
76 os.Exit(1)
77 }
78
79 fs, err := diskImg.CreateFilesystem(disk.FilesystemSpec{Partition: 1, FSType: filesystem.TypeFat32, VolumeLabel: "ESP"})
80 if err != nil {
81 fmt.Printf("Failed to create filesystem: %v", err)
82 os.Exit(1)
83 }
84 if err := fs.Mkdir("/EFI"); err != nil {
85 panic(err)
86 }
87 if err := fs.Mkdir("/EFI/BOOT"); err != nil {
88 panic(err)
89 }
90 if err := fs.Mkdir("/EFI/smalltown"); err != nil {
91 panic(err)
92 }
93 efiPayload, err := fs.OpenFile("/EFI/BOOT/BOOTX64.EFI", os.O_CREATE|os.O_RDWR)
94 if err != nil {
95 fmt.Printf("Failed to open EFI payload for writing: %v", err)
96 os.Exit(1)
97 }
98 efiPayloadSrc, err := os.Open(os.Args[1])
99 if err != nil {
100 fmt.Printf("Failed to open EFI payload for reading: %v", err)
101 os.Exit(1)
102 }
103 defer efiPayloadSrc.Close()
104 // If this is streamed (e.g. using io.Copy) it exposes a bug in diskfs, so do it in one go.
105 efiPayloadFull, err := ioutil.ReadAll(efiPayloadSrc)
106 if err != nil {
107 panic(err)
108 }
109 if _, err := efiPayload.Write(efiPayloadFull); err != nil {
110 fmt.Printf("Failed to write EFI payload: %v", err)
111 os.Exit(1)
112 }
113 configFile, err := fs.OpenFile("/EFI/smalltown/config.toml", os.O_CREATE|os.O_RDWR)
114 if err != nil {
115 fmt.Printf("Failed to open config for writing: %v", err)
116 os.Exit(1)
117 }
118 configData, _ := toml.Marshal(cfg)
119 if _, err := configFile.Write(configData); err != nil {
120 fmt.Printf("Failed to write config: %v", err)
121 os.Exit(1)
122 }
123 if err := diskImg.File.Close(); err != nil {
124 fmt.Printf("Failed to write image: %v", err)
125 os.Exit(1)
126 }
127 fmt.Println("Success! You can now boot smalltown.img")
128}