Arch Linux, EFISTUB, Gummiboot, and the Apple Bootloader

I recently went through the setup of my favorite OS, Arch Linux, on a 2011 Macbook Air (Model: A1369) and decided to keep the Apple bootloader. The main reason I went down this route was because I wanted to keep the seamless appearance of an Apple product. Configuring rEFIt to boot OS X as the default would be easy enough to do and I highly recommend that approach if you’re not concerned about looks or having OS X as the default without a OS selection prompt. So yeah, I thought a how-to of the steps involved would possibly help others who want to do this but need a reference :)

The first step is getting your OS X partition(s) setup correctly and I felt the triple boot documentation was adequate enough to get the idea of what needed to be done. Here is the procedure (slightly modified for our purposes):

  1. In Mac OS X, run Disk Utility (located in /Applications/Utilities).
  2. Select the drive to be partitioned in the left-hand column (not the partitions!). Click on the partition tab on the right.
  3. Select the volume to be resized in the volume scheme.
  4. Decide how much space you wish to have for your Mac OS X partition, and how much for Arch Linux. Remember that a typical installation of Mac OS X requires around 15-20 GiB.
  5. Go ahead and resize the OS X partition leaving the empty space for Arch Linux later in the installation process.
  6. Finally, click apply. This will resize your partition and make room for Arch!

Next step is getting the arch install medium onto a usb drive. I followed the instructions listed on the USB Installation Media page. After you have the USB drive plugged into the laptop and reboot make sure to hold the ⌥ option key and select the usb drive as the boot option.

Great, now you should be presented with a shell prompt and automatically logged in as root.

NOTE: I’m making the assumption that your drive will be /dev/sda. It could very well be something completely different just be sure to double check with fdisk -l before you continue.

  1. Setup your wired/wireless internet connection (Establish an internet connection)

  2. Verify you’re booted into UEFI mode by running efivar -l. If efivar lists the uefi variables without any error, then you’re good to continue

  3. Run fdisk -l and verify /dev/sda1 is of type EFI system

  4. cd /boot and mkdir efi

  5. mount /dev/sda1 /boot/efi

  6. Run cgdisk /dev/sda and arrow down until you’ve selected the partition type free space

    • Choose New and when the tool prompts you for the First sector enter +128M (OS X likes to see a 128MB gap after partitions)
    • When the second prompt asks you for the Size in sectors press enter if you want to use the rest of the available disk space. If you don’t want to use the rest of the available disk space then enter the size here
    • Use Hex code 8300 (or press enter as 8300 is the default) for the Hex code or GUID prompt
    • Enter whatever partition name you would like to have–I chose Arch Linux as my partition name
    • Write the changes you’ve made to disk by selecting Write and typing yes when prompted
  7. After partitioning I rebooted then once I was back at a shell I formatted the Arch partition using the Ext4 file system mkfs.ext4 /dev/sda4

  8. Make sure pacman will use the mirror you want by editing /etc/pacman.d/mirrorlist. I personally prefer RIT because it’s my alma mater so the first line in my mirrorlist file is Server = http://mirror.rit.edu/archlinux/$repo/os/$arch

  9. Install the base system! pacstrap -i /mnt base and press enter for the prompts to install all packages

  10. Generate your fstab genfstab -U -p /mnt >> /mnt/etc/fstab

  11. chroot into your base system arch-chroot /mnt /bin/bash

  12. At this point I’m going to defer to the archwiki step of Chroot and configure the base system. Simply follow the wiki until you get to Install and configure a bootloader then continue back here

  13. So now the fun begins. Assuming you’re still in your chrooted setup run pacman -S gummiboot

  14. Run mkdir /boot/efi and mount /dev/sda1 /boot/efi

  15. cd /boot/efi run gummiboot --path=/boot/efi install and create /boot/efi/EFI/arch

  16. copy /boot/vmlinuz-linux, /boot/initramfs-linux.img, and /boot/initramfs-linux-fallback.img to boot/efi/EFI/arch/vmlinuz-arch.efi, boot/efi/EFI/arch/initramfs-arch.img, and boot/efi/EFI/arch/initramfs-arch-fallback.img respectively.

  17. cd /boot/efi/loader and edit the loader.conf file to be

    default arch
    timeout 10
    

  18. cd entries and create a file named arch.conf with the contents of

    title Arch Linux
    efi EFI/arch/vmlinuz-arch.efi
    options initrd=EFI/arch/initramfs-arch.img root=/dev/sda4 rw
    

    • NOTE: If you don’t set the initrd and root paths on the same line you’ll get an error along the lines of kernel panic-not syncing: VFS: unable to mount root fs on unknown block(0,0).
  19. reboot the computer and when prompted by gummiboot choose to boot OS X

  20. Once you’ve booted into OS X open a terminal and sudo bless -folder /System/Library/CoreServices -setBoot

    • NOTE: this sets the OS X default bootloader back to being the default bootloader
  21. Reboot and hold down ⌥ option key and select EFI BOOT then select Arch Linux

  22. enter your login information and mount /dev/sda1 /boot/efi && cd /boot/efi/loader

  23. edit loader.conf and remove the timeout that was set earlier. Reboot

  24. Congratulations! You now have a setup that will on default boot to OS X but if you want to boot into Arch all you need to do is hold down ⌥ option key and select the EFI BOOT option!

EDIT: One of the things you may want to do is setup systemd so it updates the kernel images on the EFI partition automatically. I won’t go into too much detail on this because the wiki does a pretty good job but definitely take a moment to checkout https://wiki.archlinux.org/index.php/EFISTUB#Using_systemd

Here’s the collection of sources I used while working this out:

Lander

Over the past couple of months I’ve been working on a side project to design a landing-type page which I finally finished about two weekends ago. Looking back, I now realize finding inspiration was a lot harder than I expected so I’ve decided to share some resources I found most helpful. But before I do, I wanted to talk about the design process I went through. My first effort which took several weekends resulted in this:

Initially I was really into the idea of a darker themed website as every dark website I’d ever seen had a nice look to it. However, as time went on I started to realize that picking the right color palette as well as the general criticalness that is a dark background can become a real difficult problem if you don’t know exactly what you want the end product to look like. I also felt it was lacking a somewhat professional touch and the fact that I still had two other full sections to design lead me to a redesign of the entire thing. The picture below is what I ended up with on a Saturday night after scrapping the entire project a day before.

Basically I had three major things I wanted to be prominent at first glance: content, ease-of-use, and elegance. With my initial design I missed the content part entirely so that became my focus in the resdesign. Other focuses of mine were to maintain responsiveness as well as really focus on interation rather than trying to perfect it the first time around. Anyways, here are some of the links I used for inspiration:

http://onepagelove.com/
http://www.designbombs.com/
http://www.awwwards.com/
http://www.siteinspire.com/
http://www.siiimple.com/
http://land-book.com/
http://www.cssdesignawards.com/

These sites are basically showcase sites that other designers have submitted. I also found http://www.reddit.com/r/graphic_design and its subreddits to be pretty useful as well.

Git Autocompletion and Bashthings

At my work we use Git as a VCS and while Git is very powerful, trying to remember all those little arguments can become tedious at best. Great, we established aliases, autocompletion, and Git alias autocompletion would be nice but how do we go about setting all that up?

The first thing you’re going to want to do is setup/install the git-completion.bash script

Next, add these entries into your .bash_profile (for OS X) or .bashrc (for Linux)

1
2
3
4
5
6
7
BASH_GIT_COMPLETION="/usr/local/etc/bash_completion.d/git-completion.bash"
GIT_PS1_SHOWDIRTYSTATE="true"
GIT_PS1_SHOWUPSTREAM="auto"
#bash completion
if [ -f `brew --prefix`/etc/bash_completion ]; then
     . `brew --prefix`/etc/bash_completion
