Skip to content

Commit

Permalink
storage: Support for creating biosboot and efi partitions
Browse files Browse the repository at this point in the history
This will give them the right partition type immediately.
  • Loading branch information
mvollmer committed Jan 15, 2024
1 parent d742ae0 commit e0e3274
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 10 deletions.
15 changes: 15 additions & 0 deletions doc/anaconda.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,18 @@ configuration into the real /etc/fstab (_not_
Anaconda is not expected to read it.

If and how Cockpit communicates back to Anaconda is still open.

BIOS or EFI
-----------

Anaconda needs to tell Cockpit whether a BIOS or a EFI system is being
installed. This controls which kind of special partitions can be
created easily.

This is done by setting the "efi" flag to true or false:

```
{
"efi": true
}
```
45 changes: 35 additions & 10 deletions pkg/storaged/block/format-dialog.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,8 @@ export function format_dialog(client, path, start, size, enable_dos_extended) {

function format_dialog_internal(client, path, start, size, enable_dos_extended, old_luks_version) {
const block = client.blocks[path];
const block_ptable = client.blocks_ptable[path];
const block_part = client.blocks_part[path];
const block_ptable = client.blocks_ptable[path] || client.blocks_ptable[block_part?.Table];

const offer_keep_keys = block.IdUsage == "crypto";
const unlock_before_format = offer_keep_keys && !client.blocks_cleartext[path];
Expand All @@ -170,7 +171,7 @@ function format_dialog_internal(client, path, start, size, enable_dos_extended,
title = cockpit.format(_("Format $0"), block_name(block));

function is_filesystem(vals) {
return vals.type != "empty" && vals.type != "dos-extended";
return vals.type != "empty" && vals.type != "dos-extended" && vals.type != "biosboot";
}

function add_fsys(storaged_name, entry) {
Expand All @@ -185,6 +186,12 @@ function format_dialog_internal(client, path, start, size, enable_dos_extended,
add_fsys("ext4", { value: "ext4", title: "EXT4" });
add_fsys("vfat", { value: "vfat", title: "VFAT" });
add_fsys("ntfs", { value: "ntfs", title: "NTFS" });
if (client.in_anaconda_mode()) {
if (block_ptable && block_ptable.Type == "gpt" && !client.anaconda.efi)
add_fsys(true, { value: "biosboot", title: "BIOS boot partition" });
if (block_ptable && client.anaconda.efi)
add_fsys(true, { value: "efi", title: "EFI system partition" });
}
add_fsys(true, { value: "empty", title: _("No filesystem") });
if (create_partition && enable_dos_extended)
add_fsys(true, { value: "dos-extended", title: _("Extended partition") });
Expand Down Expand Up @@ -314,7 +321,7 @@ function format_dialog_internal(client, path, start, size, enable_dos_extended,
{
choices: crypto_types,
value: offer_keep_keys ? " keep" : "none",
visible: vals => vals.type != "dos-extended",
visible: vals => vals.type != "dos-extended" && vals.type != "biosboot" && vals.type != "efi",
nested_fields: [
PassInput("passphrase", _("Passphrase"),
{
Expand Down Expand Up @@ -406,6 +413,8 @@ function format_dialog_internal(client, path, start, size, enable_dos_extended,
} else {
dlg.update_actions({ Variants: [action_variant], Title: action_title });
}
if (vals.type == "efi" && !vals.mount_point)
dlg.set_values({ mount_point: "/boot/efi" });
}
},
Action: {
Expand All @@ -416,6 +425,18 @@ function format_dialog_internal(client, path, start, size, enable_dos_extended,
disable_on_error: usage.Teardown,
action: function (vals) {
const mount_now = vals.variant != "nomount";
let type = vals.type;
let partition_type = "";

if (type == "efi") {
type = "vfat";
partition_type = block_ptable.Type == "dos" ? "0xEF" : "c12a7328-f81f-11d2-ba4b-00a0c93ec93b";
}

if (type == "biosboot") {
type = "empty";
partition_type = "21686148-6449-6e6f-744e-656564454649";
}

const options = {
'tear-down': { t: 'b', v: true }
Expand Down Expand Up @@ -517,13 +538,13 @@ function format_dialog_internal(client, path, start, size, enable_dos_extended,

function format() {
if (create_partition) {
if (vals.type == "dos-extended")
if (type == "dos-extended")
return block_ptable.CreatePartition(start, vals.size, "0x05", "", { });
else if (vals.type == "empty")
return block_ptable.CreatePartition(start, vals.size, "", "", { });
else if (type == "empty")
return block_ptable.CreatePartition(start, vals.size, partition_type, "", { });
else
return block_ptable.CreatePartitionAndFormat(start, vals.size, "", "", { },
vals.type, options);
return block_ptable.CreatePartitionAndFormat(start, vals.size, partition_type, "", { },
type, options);
} else if (keep_keys) {
return (edit_crypto_config(block,
(config, commit) => {
Expand All @@ -532,10 +553,14 @@ function format_dialog_internal(client, path, start, size, enable_dos_extended,
})
.then(() => maybe_unlock())
.then(content_block => {
return content_block.Format(vals.type, options);
return content_block.Format(type, options);
}));
} else {
return block.Format(vals.type, options);
return block.Format(type, options)
.then(() => {
if (partition_type != "" && block_part)
return block_part.SetType(partition_type, {});
});
}
}

Expand Down
76 changes: 76 additions & 0 deletions test/verify/check-storage-anaconda
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,82 @@ class TestStorageAnaconda(storagelib.StorageCase):
self.dialog_wait_close()
m.execute("! findmnt --fstab -n /sysroot")

def testBiosboot(self):
b = self.browser

disk = self.add_ram_disk()

anaconda_config = {
"mount_point_prefix": "/sysroot",
"available_devices": [disk],
"efi": False,
}

self.login_and_go("/storage")
b.call_js_func("window.localStorage.setItem", "cockpit_anaconda", json.dumps(anaconda_config))
b.reload()
b.enter_page("/storage")

# Create a biosboot partition on GPT
b.wait_text(self.card_row_col("Storage", 1, 3), "Unformatted data")
self.click_dropdown(self.card_row("Storage", 1), "Create partition table")
self.confirm()
b.wait_text(self.card_row_col("Storage", 2, 2), "Free space")
self.click_dropdown(self.card_row("Storage", 2), "Create partition")
self.dialog({"type": "biosboot"})

# Check the type and set it to something else
b.wait_text(self.card_row_col("Storage", 2, 3), "Unformatted data")
self.click_card_row("Storage", 2)
b.wait_text(self.card_desc("Partition", "Type"), "BIOS boot partition")
b.click(self.card_desc_action("Partition", "Type"))
self.dialog({"type": "0fc63daf-8483-4772-8e79-3d69d8477de4"})
b.wait_text(self.card_desc("Partition", "Type"), "Linux filesystem data")

# Correct it by reformatting as "biosboot"
self.click_card_dropdown("Unformatted data", "Format")
self.dialog({"type": "biosboot"})
b.wait_text(self.card_desc("Partition", "Type"), "BIOS boot partition")

def testEfiSystemPartition(self):
b = self.browser

disk = self.add_ram_disk()

anaconda_config = {
"mount_point_prefix": "/sysroot",
"available_devices": [disk],
"efi": True,
}

self.login_and_go("/storage")
b.call_js_func("window.localStorage.setItem", "cockpit_anaconda", json.dumps(anaconda_config))
b.reload()
b.enter_page("/storage")

# Create a EFI system partition on GPT
b.wait_text(self.card_row_col("Storage", 1, 3), "Unformatted data")
self.click_dropdown(self.card_row("Storage", 1), "Create partition table")
self.confirm()
b.wait_text(self.card_row_col("Storage", 2, 2), "Free space")
self.click_dropdown(self.card_row("Storage", 2), "Create partition")
self.dialog({"type": "efi"}, secondary=True)

# Check the type and set it to something else
b.wait_text(self.card_row_col("Storage", 2, 3), "vfat filesystem")
b.wait_text(self.card_row_col("Storage", 2, 4), "/boot/efi (not mounted)")
self.click_card_row("Storage", 2)
b.wait_visible(self.card("vfat filesystem"))
b.wait_text(self.card_desc("Partition", "Type"), "EFI system partition")
b.click(self.card_desc_action("Partition", "Type"))
self.dialog({"type": "0fc63daf-8483-4772-8e79-3d69d8477de4"})
b.wait_text(self.card_desc("Partition", "Type"), "Linux filesystem data")

# Correct it by reformatting as "efi"
self.click_card_dropdown("vfat filesystem", "Format")
self.dialog({"type": "efi"}, secondary=True)
b.wait_text(self.card_desc("Partition", "Type"), "EFI system partition")


if __name__ == '__main__':
testlib.test_main()

0 comments on commit e0e3274

Please sign in to comment.