diff options
| author | Alejandro Sior <aho@sior.be> | 2022-06-18 13:54:25 +0200 |
|---|---|---|
| committer | Alejandro Sior <aho@sior.be> | 2022-06-18 13:54:25 +0200 |
| commit | 6117a803ad717fd50003c0bd8fbe393db2dcac6b (patch) | |
| tree | a01ba73f37570b96bebef8c193abaf686ef9f696 | |
| parent | d6181b5e4f6f2dc72907e9f2e73db9ce0075cddd (diff) | |
add header command
| -rw-r--r-- | convert/convert.ha | 21 | ||||
| -rw-r--r-- | create/create.ha | 15 | ||||
| -rw-r--r-- | gpt/gpt.ha | 15 | ||||
| -rw-r--r-- | header/header.ha | 37 | ||||
| -rw-r--r-- | main.ha | 29 | ||||
| -rw-r--r-- | mkbackup/mkbackup.ha | 21 |
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); + }; +}; @@ -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)!; +}; @@ -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); +}; |
