Initial operating system work

Adds a draft for most of the operating system work, sans external things like EDK2 and kernel build which will be pushed later in a separate diff.

* Sealing/Unsealing of encrypted and integrity-protected data partition using TPM2
* PID1 standard behaviour (mounting minimal filesystems, cleaning up orphans)
* TPM2.0 helper library
* Block device finding and mounting

Test Plan: Manually tested, CI will be dealt with later.

X-Origin-Diff: phab/D157
GitOrigin-RevId: 6fc494f50cab1f081c3d352677158c009f4d7990
diff --git a/cmd/mkimage/main.go b/cmd/mkimage/main.go
new file mode 100644
index 0000000..e6c9c58
--- /dev/null
+++ b/cmd/mkimage/main.go
@@ -0,0 +1,128 @@
+// Copyright 2020 The Monogon Project Authors.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import (
+	"fmt"
+	"io/ioutil"
+	"os"
+	"smalltown/generated/common"
+	"smalltown/internal/config"
+
+	"github.com/diskfs/go-diskfs"
+	"github.com/diskfs/go-diskfs/disk"
+	"github.com/diskfs/go-diskfs/filesystem"
+	"github.com/diskfs/go-diskfs/partition/gpt"
+	"github.com/naoina/toml"
+)
+
+var SmalltownDataPartition gpt.Type = gpt.Type("9eeec464-6885-414a-b278-4305c51f7966")
+
+func mibToSectors(size uint64) uint64 {
+	return (size * 1024 * 1024) / 512
+}
+
+var cfg = config.Config{
+	NodeName:      "smalltown-testing",
+	DataDirectory: "/data",
+	ExternalHost:  "",
+	TrustBackend:  common.TrustBackend_DUMMY,
+}
+
+func main() {
+	os.Remove("smalltown.img")
+	diskImg, err := diskfs.Create("smalltown.img", 3*1024*1024*1024, diskfs.Raw)
+	if err != nil {
+		fmt.Printf("Failed to create disk: %v", err)
+		os.Exit(1)
+	}
+
+	table := &gpt.Table{
+		// This is appropriate at least for virtio disks. Might need to be adjusted for real ones.
+		LogicalSectorSize:  512,
+		PhysicalSectorSize: 512,
+		ProtectiveMBR:      true,
+		Partitions: []*gpt.Partition{
+			{
+				Type:  gpt.EFISystemPartition,
+				Name:  "ESP",
+				Start: mibToSectors(1),
+				End:   mibToSectors(128) - 1,
+			},
+			{
+				Type:  SmalltownDataPartition,
+				Name:  "SIGNOS-DATA",
+				Start: mibToSectors(128),
+				End:   mibToSectors(2560) - 1,
+			},
+		},
+	}
+	if err := diskImg.Partition(table); err != nil {
+		fmt.Printf("Failed to apply partition table: %v", err)
+		os.Exit(1)
+	}
+
+	fs, err := diskImg.CreateFilesystem(disk.FilesystemSpec{Partition: 1, FSType: filesystem.TypeFat32, VolumeLabel: "ESP"})
+	if err != nil {
+		fmt.Printf("Failed to create filesystem: %v", err)
+		os.Exit(1)
+	}
+	if err := fs.Mkdir("/EFI"); err != nil {
+		panic(err)
+	}
+	if err := fs.Mkdir("/EFI/BOOT"); err != nil {
+		panic(err)
+	}
+	if err := fs.Mkdir("/EFI/smalltown"); err != nil {
+		panic(err)
+	}
+	efiPayload, err := fs.OpenFile("/EFI/BOOT/BOOTX64.EFI", os.O_CREATE|os.O_RDWR)
+	if err != nil {
+		fmt.Printf("Failed to open EFI payload for writing: %v", err)
+		os.Exit(1)
+	}
+	efiPayloadSrc, err := os.Open(os.Args[1])
+	if err != nil {
+		fmt.Printf("Failed to open EFI payload for reading: %v", err)
+		os.Exit(1)
+	}
+	defer efiPayloadSrc.Close()
+	// If this is streamed (e.g. using io.Copy) it exposes a bug in diskfs, so do it in one go.
+	efiPayloadFull, err := ioutil.ReadAll(efiPayloadSrc)
+	if err != nil {
+		panic(err)
+	}
+	if _, err := efiPayload.Write(efiPayloadFull); err != nil {
+		fmt.Printf("Failed to write EFI payload: %v", err)
+		os.Exit(1)
+	}
+	configFile, err := fs.OpenFile("/EFI/smalltown/config.toml", os.O_CREATE|os.O_RDWR)
+	if err != nil {
+		fmt.Printf("Failed to open config for writing: %v", err)
+		os.Exit(1)
+	}
+	configData, _ := toml.Marshal(cfg)
+	if _, err := configFile.Write(configData); err != nil {
+		fmt.Printf("Failed to write config: %v", err)
+		os.Exit(1)
+	}
+	if err := diskImg.File.Close(); err != nil {
+		fmt.Printf("Failed to write image: %v", err)
+		os.Exit(1)
+	}
+	fmt.Println("Success! You can now boot smalltown.img")
+}