Wednesday, December 23, 2015

Switching to tmpfs and unmounting root in Raspbian

This describes how to make a Raspberry Pi running Raspbian use RAM for the root file system. This allows you do things which cannot be done while the root file system is mounted, such as shrinking it with resize2fs. It would also allow you to write a totally new image to the SD card, overwriting everything. It might also allow you to swap SD cards and write an image to a different card, but I'm not sure that the SD card driver allows it. Here is the script:

cp -r lib bin sbin etc /mnt
mkdir -p mnt/usr/lib/arm-linux-gnueabihf
cp usr/lib/arm-linux-gnueabihf/libarmmem.so mnt/usr/lib/arm-linux-gnueabihf
# Move other mounts
mkdir mnt/dev
mount --move dev mnt/dev
# Pivot root using instructions from pivot_root(8) man page
cd mnt
mkdir old_root
pivot_root . old_root
# The current directory now seems invalid, so fix it
cd /
# Old root can only be unmounted once sh running from old root finishes.
# If enough was copied, you could continue startup normally using init.
exec old_root/usr/sbin/chroot . bin/sh

First, save the script somewhere. To use it, add init=/bin/sh to /boot/cmdline.txt and reboot. When the boot text finishes, you may not see the # prompt because of kernel output, but the shell should be running, and you'll get another prompt if you press enter.

You must run the script in the shell which is running as init, not a shell spawned from it. That is because the final line needs to end that shell. You won't be able to unmount old_root if you're still running a shell from it. So, for example if the script is /root2ram, use . /root2ram to run it.

The final line is the place where any errors will manifest themselves. You would get a kernel panic if chroot or sh can't run. If you're experience a problem, comment out the last line and look at the state of the system at that point.

The script is intentionally minimalist. All of Raspbian won't fit into RAM, so it only copies some parts. Some binaries in /bin and /sbin require libraries from
/usr/lib/arm-linux-gnueabihf/, and only the most commonly used one gets copied. The script does not umount old_root at the end so you can test whatever you want to run and copy anything else you need before manually unmounting it.

This has been tested on a Raspberry Pi 2 B running Raspbian Jessie. If you want to run it on a Raspberry Pi with less RAM, you might need to be more specific when copying from /lib. It is big and there are un-needed things there.

When you are done and you want to boot normally, simply remove init=/bin/sh from /boot/cmdline.txt. You would need to mkdir boot && mount boot. Vi is in /usr/bin, but sed is in /bin and you can use sed -i 's,init=/bin/sh *,,' /boot/cmdline.txt to edit it. Normal rebooting won't work without init, so umount /boot ; sync && reboot -f.

Thursday, December 17, 2015

WM_SYSCOMMAND SC_SCREENSAVE doesn't work anymore for activating the screen saver?

I use HoeKey as my hotkey program in Windows 7. One hotkey is supposed to activate the screen saver:

