Madgwick.xyz

July 30, 2018 (2018-07-30)

Installing and Booting from a PCIe M.2 SSD on Intels Z77 Chipset

The Goal

A working Ubuntu Linux install and dual boot with windows 10 on an PCIe M.2 SSD in a computer which does not have bios support for one but does support UEFI. If you want to do this on a computer without any UEFI support or if you don’t need to dual boot then read the note at the end about how this guide could be adapted.

Proposition and Theory

My motherboard (Intel Z77) does not have any M.2 slots. However it is possible to install one by using an adaptor which converts 4x PCIe lanes to M.2. But the BIOS does not have support for PCIe M.2. This means that the drive does not show up in the BIOS as a boot device, which also means that GRUB bootloaders cannot see it, as GRUB relies on the BIOS to find boot devices (unless GRUB has it’s own drivers, which it doesn’t for M.2). In order to install Linux onto this M.2 SSD a novel method has to be used. By installing GRUB on a standard sata disk (which the BIOS can see and will boot) and then also placing the Linux kernel and initial filesystem on this (or another sata) disk it is possible to boot the kernel without using the M.2 SSD. The booting method, UEFI or MBR, shouldn’t matter, either will do. The root filesystem however, will of course be located on the M.2 SSD. The key is that while the BIOS cannot see this disk, the Linux kernel can. Once the kernel has loaded it will be able to see and then mount the M.2 SSD as the root filesystem. Ordinarily the kernel itself would be stored on the same disk as the root filesystem and OS installation, but it doesn’t need to be. As long as the kernel knows where to look for the root filesystem it will work.

The first thing I needed to do was examine the situation. The initial Windows 10 setup was on a sata boot SSD using MBR and not EFI, plus two sata HDD’s (used for file storage) and the M.2 SSD (also used for storage).

Initial partition setup (excluding installer usb):

Because both storage disks use GPT, GRUB cannot easily be installed in the MBR of these drives and the sata SSD cannot be used because the MBR already contains the windows bootloader. Therefore EFI grub must be used. This is simpler, only needing a FAT32 (ESP) partition to store bootable .EFI files, which the UEFI BIOS is able to boot directly.

Now, as we are going to install onto the M.2 SSD it needs to be repartitioned. Another drive also needs to make room for a partition to store the kernel and initramfs, plus another partition for the EFI boot files. I chose G for this, I could have used C but it’s best not to mess about with windows’ partitions in case it gets confused.

Ubuntu's Minimal Installer image

I always use the Ubuntu Minimal Installer1, because it downloads the latest versions of packages during installation. Instead of the live CD/USB which is almost 1GB and installs potentially outdated packages which have to be updated once you boot up for the first time. The Minimal Installer is also faster and power user friendly with a text based interface. Unfortunately due to a bug it needs to be tweaked2 before the image can be booted using UEFI.

Partitioning the M.2 SSD from the Ubuntu installer

I’m not sure why this was MBR and not GPT, but it was probably because I formatted it using windows. There’s no reason to use MBR over GPT and GPT apparently offers better performance on SSD’s. So I wiped it, converted to GPT and laid out two partitions. A small 16 GB partition for swap and the rest as ext4 for the root filesystem. The mount point for the ext4 partition should be / (root).

Partitioning the SATA HDD from the Ubuntu installer

I shrunk the existing NTFS partition in windows and then created two new partitions at the end of the disk. 512MB for the EFI partition and 1.5GB for the partition which would store kernels and initramfs. If your windows install is already UEFI then do not create a new Esp as you will already have one which you can use. The EFI partition is called ESP in the partitioner and the partition for kernels and initramfs should be given the mount point /boot.

Converting windows to boot using UEFI (skip if windows is already UEFI)

After this I quit the partitioner and returned to windows (booting from the existing MBR). Once in windows I used “diskpart” from command line to assign a drive letter to the EFI partition created in the previous step. Once a letter was assign I was able to use the “bcdboot” command to install a Windows EFI boot loader in the new EFI partition. This will allow me to boot windows in EFI mode instead of MBR. This also means that I will be able to select windows as an option in the GRUB bootmenu once installation is complete. If this step is skipped then one can still boot windows but the BIOS boot menu would need to be used as GRUB EFI cannot boot any OS which is using MBR.

Installation

There’s not much to say really. The only thing you need to be sure about is that on the partitioning step, you select the ESP partition as ESP and set the new boot partition to have mount point /boot. The whole of the M.2 can be set as mount point / unless you created some swap space which needs to be marked as swap. The installer will automatically set up GRUB on the ESP partition and create a boot entry for the GRUB in the UEFI BIOS. GRUB will also detect the windows loader created using “bcdboot” and add a windows 10 option in the grub menu.

Notes about MBR or Single OS install

If your BIOS doesn’t support UEFI (or apple EFI) then you need to use MBR for all partition tables and don’t need to bother with any kind of ESP partition. If you don’t want to dual boot then you still need at least one sata drive that the bios can see. You still need to make at least the two partitions (one boot, one ESP) on the sata disk and mark these correctly in the installer.

Helpful Sources of Information