Monday, August 12, 2013

I'm Thinking of Building This

Anyone know if it will work?


The USBGPIO8 is a USB-to-GPIO bridge.  Specs are here.  I want to use it to read the status of the front-panel buttons on my Thecus N5550 NAS.  (There are actually 4 buttons; the circuit diagram only shows 2 for clarity.)  I have established that the buttons are simple contact switches.

The circuit is inspired by the Background section of this article.  (This is using pull-down resistors, as shown in the lower diagram on that page.)

Other notes:
  • IO2 and IO4 are set to output/on; they provide the positive voltage that is detected when a switch is closed.
  • I have established through testing that all four positive connections (as I plan on using them) on the button module are wired together.
  • S0 is read on IO0; S1 is read on IO7.  (I probably wouldn't actually wire things up this way, but it makes the diagram clearer.)
  • The USBGPIO8 is powered (and grounded) through the USB connection.
If this is going to produce blue smoke, now would be a good time to post a comment.

Monday, July 1, 2013

Building ClockWorkMod Recovery for the Nook HD+

Now that I've set up a build environment, it's time to build ClockWorkMod Recovery (CWM) for my Nook HD+.

Get the Source Code

The CWM source code is part of the CyanogenMode source distribution.

$ mkdir src
$ cd src
$ repo init -u git://github.com/CyanogenMod/android.git -b cm-10.1

The Nook HD+ is not yet officially supported by CyanogenMod, so the repository containing device-specific files must be added.

$ mkdir .repo/local_manifests
$ wget -O .repo/local_manifests/verygreen_ovation_emmc.xml \
https://raw.github.com/verygreen/android_manifests/cm-10.1/NookHD-jb/local_manifest.xml

Now the source code (approximately 15 GB of it!) can be downloaded, along with any required pre-built binaries.

$ repo sync
$ vendor/cm/get-prebuilts

Build It

$ breakfast cm_ovation-userdebug
$ make -j8 recoveryimage

Now the Tricky Part

The previous step will create a file named out/target/product/ovation/recovery.img, which is nothing of the sort.  (It's actually a ZIP file containing a kernel and a ramdisk image, and the ramdisk isn't even in the required format.)  To make an actual recovery image, use the mkbootimg tool.

$ out/host/linux-x86/bin/mkbootimg --pagesize 4096 --base 0x80000000 \
    --kernel out/target/product/ovation/kernel \
    --ramdisk out/target/product/ovation/ramdisk-recovery.img \
    --output my-recovery.img

This will create a standard, bootable recovery image.  Sadly, a Nook HD+ will not boot a standard image, because of its locked bootloader.

CyanoBoot

CyanoBoot  is "second stage bootloader" that can boot a non-stock ROM or recovery on a Nook HD+.  It occupies the first 1 MiB (1,048,576 bytes) of the recovery partition, followed by the recovery image created in the previous step.  If ClockWorkMod Recovery has been successfully installed on a Nook HD+, CyanoBoot is already installed, and it's possible to simple write the new recovery image at a 1 MiB offset.

Personally, I prefer to create a "complete" image that can be flashed directly to the recovery partition; it strikes me as slightly less error-prone.  The first step is to extract the bootloader from the standard CWM ZIP file.

$ cd
$ wget http://nook.rootshell.ru/hd/cwm-recovery-ovation-2.zip
$ unzip cwm-recovery-ovation-2.zip recovery.img

$ dd if=recovery.img of=cyanoboot.img bs=1048576 count=1

Now the complete image can be created.

$ cat cyanoboot.img src/my-recovery.img > bootable-recovery.img

Installing and Testing

The recovery image is installed by writing it to the device's recovery partition.  After the image has been transferred (via adb or another mechanism), use a root shell on the device to issue the following command:

# dd if=bootable-recovery.img of=/dev/block/platform/omap/omap_hsmmc.1/by-name/recovery

(If installing a "standard" image that does not include CyanoBoot, skip the first 1 MiB of the partition by adding "bs=4096 seek=256" to the dd command.)

The new recovery image can be tested by powering the device off and booting into recovery with the power and home buttons.

Do not reboot directly into recovery via the reboot menu, ROM Manager, etc.  This will configure the device's bootloader to boot from the recovery partition.  If the recovery image is unbootable, the device will boot loop until it can be persuaded to boot from an appropriately formatted microSD card, which can be difficult.

Conclusion

With the build, installation, and testing process established. it's now time to start actually customizing the recovery image.  Thus far, I've simply changed the file system type of the SD card from FAT32 to ext4 by changing the corresponding field in device/bn/ovation/recovery.fstab.

Friday, June 28, 2013

Building Android on Fedora

Background

I've been waiting for a "Goldilocks" tablet for some time — something with a bigger screen than a 7-inch tablet but easier to hold with one hand than a 10-inch.  Barnes & Noble's Nook HD+ fits the bill, but I was never interested in running B&N's crippled flavor of Android.  (There was an early port of CyanogenMod for the Nook HD+, but it would only run off of a microSD card; it could not be installed on the device's internal storage.)  So I continued waiting.

Then I stumbled on this article, which led me to look into the current state of CyanogenMod on the Nook HD+, which led me to discover that it can now be installed on the device's internal storageBooyah!