^`=Wait|1000
=Msg|0|274|61760|0      ; start screensaver


This waits one second to avoid the key release event, and then sends a WM_SYSCOMMAND SC_SCREENSAVE message. It failed a few times in the past, but it generally worked. Now it fails all the time. I wonder why?

This doesn't seem to be a HoeKey problem, because a trivial C program can't activate a screen saver this way either. However, SC_MONITORPOWER always works in both HoeKey and the C program, shutting off the monitor when lParam is 2.

In the past when it failed I thought it was due to the adaptive screen saver timeout, but disabling that doesn't help.

Emscripten 1.34.2 and later can reveal more alignment problems

Em-DOSBox started getting graphical corruption when built with recent versions of Emscripten. This was due to improper alignment of a statically allocated variable, which was declared as 8 bit values but also accessed as 16 and 32 bit.

Here is the Emscripten change which triggered the problem. It changes the alignment of variables which are allocated at compile time. Previously, they were 64 bit aligned. Afterwards, they are aligned as appropriate for their data type. 8 bit values don't need any alignment, and so they can end up improperly aligned for 16 and 32 bit access. This change is in emscripten-fastcomp, between 1.34.1 and 1.34.2 tags. Variable alignment depends on the build used during the final Emscripten link.

This is not an Emscripten problem, but an issue in DOSBox which started causing problems after that Emscripten change. If you think you may be dealing with an alignment problem, link the program with -s SAFE_HEAP=1. That will cause misaligned access to report and alignment error and throw an exception. You may also want to use a lower level of optimization or at least --profiling-funcs, so it is easier to find where the problem is occurring.

Thursday, December 10, 2015

Western Digital PM2 (power up in standby) was not useful

I have a 1TB WD1002FAEX Western Digital Black which used to by my main drive but is now just a data drive. Operating systems and commonly used data can all fit on the PNY CS1211 240GB SSD. As a result, the 1TB drive doesn't really need to spin up every time the computer turns on. Enabling power up in standby seems like a good idea.

Western Digital drives support power up in standby via a jumper, which they document in a PDF. The drive did not support setting of the feature using software via hdparm -s. This is probably wise. If power up in standby is enabled via software, you could end up in a situation where your operating system doesn't recognize the drive and you can't disable the feature. Such a drive isn't bricked, but you may need to connect it to a different computer running a different operating system in order to rescue it. A jumper is very easy to remove.

After placing the jumper, the drive didn't spin up when I turned on my computer, as expected. The Gigabyte GA-P35-DS3R F13 BIOS identified a hard drive there, but didn't identify what kind and didn't spin up the drive. There was a long delay before booting, but Linux successfully booted from the SSD. Linux spun up the drive and mounted the partitions on there. It complained about failing to spin up the drive, but I didn't notice any actual problems. So far, that is all okay. Then I put the computer to sleep and woke it up, hoping the drive wasn't going to spin up. Unfortunately, Linux spun it up. So, the drive remains usable with Linux, but this feature is pointless because Linux spins up the drive anyways.

Next, I tested Windows 7. It acted as if the drive was totally non-existent. Since it wasn't detected, other software couldn't be used to spin up the drive. This means power up in standby is totally incompatible with Windows 7. It could only work if the BIOS or a 3rd party driver spun up the drive during boot and after waking from sleep.

Wednesday, December 09, 2015

Comparing an Olympus Li-10B battery to a "1400 mAh" replacement

Both of these batteries had to be discarded because they were swelling. The Li-10B was purchased along with my Olympus C-770 Ultra Zoom camera in May 2005. I'm pretty sure the replacement was purchased from DX (DealExtreme) in January 2011.

I wanted to open them up for two main reasons: to see if it's possible to replace the cell, and to examine deception in the replacement. Both batteries were easy to open up by cutting along the seam. There are tabs, but I think the cases were welded or glued. Here's what's inside:
The Olympus Li-10B has a Sony cell inside, and the "1400 mAh" replacement contains a 750 mAh cell. It's probably decent quality, because in June 2013, after almost two and a half years of use, I measured 760 mAh.  The part number seems to be 063040AL.

In the original Li-10B, the cell fills the case. There is only some very thin double-sided tape on one side, and a bit of very thin insulating tape. The replacement contains a thick foam rubber spacer, and a thinner paper spacer. The cell thickness difference is easy to see. This is at least part of why the "1400 mAh" battery was lighter than the Li-10B.

Finally, here are the protection boards. The top is the original, and the bottom is the replacement. In the original board, the small black square is the control chip, and the much larger component is a low Rds(on) MOSFET. I'm not sure about the components in the replacement, or why one of the chips is cracked in a corner.

The replacement never had as much battery life as the original when it was new, and it probably wasn't much better than the already worn out Li-10B. However, at $5.18 US I can't say it was a ripoff, and it was helpful.

Preserving order when importing Internet Explorer Favourites

Internet Explorer stores its favourites as individual shortcut files in %USERPROFILE%\Favourites. Folders of favourites correspond to directories there. This is all easy to deal with, and other browsers can easily import it.

Ordering of favourites within a folder is stored separately, in HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\MenuOrder\Favorites. It uses an undocumented binary format. If you want to import into Internet Explorer elsewhere, you can simply export that branch of the registry using regedit, and then import it to restore the order. Exporting the ordering into other browsers is more difficult.

A CodeProject article explains the registry format. The code there is compatible with Windows XP and Vista, but not later versions. I also had some other problems, which I listed in a comment over there. Nevertheless, the code there was a very helpful starting point and only a few changes were needed.

The problem then is using the bookmarks.xml file, which is in XBEL format. Firefox is incapable of reading that format, and the XBELFox extension didn't work either. Debian had some XBEL tools in the past, but those depend on Python 2.1. I eventually ended up installing Konqueror and exporting to Mozilla format from there. That may seem like a ridiculously inefficient method, but it's much faster than spending more time searching for a suitable format conversion utility. Afterwards, it was easy to use dpkg.log to purge Konqueror and all of the KDE stuff it installed.

Tuesday, December 01, 2015

Windows 7 won't let you delete a hard-linked read-only file

Normally, Windows 7 file management ignores the read-only attribute. You can delete read-only files in Explorer or in cmd.exe command prompt without any need to remove the attribute. There is no additional prompting or notification, so it's effectively as if the attribute wasn't set. Some attempts to overwrite the file can be stopped by the attribute, so the read-only attribute isn't totally pointless.

When a file has hard links (or in other words, is associated with multiple directory entries), weird things happen. It seems as if there is one read-only attribute for the file itself which affects all of the file's directory entries, and an attribute cache associated with directory entries (file names). When you change the attribute for one name, you change it for all names, but attrib will give you incorrect old information for other names. The cache is updated when you attempt to overwrite or delete the file, and attrib will then provide accurate results.

If you try to delete a read-only file with multiple directory entries in cmd.exe, it will fail with "Access is denied." Explorer may fail to delete the file in some situations, incorrectly telling you that the file is in use.

Wednesday, November 11, 2015

Simple Linux boot repair by loading GRUB stage 1 from a file.

When booting on a PC with a legacy BIOS and MBR partitioning, Linux has a problem. At the start of the boot process, the BIOS can only load the first sector from the drive. That's only 512 bytes, and because it contains the partition table, only 446 bytes are available for code which could continue boot-up. The standard MBR code would load the first sector from the active partition, which is once again 512 bytes.

That's not enough space for GRUB, and it's not even enough space for code which could load a file from ext4 or other complex file systems used by Linux. The default solution is to put some more code right after the first sector, in the free space between it and the first partition. The BIOS loads the stage 1 code in the MBR, that code loads the stage 1.5 code which follows, and then finally it can load stage 2 from the Linux file system.

The problem is that it depends on GRUB stage 1 being in the MBR sector. When Windows and other operating systems are installed, they can overwrite stage 1 with their own code. The MBR code installed by Windows is reasonable. It will boot from whatever partition is active. However, if you installed GRUB in the MBR, the Linux partition is not bootable, so that won't help you.

There is plenty of information online on how to fix this by booting from removable media and re-installing GRUB. I'm proposing a much simper fix: load GRUB stage 1 from a file or write it to the MBR sector yourself. If you're running Windows you can take GRUB stage1 or boot.img files, put them somewhere on the Windows partition, and set up the Windows boot loader to boot them. In Windows Vista and later, you can do this via bcdedit. In earlier versions, it's just a single line of text in C:\boot.ini, like C:\stage1="GRUB stage 1".

If you want to write stage 1 to the MBR sector yourself, you can do that with a disk editor or dd in Cygwin. It's critical to remember to only overwrite the first 446 bytes, so you don't overwrite the partition table! This would mean using bs=446 count=1 arguments with dd. (If you overwrite the partition table, all is not lost though. TestDisk should be able to recover it.) GRUB stage 1 has some code after the first 446 bytes which doesn't get copied, but that code is only needed when booting from floppy. It's also critical to understand where you're writing, because writing to the wrong place could corrupt a file system! It is easier and safer to boot stage 1 from a file and then once booted into Linux use grub-install to do this.

On a system with multiple operating systems, I prefer installing GRUB in the Linux partition. In that situation, grub-install will complain about blocklists, and --force will be needed to make it install. The problem here is that the location of the file to load next is hard-coded in the boot sector, and if that file moves you can't boot anymore. It hasn't been a problem in practice when booting normally from a Linux partition. It is however a problem when using EasyBCD, because it makes a copy of the Linux boot sector which becomes out of date. My solution there is to chain load the Linux boot sector.