Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for Hybrid MBR #168

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions example/hybrid-mbr.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
{ disks ? [ "/dev/sda" ], ... }:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have a suggestion how we should name hybrid.nix in that case since it's still a bit confusing to have both.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I comment here #166 (comment) existent gpt-bios-compat.nix is enough. hybrid.nix or hybrid-tmpfs-onroot.nix looks confusing and redundant for me.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, the gpt-bios-compat can't do EFI because it has no efi or boot partition

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. I would also prefer something that can support both EFI/BIOS. We have installer that works with both EFI and BIOS and makes it unnecessary for people to have to figure out what mode there machines was booted from.

Copy link
Author

@oneingan oneingan Mar 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, so maybe we could reorganize as:

remove gpt-bios-compat.nix (I'm not sure which is the use case of this without EFI partition)
EDIT: Ok, use case is boot larger disks in BIOS ONLY systems.
remove hybrid-tmpfs-onroot.nix (or not, but for clarity on discussion)

then if we want to keep the hybrid keyword:

hybrid.nix -> hybrid_boot.nix

Also, being stricts, seems like the real name of hybrid boot using bios_grub flags is GPT-only protocol. As in https://wiki.archlinux.org/title/Arch_boot_process#Feature_comparison and https://repo.or.cz/syslinux.git/blob/HEAD:/doc/gpt.txt.

or refered as "BIOS/GPT boot" in wikipedia: https://en.wikipedia.org/wiki/BIOS_boot_partition

hybrid.nix -> bios-gpt-boot.nix

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, maybe can we get this to a conclusion?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe we can call it bios-efi-boot? since it does both?

{
disk = {
main = {
type = "disk";
device = builtins.elemAt disks 0;
content = {
type = "hybrid_table";
efiGptPartitionFirst = false;
hybrid_partitions = [
{
type = "hybrid_partition";
gptPartitionNumber = 1;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isn't the index in the list enough? why do we need to count here? what would happen if I set this to 3?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to choose which GPT partition want to make available in DOS table. Maybe a sane default using index is ok.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so this is the index of the gpt partition table which is defined in content?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

correct.

mbrPartitionType = "0x0c";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what are other valid mbrPartitionType options?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

whatever hexcode dos table partitions support, as in https://en.wikipedia.org/wiki/Partition_type#List_of_partition_IDs.

If null then it guess partition type based on GPT one.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but would it still be a hybrid mbr if the partitionType is not "0x0c"?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, set to 0x0chave sense for RPi because RPi boot process look exactly for it, but other use cases could work with default value.

mbrBootableFlag = false;
}
];
content = {
type = "table";
format = "gpt";
partitions = [
{
type = "partition";
name = "TOW-BOOT-FI";
start = "0%";
end = "32MiB";
fs-type = "fat32";
content = {
type = "filesystem";
format = "vfat";
mountpoint = null;
};
}
{
type = "partition";
name = "ESP";
start = "32MiB";
end = "512MiB";
bootable = true;
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
};
}
{
type = "partition";
name = "root";
start = "512MiB";
end = "100%";
content = {
type = "filesystem";
format = "ext4";
mountpoint = "/";
};
}
];
};
};
};
};
}
6 changes: 4 additions & 2 deletions types/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ rec {

# option for valid contents of devices
deviceType = lib.mkOption {
type = lib.types.nullOr (diskoLib.subType { inherit (subTypes) table btrfs filesystem zfs mdraid luks lvm_pv swap; });
type = lib.types.nullOr (diskoLib.subType { inherit (subTypes) table hybrid_table btrfs filesystem zfs mdraid luks lvm_pv swap; });
default = null;
description = "The type of device";
};
Expand Down Expand Up @@ -133,7 +133,7 @@ rec {
|| lib.hasSuffix "Hook" n
|| isAttrsOfSubmodule o
# TODO don't hardcode diskoLib.subType options.
|| n == "content" || n == "partitions"
|| n == "content" || n == "partitions" || n == "hybrid_partitions"
);
in
lib.toShellVars
Expand Down Expand Up @@ -342,7 +342,9 @@ rec {
btrfs_subvol = ./btrfs_subvol.nix;
filesystem = ./filesystem.nix;
table = ./table.nix;
hybrid_table = ./hybrid_table.nix;
partition = ./partition.nix;
hybrid_partition = ./hybrid_partition.nix;
swap = ./swap.nix;
lvm_pv = ./lvm_pv.nix;
lvm_vg = ./lvm_vg.nix;
Expand Down
59 changes: 59 additions & 0 deletions types/hybrid_partition.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
{ config, options, lib, diskoLib, ... }:
{
options = {
type = lib.mkOption {
type = lib.types.enum [ "hybrid_partition" ];
internal = true;
description = "Type";
};
gptPartitionNumber = lib.mkOption {
type = lib.types.int;
description = "GPT partition number";
};
mbrPartitionType = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
description = "MBR type code";
};
mbrBootableFlag = lib.mkOption {
type = lib.types.bool;
default = false;
description = "Set the bootable flag (aka the active flag) on any or all of your hybridized partitions";
};
_meta = lib.mkOption {
internal = true;
readOnly = true;
type = lib.types.functionTo diskoLib.jsonType;
default = dev: {};
description = "Metadata";
};
_create = diskoLib.mkCreateOption {
inherit config options;
default = { dev, partNum }: ''
${lib.optionalString (config.mbrPartitionType != null) ''
sfdisk --label-nested dos --part-type ${dev} ${(toString partNum)} ${config.mbrPartitionType}
''}
${lib.optionalString config.mbrBootableFlag ''
sfdisk --label-nested dos --activate ${dev} ${(toString partNum)}
''}
'';
};
_mount = diskoLib.mkMountOption {
inherit config options;
default = { dev }: {};
};
_config = lib.mkOption {
internal = true;
readOnly = true;
default = dev: {};
description = "NixOS configuration";
};
_pkgs = lib.mkOption {
internal = true;
readOnly = true;
type = lib.types.functionTo (lib.types.listOf lib.types.package);
default = pkgs: lib.optionals (config.mbrPartitionType != null) [ pkgs.util-linux ];
description = "Packages";
};
};
}
59 changes: 59 additions & 0 deletions types/hybrid_table.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
{ config, options, lib, diskoLib, subTypes, ... }:
{
options = {
type = lib.mkOption {
type = lib.types.enum [ "hybrid_table" ];
internal = true;
description = "Hybrid MBR/GPT Partition table";
};
efiGptPartitionFirst = lib.mkOption {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this really need to be configurable? What is the use case? Why not always place the GPT partition first?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GPT partition first is always recommended for GRUB bootloader, but, for instance, Raspberry Pi bootloader, looks exactly for a 0x0c partition type as first partition.

IMHO, disko may support every flow gdisk hybrid tool support. As related in "Creating a Hybrid MBR" from https://www.rodsbooks.com/gdisk/hybrid.html

type = lib.types.bool;
default = true;
description = "Place EFI GPT (0xEE) partition first in MBR (good for GRUB)";
};
hybrid_partitions = lib.mkOption {
type = lib.types.listOf subTypes.hybrid_partition;
default = [ ];
description = "List of one to three GPT partitions to be added to the hybrid MBR";
};
content = diskoLib.deviceType;
_meta = lib.mkOption {
internal = true;
readOnly = true;
type = lib.types.functionTo diskoLib.jsonType;
default = dev:
diskoLib.deepMergeMap (partition: partition._meta dev) config.partitions;
description = "Metadata";
};
_create = diskoLib.mkCreateOption {
inherit config options;
default = { dev }: ''
${(config.content._create { inherit dev; })}

sgdisk -h \
${lib.concatMapStringsSep ":" (hp: (toString hp.gptPartitionNumber)) config.hybrid_partitions}${lib.optionalString (!config.efiGptPartitionFirst) ":EE"} \
${dev}

${lib.concatImapStrings (i: hp: hp._create {inherit dev; partNum = i + (if config.efiGptPartitionFirst then 1 else 0 );}) config.hybrid_partitions}
'';
};
_mount = diskoLib.mkMountOption {
inherit config options;
default = { dev }: config.content._mount { inherit dev; };
};
_config = lib.mkOption {
internal = true;
readOnly = true;
default = dev: config.content._config dev;
description = "NixOS configuration";
};
_pkgs = lib.mkOption {
internal = true;
readOnly = true;
type = lib.types.functionTo (lib.types.listOf lib.types.package);
default = pkgs:
[ pkgs.gptfdisk ] ++ (config.content._pkgs pkgs);
description = "Packages";
};
};
}