10

I'm trying to figure out how to do the equivalent of these instructions for creating an archlinux bootable drive on a Mac. (I'm using a Micro SD to USB adapter.) I found these instructions on partitioning a flash drive, but I'm not sure how to apply them, since the instructions I'm trying to "translate" into macOS terms talk about sectors, and that's very much a lower level than I'm used to working in. To be expressly clear, my question is this: how do I achieve the same stuff as in the instructions using macOS 10.12.6? Thanks!

6
  • Is there a .iso image of ArchLinux available, for the platform you need? Would make things a lot easier :-)
    – nohillside
    Dec 24, 2017 at 8:14
  • I tried looking for one and didn't find one, but I got a lot of spurious search results as well. I found a discussion forum thread (archlinuxarm.org/forum/viewtopic.php?f=47&t=7996) from a few years ago that referenced downloading an ISO for a different platform, but the link it goes to (archlinuxarm.org/platforms/armv7/samsung/…) no longer has an ISO.
    – Becca
    Dec 24, 2017 at 19:42
  • Your link is for ARM architecture processors. Mac's use Intel processors which have a x64 architecture. Are you sure you did not mean this web site? Dec 24, 2017 at 22:00
  • 1
    @davidanderson I assume the OP wants to use a Mac to create a boot image for an ARM device on an SD card.
    – nohillside
    Dec 25, 2017 at 13:11
  • @patrix: I figured that out. I am currently entering the procedure. Dec 25, 2017 at 13:31

2 Answers 2

9

There is no command in macOS to format a partition to use a linux file system. In other words, there is no equivalent for the Arch Linux mkfs.ext4 command. There are many possible solutions to this problem. Below is one such solution.

I propose that the best way, to accomplish the creation of the bootable drive, is to boot the Arch Linux operation system on your Mac. This will allow you to use the commands shown in the web link you provided. This boot of Arch Linux will be done from a 1 GB or larger flash drive. The advantage to using a flash drive is that you will not have to install Arch Linux on any of your internal drives.

Manual Approach to Creating a Mac Bootable Arch Linux Flash Drive

