Update: Raspbian now includes support for the Raspberry Pi 2; the linux-image-rpi2-rpfv
metapackage installs the raspbian kernel for Raspberry Pi 2, and automatically creates an initramfs during installation.
TL;DR I learn that the linux kernel has never supported LABEL= or UUID= root devices, it was being done by initramfs all along.
My Raspberry Pi 2 is on its way! :D
The plan is to use the microSD card from my old Model B, just drop in the new hardware. However, the Raspberry Pi 2 requires the latest firmware.
The current OS is raspian jessie, installed using raspian-ua-netinst. It’s just using the default kernel (linux-image-3.12-1-rpi
), with the default firmware (raspberrypi-bootloader-nokernel
), both installed using apt-get
. However, this won’t suport the Raspberry Pi 2.
I need to install the latest firmware using rpi-update
:
apt-get install rpi-update
rpi-update
All successful; no errors.
After rpi-update completes, the /boot folder now contains a second kernel, kernel7.img, which will be used by the Raspberry Pi 2. However, the Raspberry Pi 2 hasn’t arraived yet, so I keep using kernel.img for the current Raspberry Pi.
I update /boot/config.txt
, set kernel=kernel.img
and remove the initramfs
entry (since rpi-update
doesn’t make one).
All good, right? Time to reboot.
Nothing.
No disk activity on the root device (an external USB HDD, one of many attached to the system via a powered USB hub).
Hmm. I pop out the SD card and revert back to vmlinuz-3.12-1.rpi
(and initramfs). Works fine. Hmm.
I switch back to the new kernel.img
. Won’t boot. Hmm.
I change root=UUID=
to root=/dev/mmcblk0p2
. Works fine. With the new kernel.
I change it back to root=/dev/sda1
. It doesn’t boot, still no activity on the root device.
However, there is some activity on one of the other USB devices. Progress!
I boot using /dev/sda1
again, but this time I remove all the other USB devices first. Success! It boots fine!
Ok, so root=/dev/sda1
works fine, but root=UUID=
does not. I have a booting system, but I have to remove all USB devices every time I reboot. But what if I’m not onsite? Or what if there’s a power outage?
I need to be able to reboot the box without physical access. So why doesn’t root=UUID=
work?
Apparently, UUID
and LABEL
aren’t supported by the linux kernel. They never have, not on your kernel or mine.
root=LABEL=/
for years!The kernel doesn’t support it. The initramfs is what allows UUID
and LABEL
.
And that explains why the rpi-update kernel can’t find the root device: it doesn’t create an initramfs!
sudo update-initramfs -c -k 3.18.5+
And then set initramfs initrd.img-3.18.5+
in /boot/config.txt
The initramfs will need to be updated every time the kernel is updated. To be on the safe side, I’ve renamed kernel.img; if I forget to update-initramfs
before rebooting, at least it’ll still boot.
root=/dev/sda1
will work fine—just make sure you unplug other USB storage before rebooting!root=PARTUUID=
instead. (This is supported by the kernel—it’s needed for native UEFI boot).You want to take screenshots during the OS X recovery process.
The screencapture
command can be used to create screenshots from the Terminal.
(To launch the Terminal: hover the cursor at the top edge to show the menu bar, then select Utilities → Terminal).
Type the following:
screencapture -W /path/to/screenshot.png
then click the window you want to capture.
But wait— the recovery environment allows only one app to run at a time. If you want screenshots of Terminal, then this method works great. However, if you want screenshots of something else, you’re out of luck.
Fortunately, the recovery partition includes sshd. It’s not running by default, but starting it is easy:
/usr/sbin/sshd -o UsePAM=no
(The absolute path is required; if you leave it out, then sshd bails out with an error).
OK, but the root account has a random password. And you can’t reset it, since the filesystem is read-only.
You want to ssh into recovery, but you can’t set the root account password.
Pubkey authentication!
First, create a writeable ramdisk:
rdsize=$((16*1024*1024/512)) # 16 megabytes
dev=`hdik -drivekey system-image=yes -nomount "ram://$rdsize"`
echo $?; echo $dev # check for errors!
newfs_hfs "$dev"
eval `/usr/bin/stat -s /var/root` # store perms for old mountponit
mount -t hfs -o union -o nobrowse "$dev" /var/root # magic happens here
chown "$st_uid:$st_gid" /var/root
chmod "$st_mode" /var/root
Next, add your key to /var/root/.ssh/authorized_keys.
mkdir /var/root/.ssh
cat /Volumes/THUMBDRIVE/id_rsa.pub > /var/root/.ssh/authorized_keys
You can now use your private key to authenticate to sshd.
Quit Terminal, and the ssh sessions will remain connected. You can now use the screencapture
command at any time!
You can create screenshots in /var/root, but the ramdisk is only 16 megabytes. If this is too small, increase the rdsize
before creating the ramdisk.
Of course, since this is a ramdisk, all modifications will be lost upon reboot. You might want to save the screenshots to a USB device instead. (Or scp/sftp, etc).
Your ssh key should be located on the client machine at ~/.ssh/id_rsa.pub
. If it’s not there, it can be created using ssh-keygen. (You might also see a file called id_rsa
—that’s the private key; do not copy it).
I’m sure you can think of many other uses for ramdisks. :)
In /boot/config.txt:
initial_turbo=180
This disables dynamic overclocking for the first 180 seconds after boot. This should help devices to boot from a poor‑quality power supply.
My rasberry pi recently stopped booting after a (successful!) firmware update.
This fixed it.
#include <stdio.h>
int main()
{
printf("0.57 * 100 = %d\n", 0.57 * 100);
printf("Math is hard!\n");
return 0;
}
The Windows 8.1 Upgrade Assistant is running. Quit the upgrade assistant and try again.
I wish this was a joke.
For my own future reference:
python -m smtpd -n -c DebuggingServer localhost:25
Source: http://stackoverflow.com/a/6344240/2454476
sudo will be required for ports under 1024
Symptoms:
Oct 13 06:27:07 dl sshd[44354]: fatal: Access denied for user foo by PAM account configuration [preauth]
Solution:
If an entry is missing, you can create a new one using the passwd utility.
Alternatively, if no password is required, create a dummy entry like this:
foo:!:15991:0:99999:7:::
For more info:
man 5 shadow
Consider the following:
#!/bin/bash
month='08'
for m in $( seq 1 $(( ${month} - 1 )) ); do
rm "backupfile-${m}.tar.bz2"
done
When run, it produces the following error:
$ /bin/bash ./test.sh
test.sh: line 6: 08: value too great for base (error token is "08")
According to man 1 bash
:
Constants with a leading 0 are interpreted as octal numbers.
Solution 1: force the number to be interpreted as decimal:
#!/bin/bash
month='08'
for m in $( seq 1 $(( 10#${month} - 1 )) ); do
rm "backupfile-${m}.tar.bz2"
done
Solution 2: strip the leading zero:
#!/bin/bash
month='08'
for m in $( seq 1 $(( ${month#0} - 1 )) ); do
rm "backupfile-${m}.tar.bz2"
done
(or if there are multiple leading zeros:)
#!/bin/bash
month='08'
for m in $( seq 1 $(( $(echo "${month}" | sed 's/^0*//') - 1 )) ); do
rm "backupfile-${m}.tar.bz2"
done
Sometimes you want to boot a Mac from the network without running a netboot server. You already have a TFTP server set up, and the root image is sitting on a HTTP server. The only missing piece of the puzzle is how to get the Mac to boot from the network.
One option is to deploy an Apple netboot server.
Another option is to fudge it using a Linux DHCP server.
However, if you can’t do either of those things (or if you just don’t want to), then you only other option is to inject it directly into the Mac’s firmware settings.
Fortunately, the bless command has some undocumented arguments to make this easier.
This document assumes you have a netboot bundle on a server somewhere, and HTTP and TFTP already configured.
Netboot bundles will typically contain the following components:
i386/booter
i386/mach.macosx
and/or i386/x86_64/mach.macosx
i386/mach.macosx.mkext
and/or i386/x86_64/mach.macosx.mkext
i386/kernelcache
and/or i386/x86_64/kernelcache
NetInstall.sparseimage
and/or NetRestore.sparseimage
OS X 10.6 bundles typically have a booter, a kernel, and a root filesystem image. The bless command looks like this:
sudo bless --netboot \
--booter tftp://server/path/to/i386/booter \
--kernel tftp://server/path/to/i386/mach.macosx \
--options rp=http://server/path/to/NetInstall.sparseimage
The mkext doesn’t need to be specified; the firmware attempts to load it automatically.
This is explained in further detail in the Mactips article How to NetBoot Across Subnets.
Some time around 10.7 or 10.8, Apple removed the kernel and replaced it with the kernelcache:
sudo bless --netboot \
--booter tftp://server/path/to/i386/booter \
--kernelcache tftp://server/path/to/i386/x86_64/kernelcache \
--options rp=http://server/path/to/NetInstall.sparseimage
However, what if you want to boot to a Mountain Lion netboot image from
Snow Leopard? Unfortunately, the bless command in Snow Leopard
does not support the --kernelcache
option, and if you specify the
kernelcache in the --kernel
option, then the firmware treats
it as a kernel, which fails.
To get kernelcache working from Snow Leopard, you need to get creative:
sudo bless --netboot \
--booter tftp://server/path/to/i386/booter \
--kernel tftp://server/path/to/i386/x86_64/kernelcache \
--options rp=http://server/path/to/NetInstall.sparseimage
sudo nvram "$( sudo nvram efi-boot-file \
| sed -E 's/^efi-boot-file[[:space:]]*/efi-boot-kernelcache=/' )"
sudo nvram -d efi-boot-file
This command uses bless to put the kernelcache into the wrong nvram variable. Next, it uses the nvram command to copy the kernelcache into the correct nvram variable. Finally, it uses the nvram command to delete the incorrect variable.
The end result is the same as if the --kernelcache
option was
used in Mountain Lion.
This article by Pepijn Oomen describes how to get a netboot image to show up in the ⌥‑boot menu of the MacMini3,1, using nothing but the standard ISC‑DHCP server.
Why would you do this? Well, the ISC‑DHCP server is the standard DHCP server in many Linux distributions. :)
This method worked great until I updated the firmware on my iMac12,1. I could still boot the image, but it would not appear in the boot menu.
However, I was able to get it working by modifying the BSDP packet.
Pepijn’s configuration has the following characteristics:
option vendor-encapsulated-options
01:01:01: # bsdp_msgtype_list
09:0c:81:00:00:01:07:6e:65:74:62:6f:6f:74; # netboot
option vendor-encapsulated-options
01:01:02: # bsdp_msgtype_select
08:04:81:00:00:01; # bsdptag_selected_boot_image
This worked fine with the new firmware when the Mac was booted holding ‘N’, but to get it to appear in the ⌥‑boot menu, I had to make the following modifications:
# bsdp image list message:
# one image, plus one default image (both are the same)
option vendor-encapsulated-options
01:01:01: # bsdp_msgtype_list
04:02: # bsdp option code 4 (length 02) server priority
80:00: # Priority (32768)
07:04: # bsdp option code 7 (length 04) default image id
81:00:00:89: # Image ID (137)
09:0e: # bsdp option code 9 (length 0e) image list
81:00:00:89: # Image ID (137)
09:54:68:65:2d:49:6d:61:67:65; # Name (length 09) 'The-Image'
# details about the selected image
#
option vendor-encapsulated-options
01:01:02: # bsdp_msgtype_select
08:04: # bsdptag_selected_boot_image
81:00:00:89: # Image ID (137)
82:09: # Machine Name (length 09)
54:68:65:2d:49:6d:61:67:65; # 'The-Image'
… voilà! The image appears in the boot menu.
The following pages were extremely helpful when figuring out how to modify the bsdp packets:
Finally, I have included the entire dhcpd.conf below. It also includes a (commented) message list which contains multiple images. The two images appear separately in the boot menu, but I can’t figure out an easy way to differentiate between them during bsdp_msgtype_select.
#
# Apple BSDP server. Does NOT give out IP addresses
#
ddns-update-style none;
ddns-updates off;
ignore client-updates;
allow booting;
authoritative;
boot-unknown-clients on;
ping-check off;
one-lease-per-client on;
default-lease-time 7200;
max-lease-time 7200;
allow-unknown-clients;
subnet 0.0.0.0 netmask 0.0.0.0 {
pool {
# DON'T supply an IP address!
range 0.0.0.0 0.0.0.0;
allow members of "netboot";
}
}
class "netboot" {
match if substring (option vendor-class-identifier, 0, 9) = "AAPLBSDPC";
option dhcp-parameter-request-list 1,3,17,43,60;
if (option dhcp-message-type = 1) {
option vendor-class-identifier "AAPLBSDPC";
option vendor-encapsulated-options
08:04:81:00:00:89; # bsdp option 8 (length 04) -- selected image id;
} elsif (option dhcp-message-type = 8) {
option vendor-class-identifier "AAPLBSDPC";
if (substring(option vendor-encapsulated-options, 0, 3) = 01:01:01) {
log(debug, "bsdp_msgtype_list");
# bsdp image list message:
# one image, plus one default image (both are the same)
option vendor-encapsulated-options
01:01:01: # bsdp_msgtype_list
04:02: # bsdp option code 4 (length 02) server priority
80:00: # Priority (32768)
07:04: # bsdp option code 7 (length 04) default image id
81:00:00:89: # Image ID (137)
09:0e: # bsdp option code 9 (length 0e) image list
81:00:00:89: # Image ID (137)
09:54:68:65:2d:49:6d:61:67:65; # Name (length 09) 'The-Image'
# bsdp image list message:
# TWO images, plus one default image (both are the same)
#option vendor-encapsulated-options
# 01:01:01: # bsdp_msgtype_list
# 04:02: # bsdp option code 4 (length 02) -- server priority
# 80:00: # Priority (32768)
# 07:04: # bsdp option code 7 (length 04) -- default image id
# 81:00:00:89: # Image ID (137)
# 09:1b: # bsdp option code 9 (length 1b) -- image list
# 81:00:00:89: # Image ID (137)
# 09:54:68:65:2d:49:6d:61:67:65: # Name (length 09) 'The-Image'
# 81:00:04:31: # Image ID (1073)
# 08:44:53:52:2d:31:30:37:33; # Name (length 08) 'DSR-1073'
#
# option-boot lists both images, but the "root-path"
# below is hardcoded! So it doesn't actually support
# both images -- it'll always boot the first image. :(
} else {
log(debug, "bspd_msgtype_select");
# details about the selected image
#
option vendor-encapsulated-options
01:01:02: # bsdp_msgtype_select
08:04: # bsdptag_selected_boot_image
81:00:00:89: # Image ID (137)
82:09: # Machine Name (length 09)
54:68:65:2d:49:6d:61:67:65; # 'The-Image'
if (substring(option vendor-class-identifier, 10, 4) = "i386") {
filename "/osx/i386/booter";
next-server 10.25.64.32;
option root-path = "http://10.25.64.32/build.sparseimage";
} elsif (substring(option vendor-class-identifier, 10, 3) = "ppc") {
filename "nil";
}
}
}
}
Update 06 Feb 2013: Brandon’s Tinkerings has a solution for handling multiple images correctly. Awesome! :)
Update 21 Feb 2013: The server priority is in fact BSDP option 4, not option 2.
Update 09 April 2014: Brandon’s Tinkerings appears to be offline. :( Mirror here.
Update: Brandon’s Tinkerings is back up again! :)
Boot into single user mode (⌘S), and run the following commands:
# Mount the filesystem; start opendirectoryd:
/sbin/fsck -fy && /sbin/mount -uw /
launchctl load /System/Library/LaunchDaemons/com.apple.opendirectoryd.plist
# Create the user account:
dscl . -create /Users/localadmin
dscl . -create /Users/localadmin UserShell /bin/bash
dscl . -create /Users/localadmin RealName "Local Admin"
dscl . -create /Users/localadmin UniqueID 502
dscl . -create /Users/localadmin PrimaryGroupID 20
dscl . -create /Users/localadmin NFSHomeDirectory /Users/localadmin
# Create the home directory:
cp -R "/System/Library/User Template/English.lproj" /Users/localadmin
chown -R localadmin:staff /Users/localadmin
# Set the password:
dscl . -passwd /Users/localadmin newPassword
# Grant admin access (optional):
dscl . -append /Groups/admin GroupMembership localadmin
You may see this error message, but don’t worry, it can be safely ignored:
launchctl: Couldn't stat("/System/Library/LaunchDaemons/com.apple.DirectoryServicesLocal.plist"): No such file or directory
nothing found to load
To get the next unused UniqueID, run this command:
maxid=$(dscl . -list /Users UniqueID | awk '{print $2}' | sort -ug | tail -1)
newid=$((maxid+1))
echo $newid
To get the group id for the staff group, run this command:
dscacheutil -q group -a name staff
(make a note of the uid — usually 20)
Sources:
http://support.apple.com/kb/HT4749
http://serverfault.com/questions/20702/how-do-i-create-user-accounts-from-the-terminal-in-mac-os-x-10-5
Interesting.
Nice tutorial.
I wrote a SyntaxHighlighter plugin for ini, inf, and reg files.
See it in action here.
Why do it the easy way?
Update: I originally wrote this post because of an overflow bug which caused files over 2GB to fail silently, and the fix hadn’t yet been released. Well, the fix has now been released, so it’s probably a better idea to use that version, since this portfile does not work properly with selfupdate.
Install and configure macports. Note that selfupdate doesn’t work from svn.
Create a local repository:
mkdir -p ~/ports/net/cntlm/files
Copy the Portfile and patch to the repository (contents below):
cp /path/to/Portfile ~/ports/net/cntlm cp /path/to/patch-trunk-Makefile.diff ~/ports/net/cntlm/files
Configure the local repository. Add the following line to /opt/local/etc/macports/sources.conf, then sync the repository:
file:///Users/localadmin/ports
sudo port -d sync
Install cntlm:
sudo port -v install cntlm
# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4 # $Id$ PortSystem 1.0 name cntlm version HEAD license gpl categories net platforms darwin maintainers xs4all.nl:hbruinsma homepage http://cntlm.sourceforge.net/ description Cntlm is an NTLM / NTLM Session Response / NTLMv2 authenticating HTTP proxy svn.url https://cntlm.svn.sourceforge.net/svnroot/cntlm/cntlm/trunk svn.revision HEAD fetch.type svn worksrcdir trunk patchfiles patch-trunk-Makefile.diff depends_lib port:coreutils build.target {} build.args SYSCONFDIR=/opt/local/etc BINDIR=/opt/local/sbin \ MANDIR=/opt/local/man destroot.args SYSCONFDIR=/opt/local/etc BINDIR=/opt/local/sbin \ MANDIR=/opt/local/man startupitem.create yes startupitem.name cntlm startupitem.executable "${prefix}/sbin/cntlm"
-- Makefile 2011-10-14 19:45:26.000000000 +0800 +++ Makefile.old 2011-12-06 17:11:08.000000000 +0800 @@ -44,10 +44,10 @@ install -M 644 -f $(MANDIR)/man1 doc/$(NAME).1; \ install -M 600 -c $(SYSCONFDIR) doc/$(NAME).conf; \ else \ - install -D -m 755 -s $(NAME) $(BINDIR)/$(NAME); \ - install -D -m 644 doc/$(NAME).1 $(MANDIR)/man1/$(NAME).1; \ + install -m 755 -s $(NAME) $(BINDIR)/$(NAME); \ + install -m 644 doc/$(NAME).1 $(MANDIR)/man1/$(NAME).1; \ [ -f $(SYSCONFDIR)/$(NAME).conf -o -z "$(SYSCONFDIR)" ] \ - || install -D -m 600 doc/$(NAME).conf $(SYSCONFDIR)/$(NAME).conf; \ + || install -m 600 doc/$(NAME).conf $(SYSCONFDIR)/$(NAME).conf; \ fi @echo; echo "Cntlm will look for configuration in $(SYSCONFDIR)/$(NAME).conf"
Note that macports does not recommend building from subversion, since the results will not be reproducible. However, for testing, it should work fine.