I've had the Nook HD+ for about a week now, and it's exactly what I hoped for.  The 9-inch 1920x1280 screen is great for e-books and magazines, web browsing, and videos.  The dual-core 1.5 GHz OMAP processor and 1 GB of RAM are not world-beating, but they're perfectly adequate for these activities.  I don't share the complaints that some people have about occasional unresponsiveness.  (It probably helps that my previous tablet was a Nook Color.)  And unlike my wife's ASUS TF700, I can comfortably hold the Nook HD+ in one hand for several hours.
This is not a dig at the TF700.  It's an awesome device, with performance that blows away the Nook HD+.  Like every other 10-inch tablet that I've ever picked up, however, it's just bit too large and heavy to be comfortably held in one hand for an extended period.

The Problem ... and Project

Back to those videos ... I prefer to rip videos to DVD ISO files, rather than simple MP4s.  I actually enjoy a lot of the DVD extras — particularly commentary tracks.  I discovered an app called Wondershare Player that will play DVD ISOs on the tablet; just open the ISO file in File Manager, and it takes you to the DVD's main menu.

DVD ISO files are often larger than 4 GB, the largest file that can be stored on a FAT32 file system.  Microsoft has introduced a new file system called exFAT to address the limitations of FAT32 on larger flash drives.  (64 GB SD cards are generally pre-formatted as exFAT.)  Unfortunately, exFAT is both proprietary and heavily patent encumbered, so it won't be supported by open source software such as CyanogenMod any time soon.

But Android is Linux, and ext4 (the most widely used Linux file system) can store files as large as 16 TB.  Sure enough, CyanogenMod will happily use an ext4-formatted SD card.  The problem is that ClockWorkMod Recovery (CWM) will not; it is hardcoded to expect a FAT32-formatted partition.

This is where I get in trouble.  CWM is also Linux, so how hard could it be to make it recognize an ext4-formatted SD card?  It turns out to be very conceptually simple to change the filesystem type; it's a simple edit to CWM's equivalent of /etc/fstab.  The challenge lies in setting up an environment to actually build a modified recovery image.

Ubuntu, Fedora, or Both?

I've been a Red Hat/Fedora user for at least 15 years.  I'm not about to switch to Ubuntu just because that's what Google uses.  On the other hand, experience has taught me that it's pretty much impossible to build Android, including CyanogenMod, on either Red Hat Enterprise Linux or Fedora, and building ClockworkMod Recovery requires a CyanogenMod build environment.  (The CWM source is distributed as part of the CyanogenMod source.)

The usual solution to this problem is to create a full-fledged Ubuntu virtual machine.  This certainly works, but it limits the performance of the build environment in a couple of ways.  First, there's the overhead that comes from running in a VM, particularly when it comes to I/O.  Second, the VM can never use all of the resources of the host system; some amount of CPU, I/O, and memory has to be reserved for the host operating system.  If I create a VM with 24 GB of RAM (on my 32 GB workstation), that VM will never be able to use the remaining 8 GB of memory in the machine, regardless of whether the host operating system is doing anything useful with it.

Instead of creating a virtual machine, I decided to set up Ubuntu 12.04 LTS in a chroot.  chroot is not widely used these days.  It has (rightly) fallen out of favor as a security mechanism, and virtualization is usually an easier route to software compatibility.  For the reasons described above, however, it's a good tool for this particular use case.

Creating the chroot

After creating and mounting a file system for the environment (at /mnt/ubuntu), I used the debootstrap command to download and extract a minimal Ubuntu system.

# yum install debootstrap
# debootstrap --arch=amd64 precise /mnt/ubuntu

To provide the illusion of an actual running operating system, the chroot environment will need access to several bits of the larger filesystem tree.  (Remember that this setup is intended to provide software compatibility, not security.)

# mount -o bind /proc /mnt/ubuntu/proc
# mount -o bind /dev /mnt/ubuntu/dev
# mount -o bind /sys /mnt/ubuntu/sys
# mount -o bind /lib/modules /mnt/ubuntu/lib/modules

These can be added to /etc/fstab, if desired.  (The last one is required by the Android build process.  For some reason it insists on running depmod on the host on which it is running.)

Setting the Locale

# chroot /mnt/ubuntu
# echo 'LANG="en_US.UTF-8"' > /etc/default/locale
 

Adding User Information to the chroot

The chroot environment has its own copy of /etc/passwd and /etc/group.  Any non-root users that will use the environment must be added — with the correct UIDs and GIDs.


# groupadd -g 1000 pilcher
# adduser --uid 1000 --gid 1000 --disabled-password --gecos 'Ian Pilcher' pilcher
# su - pilcher
$ exit

Android Build Requirements

Android requires the schedtool package, which is in Ubuntu's "Universe" repository.  This repository must be added.

# echo 'deb http://us.archive.ubuntu.com/ubuntu/ precise universe' >> /etc/apt/sources.list
# apt get-update
# apt get install curl wget make bison schedtool python-software-properties git
# apt-get install g++-multilib flex xsltproc lib32z1 unzip gperf zip libxml2-utils

Building Android also requires Oracle Java 6.  As is their wont, Oracle have forced Canonical to remove the sun-java6 package from their partner archive.  They also make it painful to download it directly.  (No Larry, you can't have my firstborn son's social security number.)  Thankfully, these fine folks have created a couple of packages which do the dirty work for you.

# add-apt-repository ppa:webupd8team/java
# apt-get update
# apt-get install oracle-java6-installer
# apt-get install oracle-java6-set-default

Finally, download the repo tool.

# wget -P /usr/local/bin https://dl-ssl.google.com/dl/googlesource/git-repo/repo
# chmod 0755 /usr/local/bin/repo

Conclusion

That's it.  I now have an Ubuntu 12.04-compatible Android build environment.  To use the environment as my normal user, I do the following.

$ sudo chroot /mnt/ubuntu
# su - pilcher