fi

Note: the BASH_GIT_COMPLETION path will vary depending on your setup. As a note, these are my git aliases. Feel free to use them:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
alias g='git'
alias ga='git add'
alias gaa='git add -A'
alias gb='git branch'
alias gba='git branch -a'
alias gbam='git add . && git commit -am'
alias gc='git commit -v'
alias gca='git commit -v -a'
alias gcam='git commit -am'
alias gcm='git commit -m'
alias gco='git checkout'
alias gcount='git shortlog -sn'
alias gcp='git cherry-pick'
alias gd='git diff'
alias gdf='git diff --full-index master'
alias gf='git fetch'
alias gl='git log --graph --pretty=format:"%C(yellow)%h%Cred%d\\ %Creset%s%Cblue\\ [%cn]" --decorate'
alias glg='git log --stat --max-count=5'
alias glgg='git log --graph --max-count=5'
alias glp='git log --oneline --decorate'
alias gmt='git mergetool -t diffmerge'
alias gpo='git pull origin'
alias grh='git reset HEAD'
alias grhh='git reset HEAD --hard'
alias grm='git status | grep deleted | awk '\''{print $3}'\'' | xargs git rm'
alias gs='git status'
alias gsd='git svn dcommit'
alias gsr='git svn rebase'
alias gss='git status -s'
alias gsu='git submodule'
alias gup='git fetch && git rebase'

After you’ve added/source’d the aliases file into your .bash_profile you can insert/source the alias_completion script

