:: commit 6a59da5ab887245e8dfb86eb333ee3e82cfa1492

mintsuki <mintsuki@protonmail.com> — 2022-07-01 15:30

parents: 19d2e64fb7

part: Fix long standing issue with GPT logical block sizes and implement lsvol console command

diff --git a/common/console.c b/common/console.c
index ae3c5941..b43d259a 100644
--- a/common/console.c
+++ b/common/console.c
@@ -9,13 +9,15 @@
 #include <lib/libc.h>
 #include <lib/blib.h>
 #include <lib/term.h>
+#include <lib/part.h>
 
 static void console_help(void) {
     print(
         "Available commands:\n"
         "exit      -- Exit Limine console.\n"
-        "clear     -- Clears the console.\n"
+        "clear     -- Clear the console.\n"
         "%s"
+        "lsvol     -- List volumes.\n"
         "version   -- Print version.\n"
         "copyright -- Print copyright.\n"
         "help      -- Print this help message.\n",
@@ -38,6 +40,8 @@ void console(void) {
             break;
         } else if (strcmp(prompt, "clear") == 0) {
             print("\e[2J\e[H");
+        } else if (strcmp(prompt, "lsvol") == 0) {
+            list_volumes();
         } else if (editor_enabled && strcmp(prompt, "editor") == 0) {
             char *new_entry = config_entry_editor("New Entry", "");
             if (new_entry != NULL) {
diff --git a/common/lib/part.c b/common/lib/part.c
new file mode 100644
index 00000000..30fcab15
--- /dev/null
+++ b/common/lib/part.c
@@ -0,0 +1,16 @@
+#include <stddef.h>
+#include <lib/part.h>
+
+void list_volumes(void) {
+    for (size_t i = 0; i < volume_index_i; i++) {
+        struct volume *v = volume_index[i];
+        print("index: %u\n", v->index);
+        print("is_optical: %u\n", v->is_optical);
+        print("partition: %u\n", v->partition);
+        print("sector_size: %u\n", v->sector_size);
+        print("max_partition: %d\n", v->max_partition);
+        print("first_sect: %X\n", v->first_sect);
+        print("sect_count: %X\n", v->sect_count);
+        print("---\n");
+    }
+}
diff --git a/common/lib/part.h b/common/lib/part.h
index 8b14590f..f468b7d8 100644
--- a/common/lib/part.h
+++ b/common/lib/part.h
@@ -52,6 +52,8 @@ struct volume {
     struct guid part_guid;
 };
 
+void list_volumes(void);
+
 extern struct volume **volume_index;
 extern size_t volume_index_i;
 
diff --git a/common/lib/part.s2.c b/common/lib/part.s2.c
index 10a71e2c..10c3e457 100644
--- a/common/lib/part.s2.c
+++ b/common/lib/part.s2.c
@@ -125,15 +125,29 @@ struct gpt_entry {
 bool gpt_get_guid(struct guid *guid, struct volume *volume) {
     struct gpt_table_header header = {0};
 
-    int sector_size = 512;
-
-    // read header, located after the first block
-    volume_read(volume, &header, sector_size * 1, sizeof(header));
+    int lb_guesses[] = {
+        512,
+        4096
+    };
+    int lb_size = -1;
+
+    for (size_t i = 0; i < SIZEOF_ARRAY(lb_guesses); i++) {
+        // read header, located after the first block
+        volume_read(volume, &header, lb_guesses[i] * 1, sizeof(header));
+
+        // check the header
+        // 'EFI PART'
+        if (strncmp(header.signature, "EFI PART", 8))
+            continue;
+
+        lb_size = lb_guesses[i];
+        break;
+    }
 
-    // check the header
-    // 'EFI PART'
-    if (strncmp(header.signature, "EFI PART", 8))
+    if (lb_size == -1) {
         return false;
+    }
+
     if (header.revision != 0x00010000)
         return false;
 
@@ -145,15 +159,29 @@ bool gpt_get_guid(struct guid *guid, struct volume *volume) {
 static int gpt_get_part(struct volume *ret, struct volume *volume, int partition) {
     struct gpt_table_header header = {0};
 
-    int sector_size = 512;
+    int lb_guesses[] = {
+        512,
+        4096
+    };
+    int lb_size = -1;
+
+    for (size_t i = 0; i < SIZEOF_ARRAY(lb_guesses); i++) {
+        // read header, located after the first block
+        volume_read(volume, &header, lb_guesses[i] * 1, sizeof(header));
 
-    // read header, located after the first block
-    volume_read(volume, &header, sector_size * 1, sizeof(header));
+        // check the header
+        // 'EFI PART'
+        if (strncmp(header.signature, "EFI PART", 8))
+            continue;
 
-    // check the header
-    // 'EFI PART'
-    if (strncmp(header.signature, "EFI PART", 8))
+        lb_size = lb_guesses[i];
+        break;
+    }
+
+    if (lb_size == -1) {
         return INVALID_TABLE;
+    }
+
     if (header.revision != 0x00010000)
         return INVALID_TABLE;
 
@@ -163,7 +191,7 @@ static int gpt_get_part(struct volume *ret, struct volume *volume, int partition
 
     struct gpt_entry entry = {0};
     volume_read(volume, &entry,
-         (header.partition_entry_lba * sector_size) + (partition * sizeof(entry)),
+         (header.partition_entry_lba * lb_size) + (partition * sizeof(entry)),
          sizeof(entry));
 
     struct guid empty_guid = {0};
@@ -181,8 +209,8 @@ static int gpt_get_part(struct volume *ret, struct volume *volume, int partition
     ret->is_optical  = volume->is_optical;
     ret->partition   = partition + 1;
     ret->sector_size = volume->sector_size;
-    ret->first_sect  = entry.starting_lba;
-    ret->sect_count  = (entry.ending_lba - entry.starting_lba) + 1;
+    ret->first_sect  = entry.starting_lba / (lb_size / 512);
+    ret->sect_count  = ((entry.ending_lba - entry.starting_lba) + 1) / (lb_size / 512);
     ret->backing_dev = volume;
 
     struct guid guid;
tab: 248 wrap: offon