[HTC Pico (Explorer)] no.human.being:
Not exactly. It's a bit more complicated and we aren't even all that certain. I'm gonna explain it.

We know that on Android phones with Qualcomm chips there are two operating systems running all but concurrently in two separate domains. For all intents and purposes, these two separate domains appear to the software that's running within them as separate processors and each of these runs its own operating system, which in both cases is a flavor of Unix. One of these domains is called mARM (for "modem ARM") and the other is called aARM (for "application ARM"). The operating system running on mARM is called Iguana and the operating system running on aARM is called Android. The Android system uses a (forked) Linux operating system kernel, which is a monolithic kernel, while the Iguana system uses an operating system kernel that's called L4/Pistachio, which is a microkernel.

Now there are two possible scenarios and we're not absolutely certain which of these is correct (or possibly none of them is):

1. The Qualcomm chip comes with a very small, "class one hypervisor" (which means a hypervisor that runs directly on the hardware, on "bare metal", with no operating system underneath) or even "class zero hypervisor" (a hardware-supported "class one hypervisor") that's embedded into the processor's microprogram stored in on-chip (and probably read-only) micro-store. This "class zero/one hypervisor" designates small time slices to each of the "domains" (mARM and aARM) so that it appears as if both were actually running concurrently. So the lowest layer is the hypervisor and both operating systems are running on top of it. If the chip is powered up, the hypervisor loads both operating systems and starts executing them. To each operating system it looks like it was running on dedicated hardware. On top of Iguana, there runs a proprietary software called AMSS that implements the GSM/UMTS modem functionality. The Radio is the combined "mARM firmware image" (Iguana operating system and AMSS software), while the hypervisor is completely "distinct" (microprogram in on-chip micro-store).

2. The Qualcomm chips come with Iguana as their "low level operating system". When the chip is powered on, Iguana boots, then loads AMSS and a "class two hypervisor" (which is a hypervisor running on top of an operating system) for running Android. The hypervisor moves an HBOOT image from the Iguana file system into the first page of the virtualized "guest" and then starts executing the "guest code".

The Qualcomm datasheets tell us that aARM and mARM are actually separate processors on a single chip, so that the MSM chips are basically "dual core processors" with one core running Iguana and the other core running HBOOT/Android. From the software point of view, this scenario would be indistinguishable from scenario 1 (aARM and mARM being separate domains running on a "class zero hypervisor" on top of common hardware in a time-shared manner) and the "class zero hypervisor" theory makes a lot more sense, since Iguana is a very stripped-down operating system (compared to Linux/Android) and basically does only low-level functions and does not consume a lot of ressources, so it makes no sense to give it a dedicated processor to run on, as it does nothing that's actually computationally intensive, so running on virtualized hardware and giving 95 % of the processor time to Android and 5 % to Iguana probably makes a lot of sense from the economical point of view.

Our reverse-engineering on the other hand indicates (but does not actually provide a hard proof) that what's actually happening is much closer to scanerio 2. While in scenario 1, both Iguana and HBOOT/Android run concurrently, in scenario 2, they are "stacked" and HBOOT/Android is "a child of Iguana", so that Iguana much closer "control" over what HBOOT/Android is doing, e. g. because each memory request by HBOOT/Android is trapped by the hypervisor and is then handled by the complete virtual memory system of the L4/Pistachio kernel. This gives Iguana a lot of "control" over what HBOOT/Android is doing and therefore allows for easy implementation of the "NAND locks" and the "virtual Radio area" that HBOOT/Android sees, since each memory read or write that is performed by the aARM domain (so by either HBOOT or Android) gets "trapped" by the hypervisor and then handled in software. This handling can be as involved as it gets, it may even "dynamically generate" the content that the "load" instruction retrieves. It also explains, why phones are can hard-brick when the Radio image gets damaged. No Radio means no Iguana and no Iguana means no hypervisor and that means nothing that could run a bootloader.

Now, whatever the case, the fact is that Iguana and the hypervisor cannot distinguish HBOOT from Android (or therefore any code that's loaded and executed by HBOOT). After all, HBOOT is in fact a very simple piece of firmware (it only appears to be extremely complicated, since we analyze it on the machine code level ;) ). All it does in a normal boot is read the contents of the "boot" partition from NAND, extract the "kernel_addr" and "ramdisk_addr" from the header, then begin reading from "beginning of kernel image inside boot partition" and write to "kernel_addr" until you've read/written "kernel_size" bytes, then begin reading from "beginning of ramdisk image inside boot partition" and write to "ramdisk_addr" until you've read/written "ramdisk_size" bytes, then get the processor into the state that a Linux kernel (Android is based on Linux) expects the processor to be in (supervisor mode, interrupts disabled, MMUs disabled, data cache disabled, r0 initialized to 0, r1 initialized to "processor_type", r2 initialized to a pointer to "tags_addr") and branch to "kernel_addr". So the bootloader is basically just a bunch of loops that read something from NAND and write it to RAM and then jump into it. There are a few more diagnostic functions and you can also load code directly from the host into RAM for execution using USB and the Fastboot protocol, but that's basically "extra gimmicks to make development easier". The core functionality is "read code from NAND, write it to RAM, then jump into it". In this sense, it's a lot like our "chainloader", which "reads code from RAM, writes it somewhere different in RAM, then jumps into it".

Since Iguana or the hypervisor have no idea where the transition from "bootloader running" to "kernel running" is (it's just a jump instruction after some loops), they cannot actually "know" what's running on aARM (unless the hypervisor performs some very close inspection of memory contents of its "guest", but this is highly unlikely, the hypervisor probably won't care at all what the guest is doing). They cannot distinguish HBOOT from Android or an exploit or another HBOOT or whetever. This means that "all HBOOT can do, all code that comes after (e. g. Android) could do as well", it's just that a Linux kernel is not DESIGNED to, say, flash a bootloader. We can make it try to flash a bootloader by mapping the HBOOT partition, but if we try to perform an "erase" operation on it (NAND must be explicitely erased before it can be written), then the hypervisor traps and says "this is protected system memory, you may not erase it" and then Linux says "ok, forget it", while HBOOT would say "yeah I know, I'm authenticating". The bootloader doesn't actually care what kind of code it loads, so if we knew how to perform this authentication and how to write to NAND using machine code, we could make our exploit flash its payload directly instead of executing it. The problem is that writing to NAND is quite a complicated procedure and authenticating probably even more, so we don't try to do it directly from the exploit, but load a piece of code that has already implemented it properly (a bootloader). ;)

No, we perform the dump from aARM's domain (the guest), so we don't see the entire host with Iguana and the file system. This means we cannot run the host, we can only run the guest. Remember the guest (HBOOT) runs inside a hypervisor, so it doesn't "see" the host (Iguana) unless it specifically communicates with it through shared memory. The virtualization is transparent, so HBOOT and Android think they are running on dedicated hardware and Iguana is "non-existant". Therefore, I would just recreate the "inner part" (guest), and forget about everything else. Just take what the guest sees as NAND content, then either use an HBOOT image as the kernel image and let it run from physical address zero or use a "concatenated chainloader + HBOOT as payload binary" (not Android boot image!) as the kernel image and let it run from physical 0x12c08000.

Remember that the contents of "unmapped memory" are "generated on the fly" when the read occurs. When you get a read error, there are probably some pages that are not normally read and therefore the virtualizer knows no useful content for them. If we have any way of skipping these pages and filling them with "page_size" (probably 2048) bytes of 0xff (which is the value that NAND memory has when it's fully erased) we're probably fine. If we cannot read from it, probably no software on aARM will ever read from it. We just have to find a way to skip reading these pages without aborting the dump and filling them up in the dumped image file with "page_size" bytes of 0xff so that the memory contents remain properly aligned.

If it works, that would be nice. After all, "dd" is designed to work with binary data, while "cat" is not. On the WFS CWM recovery, the "dd" utility was broken and could not read/write from/to "mtd" (NAND) devices, which is why we used "cat" and that turned out to work nicely on our recovery image.