alias_completion Source
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
function alias_completion {
local namespace="alias_completion"
local compl_regex='complete( +[^ ]+)* -F ([^ ]+) ("[^"]+"|[^ ]+)'
local alias_regex="alias ([^=]+)='(\"[^\"]+\"|[^ ]+)(( +[^ ]+)*)'"
eval "local completions=($(complete -p | sed -Ene "/$compl_regex/s//'\3'/p"))"

(( ${#completions[@]} == 0 )) && return 0

rm -f "/tmp/${namespace}-*.tmp" # preliminary cleanup
local tmp_file="$(mktemp "/tmp/${namespace}-${RANDOM}.tmp")" || return 1

local line; while read line; do
eval "local alias_tokens=($line)" 2>/dev/null || continue # some alias arg patterns cause an eval parse error
local alias_name="${alias_tokens[0]}" alias_cmd="${alias_tokens[1]}" alias_args="${alias_tokens[2]# }"

eval "local alias_arg_words=($alias_args)" 2>/dev/null || continue

[[ " ${completions[*]} " =~ " $alias_cmd " ]] || continue
local new_completion="$(complete -p "$alias_cmd")"

# create a wrapper inserting the alias arguments if any
if [[ -n $alias_args ]]; then
  local compl_func="${new_completion/#* -F /}"; compl_func="${compl_func%% *}"
  # avoid recursive call loops by ignoring our own functions
  if [[ "${compl_func#_$namespace::}" == $compl_func ]]; then
      local compl_wrapper="_${namespace}::${alias_name}"
      echo "function $compl_wrapper {
     (( COMP_CWORD += ${#alias_arg_words[@]} ))
     COMP_WORDS=($alias_cmd $alias_args \${COMP_WORDS[@]:1})
     $compl_func
 }" >> "$tmp_file"
  new_completion="${new_completion/ -F $compl_func / -F $compl_wrapper }"
fi
  fi
  new_completion="${new_completion% *} $alias_name"
  echo "$new_completion" >> "$tmp_file"
done < <(alias -p | sed -Ene "s/$alias_regex/\1 '\2' '\3'/p")
source "$tmp_file" && rm -f "$tmp_file"
}; alias_completion

Add PS1 prompt gaudiness

PS1 prompt Source
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
if [[ $COLORTERM = gnome-* && $TERM = xterm ]] && infocmp gnome-256color >/dev/null 2>&1; then
  export TERM=gnome-256color
elif infocmp xterm-256color >/dev/null 2>&1; then
  export TERM=screen-256color
fi
tput sgr 0 0

BOLD=$(tput bold)
RESET=$(tput sgr0)
SOLAR_YELLOW=$(tput setaf 136)
SOLAR_ORANGE=$(tput setaf 166)
SOLAR_RED=$(tput setaf 124)
SOLAR_MAGENTA=$(tput setaf 125)
SOLAR_VIOLET=$(tput setaf 61)
SOLAR_BLUE=$(tput setaf 33)
SOLAR_CYAN=$(tput setaf 37)
SOLAR_GREEN=$(tput setaf 64)
SOLAR_WHITE=$(tput setaf 254)

style_user="\[${RESET}${SOLAR_ORANGE}\]"
style_host="\[${RESET}${SOLAR_YELLOW}\]"
style_path="\[${RESET}${SOLAR_GREEN}\]"
style_chars="\[${RESET}${SOLAR_WHITE}\]"
style_branch="${SOLAR_CYAN}"

if [[ "$SSH_TTY" ]]; then
  # connected via ssh
  style_host="\[${BOLD}${SOLAR_RED}\]"
elif [[ "$USER" == "root" ]]; then
  # logged in as root
  style_user="\[${BOLD}${SOLAR_RED}\]"
fi

is_git_repo() {
  $(git rev-parse --is-inside-work-tree &> /dev/null)
}

is_git_dir() {
  $(git rev-parse --is-inside-git-dir 2> /dev/null)
}

get_git_branch() {
  local branch_name

  # Get the short symbolic ref
  branch_name=$(git symbolic-ref --quiet --short HEAD 2> /dev/null) ||
      # If HEAD isn't a symbolic ref, get the short SHA
  branch_name=$(git rev-parse --short HEAD 2> /dev/null) ||
      # Otherwise, just give up
  branch_name="(unknown)"

  printf $branch_name
}

# Git status information
prompt_git() {
  local git_info git_state uc us ut st

  if ! is_git_repo || is_git_dir; then
      return 1
  fi

  git_info=$(get_git_branch)

  # Check for uncommitted changes in the index
  if ! $(git diff --quiet --ignore-submodules --cached); then
      uc="+"
  fi

  # Check for unstaged changes
  if ! $(git diff-files --quiet --ignore-submodules --); then
      us="!"
  fi

  # Check for untracked files
  if [ -n "$(git ls-files --others --exclude-standard)" ]; then
      ut="?"
  fi

  # Check for stashed files
  if $(git rev-parse --verify refs/stash &>/dev/null); then
      st="$"
  fi

  git_state=$uc$us$ut$st

  # Combine the branch name and state information
  if [[ $git_state ]]; then
      git_info="$git_info[$git_state]"
  fi

  printf "${SOLAR_WHITE} on ${style_branch}${git_info}"
}

# Set the terminal title to the current working directory
PS1="\[\033]0;\w\007\]"
# Build the prompt
PS1+="\n" # Newline
PS1+="${style_user}\u" # Username
PS1+="${style_chars}@" # @
PS1+="${style_host}\h" # Host
PS1+="${style_chars}: " # :
PS1+="${style_path}\w" # Working directory
PS1+="\$(prompt_git)" # Git details
PS1+="\n" # Newline
PS1+="${style_chars}\$ \[${RESET}\]" # $ (and reset color)

Finally, man page stuff

1
2
3
4
5
6
7
8
# Setting colorized man pages
export LESS_TERMCAP_mb=$(printf '\033[38;5;92m') # enter blinking mode - red
export LESS_TERMCAP_md=$(printf '\033[38;5;84m') # enter double-bright mode - bold, magenta
export LESS_TERMCAP_me=$(printf '\e[0m') # turn off all appearance modes (mb, md, so, us)
export LESS_TERMCAP_se=$(printf '\e[0m') # leave standout mode
export LESS_TERMCAP_so=$(printf '\033[38;5;196m') # enter standout mode - yellow
export LESS_TERMCAP_ue=$(printf '\e[0m') # leave underline mode
export LESS_TERMCAP_us=$(printf '\033[38;5;208m') # enter underline mode - cyan

Latest hotness? Check out the github repo: https://github.com/andrewSC/bash_profile (´◔◞౪◟◔)

Euclid

SO, this Christmas I was gifted a couple computer parts for a tower refresh and this weekend I made some time to put everything together and install Arch Linux on it. Since it’s been quite some time since I had installed Arch a lot has changed and it took me a while to come around and figure stuff out. Seeing as I’m doing something a little one-offish I thought it might be nice to share what I did so people who might be trying to do roughly the same thing can see how I approached this beast.

The Setup

  • Asus Sabertooth X79
  • Intel i7 Sandy Bridge 3.6Ghz Quad Core
  • 32GB G. Skill DDR3 ram at 1600Mhz
  • (2) OCZ Vertex 4 SATA III drives

The OS

  • Arch Linux 2013.01.04
  • GPT
  • UEFI
  • efibootmgr
  • LVM2 (software raid-0 with two drives)

Steps

  1. Download the latest Arch Linux iso and dd it to your thumb drive. Since I run off of an MBA most of the time, OS X commands are a little different:

    diskutil unmountDisk /dev/disk1 dd
    if=/path/to/archlinuxisoyoudownloaded.iso of=/dev/disk1 bs=8192
    diskutil eject /dev/disk1
    
    More information can be found at: Archwiki - USB installation media

  2. Put that bad boy into a usb slot on your machine and boot it. Once you’re at the terminal and logged in as root (should automagically happen) go ahead and pull up gdisk for /dev/sda: gdisk /dev/sda In gdisk you’ll see:

    • Command (? for help):
      • Type n
      • Leave Partition number blank
      • Leave First sector blank
      • Type +1G for the Last sector field
      • Type EF00 for the Hex code

    Repeat the steps in 2 again but this time leave the Last sector field blank. For the Hex code you’ll want to type 8E00. Go ahead and write these changes to disk by typing w. You can verify everything was done correctly by using

    • fdisk -l
    • lsblk

    to verify the partitions are there. More info can be found here and here.

  3. Next we’re going to setup LVM2. Go ahead and type:

    pvcreate —dataalignment 1m /dev/sda2
    pvcreate —dataalignment 1m /dev/sdb1
    
    You can verify the physical volumes were created by typing pvdisplay

  4. Create the volume group:

    vgcreate VolGroup00 /dev/sda2
    vgextend VolGroup00 /dev/sdb1
    
    Again, you can verify everything went a-okay with vgdisplay

  5. Create the logical volume:

    lvcreate -L 220G VolGroup00 -n lveuclid
    
    You can change the size of the volume later if 220 Gigabytes isn’t your thing. Also, lveuclid is just what I’m naming this volume, you can name yours whatever you like.

  6. Create the file systems:

    mkfs.vfat -F32 /dev/sda1
    mkfs.ext4 /dev/mapper/VolGroup00-lveuclid
    

  7. Mount!!!!

    mount /dev/mapper/VolGroup00-lveuclid /mnt
    mkdir /mnt/boot/efi
    mount /dev/sda1 /mnt/boot/efi
    

  8. Install!!!! Make sure to put a fast server mirror in mirror list. Just add the Server = line to the top of the file:

    nano /etc/pacman.d/mirrorlist
    Server = http://mirror.rit.edu/archlinux/$repo/os/$arch
    pacstrap /mnt base base-devel
    
    From here on out I just followed the Beginners guide as it breaks everything down fairly nicely Arch Linux - Beginners guide Be sure to add lvm to your hooks array in mkinitcpio.conf and re-generate. Also, for efibootmgr just follow these steps: Arch Linux - UEFI bootloaders

NOTES

  • If you ever need to go back into the installer env. to do something on the LVM raid you created, to mount the LVM raid:
    modprobe dm-mod
    vgscan
    vgchange –ay
    mount /dev/mapper/yourlvmvolumenamehere /mnt
    
  • If you are trying to boot the volume be sure to use the UUID of the LVM volume NOT the partUUID as the archwiki suggests:
    root=UUID=yourguidhere
    

Honestly I’m pretty happy with this setup. You can see my boot times:

In terms of raw performance in read/write, I’m still working out the kinks but I’m getting around 600MB/s read and about ~460MB/s write. It’s not great but I’m sure there’s something I can tweak to pick these numbers up around the 900s like many people are reporting in windowsland.

Finally, many many extra credit andy points if you got the euclid reference (yes, it actually is my hostname). If you have any questions don’t hesitate to contact me (´◔◞౪◟◔)

Friendly Reminder

The single most important reason to create a routine is to reduce a program’s complexity. Create a routine to hide information so that you won’t need to think about it. Sure, you’ll need to think about it when you write the routine. But after it’s written, you should be able to forget the details and use the routine without any knowledge of its internal workings. Other reasons to create routines—minimizing code size, improving maintainability, and improving correctness—are also good reasons, but without the abstractive power of routines, complex programs would be impossible to manage intellectually.

A indication that a routine needs to be broken out of another routine is deep nesting of an inner loop or a conditional. Reduce the containing routine’s complexity by pulling the nested part out and putting it into its own routine.

p. 164 Code Complete

Trackpad, You Suck

Hi all,

So over the past month or so I’ve been having some pretty xtreme issues with my 2011 Apple Macbook Air 13” and to put it lightly, they could have been a real deal breaker if I hadn’t backed my data up. Basically it started with my laptop intermittently freezing. Now these freezes weren’t the easiest kind to diagnose because their timings were inconsistent/I couldn’t trigger the lockup through a series of repeatable actions. Basically the only way out of these things was to do a hard reset (I tried waiting out the pinwheel of death, iLost). Finally, after about three months of inconsistent lockups the SSD progressed to complete NAND/SSD controller failure.

Because I’m the genius that I am, I had everything backed up to a TimeMachine on my RAID 1 NAS so I didn’t lose any data but it did bring my productivity to a grinding halt for the rest of the day. I ended up spending the next six or so hours waiting for TimeMachine to restore the latest backup to the original SSD. Once that was done, I had my wheels back. OR SO I THOUGHT dun dun dun

About a week later I started having some very odd trackpad issues (f*** me, right?). The trackpad would emote from time to time and click-n-drag all the things or assume I was dragging my knuckles all over it in an attempt to click the proper tab on my web browser. Well, it got to the point where I had had enough and decided to take destiny by the reins (whoa)

First, I placed an order with iFixit

Second, I printed this guide.

Third, I disassembled my laptop:


Voilà! and that completes my trackpad superfuntime.gif replacement experience. Honestly I was expecting it to be much worse given the recent reviews about how Macbooks are becoming incredibly difficult to repair. However, compared to my Acer Ferrari 4000, this was painless.

Hmm, Where Were We?

Hi everyone!

Today is a pretty exciting day because I’m starting my own blog! Over the past several weeks I’ve had a real hankering to post what I’ve been working on academically as well as my personal Adventure Time adventures with Arch Linux system administration/installing things/computer. So besides posting all that cool geometric mess I want to work on these things, long termskis:

+Better writing/grammar in short format, for the win. Provide some way for others to see what I actually do when I’m too busy to brohang.exif Make notes for my future self so if I durp and have to redo something on an older machine I can be like: “Oh yeah, math that, this is how I did it”. As I think of more reasons to have a blog I’ll be sure to post them (´◔◞౪◟◔)