wolfwings: (Default)
wolfwings ([personal profile] wolfwings) wrote2013-01-11 12:48 pm

UEFI Linux w/ SSDs

This is partially some notes, and partially a guide to setting up a fully UEFI (though not Secure Boot enabled) Linux laptop, optimized for use with any and all SSD's including the most recently known details (as of January 2013) on how to get the best performance and endurance from consumer-grade SSD's, including minimizing I/O latency and allowing as many features of Linux as possible to work.

Note, however, that I am making one specific trade-off: I'm optimizing for a machine with 8+GB of memory, and an SSD under 100GB when we're done, so I'm not even attempting to add swap space or enable disk hibernation as a result.

This work was done to configure a Dell Latitude E6430 w/ 16GB of RAM, and a Samsung 840 Pro 120GB SSD. I must give Dell EXTREMELY high marks for their UEFI BIOS, BTW. It's the best I've seen for dealing with advanced setup and configuration and made this a breeze compared to my ThinkPad W530's BIOS.


There are several items of note regarding SSD's that drive the choices made later on:

  • They 'erase' data in large blocks.
    Usually at least 128KiB, sometimes as large as 2MiB.
    This is the data-block size they love to see most.
    ALL data interactions when possible should be on a multiple of this size.

  • They perform best long-term with at least 25% of the drive left unprovisioned.
    This means for my 120GB drive, I'll have around 90GB usable.
    I'm opting for hard-limiting the drive capacity to enforce this.

  • They have effectively zero seek time.
    This means disabling the I/O scheduler in Linux for them.

Regarding UEFI, I'm opting for an EXTREMELY minimal approach:

  • No dedicated bootloader.
    This means no GRUB, nadda. Direct EFI-Stub booting.
  • Only two partitions as a result.
    You can extend this to dual-booting Windows, etc, and in fact it's easier to keep the Windows boot-loader than chain-load to it later.

Finally, one item regarding x86/x86_64 platforms where UEFI are most commonly encountered by those installing Linux:

  • Huge Pages are 2MiB in size.
    This is a convenient size to focus everything around; while non-optimal for many SSDs it's a valid least-worst option.

Partitioning the Drive

First, we need to check how many total sectors the drive says we have, so limit overall size/use to 75% of that to maintain performance long-term:

root@sysresccd /root % hdparm /dev/sda | egrep -o "sectors = [0-9]+"
sectors = 250069680

In this case, my SSD has 250069680 512-byte sectors available. We'll only use 75% of those, and want to keep that 2MiB alignment to keep things universal, so:

root@sysresccd /root % echo $[250069680*3/4/4096*4096-1]

Note this number down, we'll need it in a here as we partition things:

root@sysresccd /root % gdisk /dev/sda
GPT fdisk (gdisk) version 0.8.5

Partition table scan:
  MBR: protective
  BSD: not present
  APM: not present
  GPT: not present

Creating new GPT entries.

Command (...): x

Expert command (...): l
Enter the sector alignment value (...): 4096

Expert command (...): m

Command (...): n
Partition number (...): <Enter>
First sector (...) or ...: <Enter>
Last sector (...) or ...: 204799
Current type is 'Linux filesystem'
Hex code or GUID (...): EF00
Changed type of partition to 'EFI System'

Command (...): n
Partition number (...): <Enter>
First sector (...) or ...: <Enter>
Last sector (...) or ...: 187551743
Current type is 'Linux filesystem'
Hex code or GUID (...): <Enter>
Changed type of partition to 'Linux filesystem'

Command (...): i
Partition number (1-2): 2
Partition GUID code: ... (Linux Filesystem)
Partition unique GUID: 00000000-0000-0000-0000-000000000000
First sector: ...
Last sector: ...
Partition size: ...
Attribute flags: ...
Partition name: 'Linux filesystem'

Command (...): w

Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING

Do you want to proceed? (Y/N): y
OK; writing new GUID partition table (GPT) to /dev/sda.
The operation has completed successfully.

Creating the Filesystems

The filesystem presents another stage where we need to enforce the alignment. We do this via 'lying' to the mkfs utility and treating the SSD as a RAID w/ a "chunk" or "stripe" size equal to the erase-block size. In this case I am assuming a 2MiB erase-block size so these instructions stay as universal as possible.

The UEFI boot partition is written to almost never, so alignment is a non-issue by comparison. It also is required to be FAT32, so there's no tweaks possible really. The 'root' filesystem by comparison has two valid options currently, EXT4, or XFS.

FAT32 UEFI Partition

root@sysresccd /root % mkfs.vfat -F 32 /dev/sda1

EXT4 Root Partition

root@sysresccd /root % mkfs.ext4 -E stride=512,stripe-width=512 /dev/sda2

XFS Root Partition

root@sysresccd /root % mkfs.xfs -d su=2048k -d sw=1 /dev/sda2

Proceed with normal installation of a root filesystem, etc. Make sure to add the 'discard' flag to your root filesystem also.

Kernel Configuration

Now that you have your base OS installed on /dev/sda2, we need to make sure a couple of kernel configuration options are enabled to allow it to be booted directly:

Power management and ACPI options --->
[*] ACPI (Advanced Configuration and Power Interface) Support

Processor type and features --->
[*] EFI runtime service support
[*]   EFI stub support
[*] Built-in kernel command line
(root=PARTUUID=00000000-0000-0000-0000-000000000000 ro)
[*]   Built-in command line overrides boot loader arguments

Anything else you enable is your choice, there's plenty of guides detailing that. These are the only options you truly need to enable for this stage though.

EFI Stub Bootloader Configuration

Once you have a bzImage of your kernel, you're going to laugh at how simple it is to update your kernel image so it will boot from EFI, assuming /boot is mounted:

root@sysresccd /root % mkdir -p /boot/efi/boot
root@sysresccd /root % cp /usr/src/linux/arch/x86_64/boot/bzImage /boot/efi/boot/bootx64.efi

That's is. Really. No configuration files, nadda. Downside: No recovery options if something breaks, but I've never had good luck with those 'included' tools so I end up relying on... yup, that System Recovery CD/USB you're already using to install the system with. So is there really any downside? Not that I've found yet.

Dual-Boot w/ Windows

On pure UEFI configurations it's actually incredibly easy to add a Linux option while maintaining the Windows Bootloader. I prefer this approach as it avoids having to boot a series of bootloaders when most of the time you always boot into the same operating system.

For frequent travelling it can be nice as well because it leaves the laptop on initial boot looking like a normal Windows machine if you wish but leaving Linux available with a single keystroke.

First, copy your kernel to some other place on the EFI System Partition, such as \EFI\Linux\kernel.efi instead of \EFI\boot\bootx64.efi.

Next, we'll need to run two commands so Microsoft's BCD bootloader knows how to boot Linux without dealing with DD and GRUB and boot sectors and other crap:

C:\Windows\system32> BCDEdit /copy {9dea862c-5cdd-4e70-acc1-f32b344d4795} /d "Linux"
The entry was successfully copied to {########-####-####-####-############}.
C:\Windows\system32> BCDEdit /set {########-####-####-####-############} PATH "\EFI\Linux\kernel.efi"

Secure Boot (Coming Soon)

If you've come here before this section is ready, I deeply apologize. I haven't had time to write it yet! It does work, though in this case it's far easier to accomplish on a fully-featured UEFI BIOS like the Dell Inspirions because they let you directly modify the Secure Boot key databases without relying on external tools.

I'm ironing out the specific steps needed that will work across at least both my Dell and my Lenovo laptops, to avoid manually importing keys and such. Single-model instructions aren't helpful to the ecosystem as a whole, and Secure Boot-related tools are still in flux as well.