blob: 3a708c28d88e1be61ef068635682460c7da152f9 [file] [log] [blame]
Lorenz Brunf95909d2019-09-11 19:48:26 +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 storage
18
19import (
20 "fmt"
Leopold Schabel40ab4b42019-10-22 15:35:52 +020021 "git.monogon.dev/source/smalltown.git/pkg/sysfs"
Lorenz Brunf95909d2019-09-11 19:48:26 +020022 "io/ioutil"
23 "os"
24 "path/filepath"
Lorenz Brunf95909d2019-09-11 19:48:26 +020025 "strconv"
26
27 "github.com/rekby/gpt"
28 "golang.org/x/sys/unix"
29)
30
31// EFIPartitionType is the standardized partition type value for the EFI ESP partition. The human readable GUID is C12A7328-F81F-11D2-BA4B-00A0C93EC93B.
32var EFIPartitionType = gpt.PartType{0x28, 0x73, 0x2a, 0xc1, 0x1f, 0xf8, 0xd2, 0x11, 0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b}
33
34// SmalltownDataPartitionType is the partition type value for a Smalltown data partition. The human-readable GUID is 9eeec464-6885-414a-b278-4305c51f7966.
35var SmalltownDataPartitionType = gpt.PartType{0x64, 0xc4, 0xee, 0x9e, 0x85, 0x68, 0x4a, 0x41, 0xb2, 0x78, 0x43, 0x05, 0xc5, 0x1f, 0x79, 0x66}
36
37var ESPDevicePath = "/dev/esp"
38var SmalltownDataCryptPath = "/dev/data-crypt"
39
40// FindPartitions looks for the ESP and the Smalltown data partition and maps them to ESPDevicePath and
41// SmalltownDataCryptPath respectively. This doesn't fail if it doesn't find the partitions, only if
42// something goes catastrophically wrong.
43func FindPartitions() error {
44 blockdevNames, err := ioutil.ReadDir("/sys/class/block")
45 if err != nil {
46 return fmt.Errorf("failed to read sysfs block class: %w", err)
47 }
48 for _, blockdevName := range blockdevNames {
49 ueventData, err := sysfs.ReadUevents(filepath.Join("/sys/class/block", blockdevName.Name(), "uevent"))
50 if err != nil {
51 return fmt.Errorf("failed to read uevent for block device %v: %w", blockdevName.Name(), err)
52 }
53 if ueventData["DEVTYPE"] == "disk" {
54 majorDev, err := strconv.Atoi(ueventData["MAJOR"])
55 if err != nil {
56 return fmt.Errorf("failed to convert uevent: %w", err)
57 }
58 minorDev, err := strconv.Atoi(ueventData["MINOR"])
59 if err != nil {
60 return fmt.Errorf("failed to convert uevent: %w", err)
61 }
62 devNodeName := fmt.Sprintf("/dev/%v", ueventData["DEVNAME"])
63 if err := unix.Mknod(devNodeName, 0600|unix.S_IFBLK, int(unix.Mkdev(uint32(majorDev), uint32(minorDev)))); err != nil {
64 return fmt.Errorf("failed to create block device node: %w", err)
65 }
66 blkdev, err := os.Open(devNodeName)
67 if err != nil {
68 return fmt.Errorf("failed to open block device %v: %w", devNodeName, err)
69 }
70 defer blkdev.Close()
71 blockSize, err := unix.IoctlGetUint32(int(blkdev.Fd()), unix.BLKSSZGET)
72 if err != nil {
73 continue // This is not a regular block device
74 }
75 blkdev.Seek(int64(blockSize), 0)
76 table, err := gpt.ReadTable(blkdev, uint64(blockSize))
77 if err != nil {
78 // Probably just not a GPT-partitioned disk
79 continue
80 }
81 for partNumber, part := range table.Partitions {
82 if part.Type == EFIPartitionType {
83 if err := unix.Mknod(ESPDevicePath, 0600|unix.S_IFBLK, int(unix.Mkdev(uint32(majorDev), uint32(partNumber+1)))); err != nil {
84 return fmt.Errorf("failed to create device node for ESP partition: %w", err)
85 }
86 }
87 if part.Type == SmalltownDataPartitionType {
88 if err := unix.Mknod(SmalltownDataCryptPath, 0600|unix.S_IFBLK, int(unix.Mkdev(uint32(majorDev), uint32(partNumber+1)))); err != nil {
89 return fmt.Errorf("failed to create device node for Smalltown encrypted data partition: %w", err)
90 }
91 }
92 }
93 }
94 }
95 return nil
96}