Note: You can copy and paste each command below into the Terminal application window. This will reduce the amount of typing and the risk of type errors.

  1. Download an .iso file. The Mac compatible file I chose to download is named archlinux-2017.12.01-x86_64.iso. You can find this file at this Arch Linux web site. This file was downloaded to my "Downloads" folder. I will assume you will do the same.
  2. Open a Terminal application window. Enter the following command to navigate to your "Downloads" folder.

    cd  ~/Downloads
    
  3. Convert this .iso file to a format that is compatible with flash drives. The command below accomplishes this task.

    hdiutil  convert  archlinux-2017.12.01-x86_64.iso  -format  UDRW  -o  target.img
    
  4. The .dmg characters may be appended to the output file name. Enter the following command to check if this occurred.

    ls  target.img.dmg
    

    If file named target.img.dmg appears, then enter the next command to rename this file.

    mv  -f  target.img.dmg  target.img
    
  5. Enter the command below to get a before list of drives.

    ls  /dev  |  egrep  ^disk\\d+$
    
  6. Insert your flash drive.

  7. Enter the command below again to get an after list of drives. Next, determine the identifier assigned to your flash drive (e.g. The identifier that did not appear in step 5)

    ls  /dev  |  egrep  ^disk\\d+$
    

    Note: In the subsequent steps, replace diskN with the identifier assigned to the flash drive.

  8. Enter the command below to unmount the flash drive.

    diskutil  unmountdisk  diskN
    

    Note: If you see the error Unmount of diskN failed: at least one volume could not be unmounted, open the Disk Utility application and unmount the volume(s) (don't eject).

  9. Enter the command below to copy target.img to your flash drive.

    sudo  dd  if=target.img  bs=1m  of=/dev/diskN
    

    Note the following:

    • This command will require you to enter your login password.
    • To view the progress of the copy operation, press the control+T key, while the command is executing.
    • Using /dev/rdisk instead of /dev/disk may be faster.
    • If you see the error dd: Invalid number '1m', you are using the GNU dd command. Use the same command but replace bs=1m with bs=1M.
    • If you see the error dd: /dev/diskN: Resource busy, make sure the drive is not in use. Open the Disk Utility application and unmount the volume(s) (don't eject).
  10. When the 'dd' command completes, you will receive the following pop up message. You should select "Ignore".

    e1

    Note: The the disk (flash drive) is readable by your computer. The message should have said: "The disk you inserted was not readable by macOS."

    To continue to the next part of this procedure, you will need to leave the flash drive plugged in. If you do need to eject the flash drive, you can either use the Disk Utility application or enter the command given below.

    diskutil  eject  /dev/diskN
    

Initialization of the Micro SD Card

The instructions, you referenced, assume the micro SD card is either uninitialized or has been MBR initialized with no partitions. You may want to preform the following steps to insure your micro SD card is properly initialized.

  1. Enter the command below to get a before list of drives.

    ls  /dev  |  egrep  ^disk\\d+$
    
  2. Using the adapter, plug the micro SD card into the Mac.

  3. Enter the command below again to get an after list of drives. Next, determine the identifier assigned to your micro SD card (e.g. The identifier that did not appear in step 1)

    ls   /dev  |  egrep  ^disk\\d+$
    

    Note: In the subsequent steps, replace diskN with the identifier assigned to the micro SD card.

  4. Enter the following command to initialize the micro SD card.

    diskutil  partitiondisk  diskN  1  mbr  free  none  r
    
  5. Enter the command below to unmount the micro SD card.

    diskutil  eject  diskN
    

Boot Your Mac to Arch Linux

  1. If the Mac bootable Arch Linux flash drive is not plugged in, do so now.
  2. Restart your Mac and immediately hold down the option key, until the Startup Manager appears.
  3. Select the icon labeled "EFI Boot", then select the arrow below the label.
  4. Select "Arch Linux archiso x86_64 UEFI CD" or wait for this to happen automatically.

A Note About Drive Identifiers

Hardware used by machines running the Linux, Unix, macOS and legacy OS X operating systems are given character string device identifiers. In the context of your question, we are only dealing with devices that are drives. The macOS operating system uses diskN to identify HDD, SSD, SD cards, micro SD cards, USB flash drives, etc. The value N is some integer greater than zero. The Arch Linux operating system uses a different scheme. Here, the form of the drive identifier is sdX, where X is a lower case letter in the English alphabet.

Micro SD Card Creation

Note: Since you are booting to a "Live" version of Arch Linux, I made some changes to the procedure you referenced.

  1. Insert a micro SD card into your computer and record which device identifier it is (dmesg | tail)
  2. Make sure it's not mounted (umount /dev/sdX* or umount /dev/mmcblk*)
  3. Start fdisk to partition the SD card:

    fdisk  /dev/sdX
    
  4. At the fdisk prompt, create the new partitions:

    a. Type n, then p for primary, 1 for the first partition on the drive, the return key to accept the default starting sectors, and +100M for the ending sector.

    b. Type t to set the type, then c to set it to FAT.

    c. Type n, then p for primary, 2 for the second partition, and press the return key twice to accept default values.

    d. Exit by typing w.

  5. Create and mount the vfat filesystem:

    mkfs.vfat  /dev/sdX1
    mkdir  boot
    mount  /dev/sdX1 boot
    
  6. Create and mount the ext4 filesystem:

    mkfs.ext4  /dev/sdX2
    mkdir  root
    mount  /dev/sdX2 root
    
  7. Download and extract the root filesystem:

    cd  ~/root
    wget  http://os.archlinuxarm.org/os/ArchLinuxARM-utilite-latest.tar.gz
    cd  ~
    bsdtar  -xpf  root/ArchLinuxARM-utilite-latest.tar.gz  -C  root
    rm  root/ArchLinuxARM-utilite-latest.tar.gz
    
  8. Copy boot files to the boot partition:

    cp  root/boot/*  boot
    
  9. Unmount the partitions:

    umount  boot  root
    
  10. Remove the micro SD card from your computer and insert it into the Utilite on the front panel

3
  • I really appreciate the thorough answer. Since I have access to a machine running Linux (a Chromebook with Gallium OS), rather than create a bootable USB drive for my Mac, I was able to use that. The most useful part of your answer was There is no command in macOS to format a partition to use a linux file system. In other words, there is no equivalent for the Arch Linux mkfs.ext4 command.
    – Becca
    Dec 26, 2017 at 2:50
  • Of course, I'm having issues unrelated to the partitioning (wrong version of bsdtar, among them), but it's a learning experience!
    – Becca
    Dec 26, 2017 at 2:56
  • I did not get any indication that the bsdtar command failed, but I have no ARM machine to test on. Dec 26, 2017 at 4:58
1

This is how you do it. This works with rpi of 1st, 2nd and 3rd generation.

I separated the code in bash functions to make it more readable, hopefully.

There may be extraneous mount/unmounts, but most diskutil action result in the volumes being auto-mounted by MacOS, so we need to unmount them before continuing otherwise the commands fail saying the resource is busy.

We need to install a few dependencies. This part is not as automated as I'd like it to be.

curl -OL https://raw.githubusercontent.com/yalp/homebrew-core/fuse-ext2/Formula/fuse-ext2.rb

Now edit that file and add to it after the caveat section:

  patch do
    url "https://github.com/alperakcan/fuse-ext2/files/2576060/0001-Fix-new-Xcode-compilation.patch.txt"
    sha256 "a2a8ff14f36754aead1745b4b5f53b0333376d1bf6abe659ec4eacdbb232aceb"
  end

Now we install the dependencies:

brew install \
    findutils \
    e2fsprogs \
    pv

brew install --head ./fuse-ext2.rb

sudo cp -pR /usr/local/opt/fuse-ext2/System/Library/Filesystems/fuse-ext2.fs /Library/Filesystems/
sudo chown -R root:wheel /Library/Filesystems/fuse-ext2.fs

sudo cp -pR /usr/local/opt/fuse-ext2/System/Library/PreferencePanes/fuse-ext2.prefPane /Library/PreferencePanes/
sudo chown -R root:wheel /Library/PreferencePanes/fuse-ext2.prefPane

Finally, this is the script to format the SD card. Copy paste this script, make it executable chmod a+x FILE and call it with two arguments DEVICE and MODEL.

The script is smart enough to propose you with correct values for DEVICE and MODEL.

#!/bin/bash

function require_device() {
    local device="$1"
    local usage="$2"
    local available_devices=$(get_available_devices)
    if [ -z "$available_devices" ]; then
        echo "$usage"
        echo
        echo "No compatible device found."
        exit 1
    fi
    if [ -z "$device" ] || ! contains "$available_devices" "$device"; then
        echo "$usage"
        echo
        echo "DEVICE must be one of:"
        echo "$available_devices"
        exit 1
    fi

    echo "/dev/$device"
}

function get_available_devices() {
    diskutil list external physical \
        | grep /dev \
        | cut -d" " -f1 \
        | cut -d/ -f3
}

function require_model() {
    local model="$1"
    local usage="$2"
    local available_models=$(echo -e "rpi\nrpi2\nrpi3")
    if [ -z "$model" ] || ! contains "$available_models" "$model"; then
        echo "$usage"
        echo
        echo "MODEL must be one of:"
        echo "$available_models"
        exit 1
    fi

    echo "$model"
}

function get_arch_filename() {
    local model="$1"

    if [ "$model" = "rpi" ]; then
        echo 'ArchLinuxARM-rpi-latest.tar.gz'
    elif [ "$model" = "rpi2" ]; then
        echo 'ArchLinuxARM-rpi-2-latest.tar.gz'
    elif [ "$model" = "rpi3" ]; then
        echo 'ArchLinuxARM-rpi-3-latest.tar.gz'
    else
        echo "Unsupported model $model"
        exit 1
    fi
}
function download_archlinux() {
    local model="$1"
    local filename="$2"

    echo "Checking if we need to download the latest ArchLinuxARM iso"
    curl --silent --location \
         --output "new-md5-$model" \
         "http://os.archlinuxarm.org/os/$filename.md5"
    local current_md5="$(md5sum "$filename")"

    echo "Newest md5:" "$(cat "new-md5-$model")"
    echo "Current md5:" "$current_md5"

    if [ "$(cat "new-md5-$model")" != "$current_md5" ]; then
        echo "We do, downloading in the background..."
        (
            if curl --silent --location \
                    --remote-name \
                    "http://os.archlinuxarm.org/os/$filename"; then
                echoerr "Download done."
            else
                echoerr "Failed to download."
            fi
        )&
        local process=$!
    else
        echo "We don't, continuing"
        local process=0
    fi

    return "$process"
}

function wait_for_download() {
    local process="$1"

    if [ "$process" -ne 0 ]; then
        echo "Waiting for download to finish."
        wait "$process" || exit 1
    fi
}

function untar_and_copy_arch() {
    local filename="$1"
    local device_dir="$2"

    echo 'Untaring into root.'
    if [ ! -f "$device_dir/root/root/.bootstrap" ]; then
        sudo sh -c "pv $filename | bsdtar -xpf - -C $device_dir/root" \
             && sudo touch "$device_dir/root/root/.bootstrap"
    fi
    sudo mv "$device_dir"/root/boot/* "$device_dir"/boot
    echo 'Running sync, can take a few minutes...'
    sync
}

function umount_device() {
    local tmp_dir="$1"
    local device="$2"

    diskutil unmountDisk "$device"

    if mount | grep "$tmp_dir/root" > /dev/null \
            || mount | grep "${device}s2" > /dev/null; then
        echoerr "Unmounting mounted root."
        sudo umount "$p2"
    fi
}

function mount_device() {
    local tmp_dir="$1"
    local device="$2"

    echo "Mounting $device root and boot on $tmp_dir"
    mkdir -p "$tmp_dir/root" "$tmp_dir/boot" || exit 1
    sudo diskutil mount -mountPoint "$tmp_dir/boot" "${device}s2" || exit 1
    sudo fuse-ext2 "${device}s2" "$tmp_dir/root" -o rw+ || exit 1
}

usage="$0 DEVICE MODEL"

device="$(require_device "$1" "$usage")" || exit 1
device_root="$("${device}s2")"

model="$(require_model "$2" "$usage")" || exit 1
filename="$(get_arch_filename "$model")"


download_archlinux "$model" "$filename"
process="$?"

umount_device "$tmp_dir" "$device"


diskutil partitionDisk "$device" 2 MBR \
        "MS-DOS FAT32" BOOT 100M \
        "MS-DOS FAT32" ROOT R \
        || exit 1
umount_device "$tmp_dir" "$device"

format_ext4 "$device_root" ROOT || exit 1

wait_for_download "$process"

sleep 3
umount_device "$tmp_dir" "$device"
mount_device "$tmp_dir" "$device"

untar_and_copy_arch "$filename" "$tmp_dir"

umount_device "$tmp_dir" "$device"

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .