summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlejandro Sior <aho@sior.be>2022-06-18 13:54:25 +0200
committerAlejandro Sior <aho@sior.be>2022-06-18 13:54:25 +0200
commit6117a803ad717fd50003c0bd8fbe393db2dcac6b (patch)
treea01ba73f37570b96bebef8c193abaf686ef9f696
parentd6181b5e4f6f2dc72907e9f2e73db9ce0075cddd (diff)
add header command
-rw-r--r--convert/convert.ha21
-rw-r--r--create/create.ha15
-rw-r--r--gpt/gpt.ha15
-rw-r--r--header/header.ha37
-rw-r--r--main.ha29
-rw-r--r--mkbackup/mkbackup.ha21
6 files changed, 108 insertions, 30 deletions
diff --git a/convert/convert.ha b/convert/convert.ha
index 7ba6bf0..5404bd8 100644
--- a/convert/convert.ha
+++ b/convert/convert.ha
@@ -12,8 +12,8 @@ use errors;
use rt;
-export fn convert(args: []str) void = {
- if (len(args) < 3) {
+export fn convert(vol: io::file, args: []str) void = {
+ if (len(args) < 2) {
fmt::fatalf("gptman.convert: needs disk");
};
@@ -22,28 +22,13 @@ export fn convert(args: []str) void = {
const source = mbr::from(source)!;
- let freeno: size = 0z;
- for (let i = 0z; i < 4; i += 1) {
- const entry = &source.bootsector.entries[i];
-
- if (entry.lba_begin == 0 && entry.length == 0)
- continue;
-
- freeno += entry.length: size;
- };
-
- let file = os::create(args[2], fs::mode::USER_RWX | fs::mode::GROUP_RX | fs::mode::OTHER_RX, fs::flags::RDWR)!;
- defer io::close(file)!;
-
- let vol = gpt::create(file, freeno);
- gpt::mkbackup(vol);
+ let vol = gpt::from(vol)!;
defer {
gpt::chksums(vol);
gpt::commit(vol)!;
gpt::finish(vol);
};
- rt::memcpy(vol.mbr, source.bootsector, size(mbr::bootsector));
for (let i = 0z; i < 4; i += 1) {
const entry = &source.bootsector.entries[i];
if (entry.lba_begin == 0 && entry.length == 0)
diff --git a/create/create.ha b/create/create.ha
new file mode 100644
index 0000000..2c08eec
--- /dev/null
+++ b/create/create.ha
@@ -0,0 +1,15 @@
+use fmt;
+use io;
+
+use gpt;
+
+export fn create(vol: io::file, args: []str) void = {
+ // XXX this is a stub
+
+ const vol = gpt::create(vol, 1000);
+ defer {
+ gpt::chksums(vol);
+ gpt::commit(vol)!;
+ gpt::finish(vol);
+ };
+};
diff --git a/gpt/gpt.ha b/gpt/gpt.ha
index f104584..9474830 100644
--- a/gpt/gpt.ha
+++ b/gpt/gpt.ha
@@ -131,23 +131,25 @@ export fn create(fd: io::file, freeno: size) *gpt = {
const mbr_sec = sector::map(fd, 0, 1);
const mbr = mbr_sec.buf: *[*]u8: *mbr::bootsector;
+ *mbr = mbr::bootsector {
+ magic = 0xaa55,
+ ...
+ };
+
const prim_header_sec = sector::map(fd, 1, 1);
const prim_header = prim_header_sec.buf: *[*]u8: *header;
*prim_header = header {
signature = 0x5452415020494645,
revision = 0x10000,
header_size = 92,
- header_crc32 = 0,
- reserved0 = 0,
header_lba = 1,
backup_header_lba = bheader_begin,
first_lba = free_begin,
last_lba = bentries_begin - 1,
- disk_guid = [0xCAFEBABE, 0xCAFEBABE],
entries_lba = entries_begin,
entries_len = 128,
entry_size = 128,
- entries_crc32 = 0,
+ ...
};
const prim_entries_sec = sector::map(fd, entries_begin, 128*128/512);
@@ -286,6 +288,9 @@ export fn mkbackup(self: *gpt) void = {
self.backup.header.header_lba = self.backup.header_sec.offs;
self.backup.header.backup_header_lba = self.primary.header_sec.offs;
self.backup.header.entries_lba = self.backup.entries_sec.offs;
+
+ self.backup.header.entries_crc32 = entries_crc32(self.backup.entries);
+ self.backup.header.header_crc32 = header_crc32(self.backup.header);
};
// Commits changed done on the data structure to the disk
@@ -298,7 +303,5 @@ export fn commit(self: *gpt) (void | io::error) = {
// Updates the CRC32 checksums of the different blocks
export fn chksums(self: *gpt) void = {
self.primary.header.entries_crc32 = entries_crc32(self.primary.entries);
- self.backup.header.entries_crc32 = entries_crc32(self.backup.entries);
self.primary.header.header_crc32 = header_crc32(self.primary.header);
- self.backup.header.header_crc32 = header_crc32(self.backup.header);
};
diff --git a/header/header.ha b/header/header.ha
new file mode 100644
index 0000000..9602071
--- /dev/null
+++ b/header/header.ha
@@ -0,0 +1,37 @@
+use fmt;
+use io;
+
+use gpt;
+
+export fn header(vol: io::file, args: []str) void = {
+ const vol = match (gpt::from(vol)) {
+ case let g: *gpt::gpt =>
+ yield g;
+ case gpt::nogpt =>
+ fmt::fatalf("gpt.header: disk {} does not have valid gpt", args[0]);
+ case =>
+ fmt::fatalf("gpt.header: could not access disk {}", args[0]);
+ };
+ defer gpt::finish(vol);
+
+ const header = vol.primary.header;
+
+ fmt::printfln("revision: \t\t{}", header.revision)!;
+ fmt::printfln("header_size: \t\t{}", header.header_size)!;
+ fmt::printfln("header_crc32: \t\t{}", header.header_crc32)!;
+ fmt::printfln("header_lba: \t\t{}", header.header_lba)!;
+ fmt::printfln("backup_header_lba: \t{}", header.backup_header_lba)!;
+ fmt::printfln("first_lba: \t\t{}", header.first_lba)!;
+ fmt::printfln("last_lba: \t\t{}", header.last_lba)!;
+ fmt::printfln("disk_guid: \t\t[{},{}]", header.disk_guid[0], header.disk_guid[1])!;
+ fmt::printfln("entries_lba: \t\t{}", header.entries_lba)!;
+ fmt::printfln("entries_len: \t\t{}", header.entries_len)!;
+ fmt::printfln("entry_size: \t\t{}", header.entry_size)!;
+ fmt::printfln("entries_crc32: \t\t{}", header.entries_crc32)!;
+
+ const primary_valid = gpt::header_crc32(header) == header.header_crc32 && gpt::entries_crc32(vol.primary.entries) == header.entries_crc32;
+ const backup_valid = gpt::header_crc32(vol.backup.header) == vol.backup.header.header_crc32 && gpt::entries_crc32(vol.backup.entries) == vol.backup.header.entries_crc32;
+
+ fmt::printfln("primary_sane: \t\t{}", primary_valid)!;
+ fmt::printfln("backup_sane: \t\t{}", backup_valid)!;
+};
diff --git a/main.ha b/main.ha
index 89e6686..508bd0c 100644
--- a/main.ha
+++ b/main.ha
@@ -1,18 +1,35 @@
use fmt;
use getopt;
use os;
+use fs;
+use io;
-use convert;
use mbr;
use gpt;
+use convert;
+use create;
+use header;
+use mkbackup;
+
export fn main() void = {
- if (len(os::args) < 2) {
- fmt::fatalf("{}: expected command", os::args[0]);
+ if (len(os::args) < 3) {
+ fmt::fatalf("{}: expected disk name", os::args[0]);
+ };
+
+ const volume = match(os::create(os::args[1], fs::mode::USER_RWX | fs::mode::GROUP_RX | fs::mode::OTHER_RX, fs::flags::RDWR)) {
+ case let v: io::file =>
+ yield v;
+ case =>
+ fmt::fatalf("{}: cannot open file {}", os::args[0], os::args[1]);
};
+ defer io::close(volume)!;
- switch (os::args[1]) {
- case "convert" => convert::convert(os::args[1..]);
- case => fmt::fatalf("{}: no such command {}", os::args[0], os::args[1]);
+ switch (os::args[2]) {
+ case "convert" => convert::convert(volume, os::args[2..]);
+ case "create" => create::create(volume, os::args[2..]);
+ case "header" => header::header(volume, os::args[2..]);
+ case "mkbackup" => mkbackup::mkbackup(volume, os::args[2..]);
+ case => fmt::fatalf("{}: no such command {}", os::args[0], os::args[2]);
};
};
diff --git a/mkbackup/mkbackup.ha b/mkbackup/mkbackup.ha
new file mode 100644
index 0000000..210e00a
--- /dev/null
+++ b/mkbackup/mkbackup.ha
@@ -0,0 +1,21 @@
+use fmt;
+use io;
+
+use gpt;
+
+export fn mkbackup(vol: io::file, args: []str) void = {
+ const vol = match(gpt::from(vol)) {
+ case let g: *gpt::gpt =>
+ yield g;
+ case gpt::nogpt =>
+ fmt::fatalf("{}: disk does not have valid gpt", args[0]);
+ case =>
+ fmt::fatalf("{}: could not access volume", args[0]);
+ };
+ defer {
+ gpt::commit(vol)!;
+ gpt::finish(vol);
+ };
+
+ gpt::mkbackup(vol);
+};