Since I seem to be the first person on the internet to tailor the camera firmware, I figured I should publish what I've learned.
Shameless plug: To everyone who doesn't normally read my blog, I gently nudge you to give naturism a try at some point in your life. 25% of Americans, and a much higher percentage of Europeans, already have. Once you get over the initial fears, it's rewarding and will change your life. You'll wish you tried it sooner. Find your nearest resort or free beach, dive in and give it a try.
Onward to the NX300 hacking! These same concepts should apply to the NX30, NX300M, and NX2000 cameras as well. Tread carefully through this guide, as installing a bad firmware image on your camera could kill it. Sending it in for repair can be costly.
Improving on op-code's table of key bindings, the two important ones which were missing are:
- Shutter half-press: keycode 133 (keysym 0xffeb, Super_L)
- Shutter full-press: keycode 134 (keysym 0xffec, Super_R)
So from any Linux machine, you can script taking photos and even grabbing a preview of those pictures:
xdotool keydown Super_L
xdotool keydown Super_R
xdotool keyup Super_R
xdotool keyup Super_L
xwd -out screenshot.xwd -root -display $DISPLAY
Note: The xwd screenshots cannot view the live image on the camera, but anything else is OK.
Compiling the Source Code
Attempts to build the source code in the Spring/Summer 2014 timeframe (v1.31, v1.40, v1.41) all failed, even after some email exchanges with Samsung. As-of v1.41, my suggestion is to use a machine with at least 15 gigs of space and use the username "openuser". I was using Lubuntu in VirtualBox. It helps to download and install Sourcery (free) too since their documentation mentions using it as the compiler.
I have a lot of notes, and followed two different sets of instructions. Each set required a lot more steps than Samsung lists in their guides. Things seem to go a lot easier if you have git access to their servers. I fixed a lot and made it petty far, but always ran into problems with SBS (Samsung Build System) while compiling. Hopefully someone will figure it out and post detailed steps.
With the v1.41 source, I performed a "make firmware" with the already-compiled binaries. The result was DIFFERENT than the released v1.41 firmware binary. I also noted that the v1.40 source had the v1.31 version.info file in it. Quite frankly, I don't entirely trust Samsung's open source packages.
Depending on how you want to enhance the camera, compiling probably isn't required.
Hacking the Firmware
The firmware (nx300.bin) consists of the following:
- vImage contents
- D4_IPL.bin contents
- D4_PNLBL.bin contents
- uImage contents
- platform.img contents
- Another header for pcache.list
- pcache.list contents
The main header consists of:
- Contents of version.info and some other stuff (0x0000 .. 0x003F)
- Metadata for vImage (0x0040 .. 0x004F)
- Metadata for D4_IPL.bin (0x0050 .. 0x005F)
- Metadata for D4_PNLBL.bin (0x0060 .. 0x006F)
- Metadata for uImage (0x0070 .. 0x007F)
- Metadata for platform.img (0x0080 .. 0x008F)
The header for pcache.list is similar to the metadata for the other files.
The metadata is four 32-bit values, each is in little-endian byte order:
- Size of the file.
- Start Location in nx300.bin.
- I assume where it goes in camera flash.
The CRC used is:
width=32 poly=0x04c11db7 init=0xffffffff refin=true refout=true xorout=0x00000000 check=0x340bc6d9 name="JAMCRC"
CRCs can be checked with jacksum:
jacksum -x -a crc:32,04c11db7,ffffffff,true,true,00000000 [file]
Note: The v1.40 platform.img CRC seems to be wrong, but the camera accepts it. All the CRCs for v1.31, v1.41, v1.42, and other files in v1.40 check out fine.
Pulling it Apart
Note: Linux is required for all of these steps. If you're stuck on Windows, you can use VirtualBox with a Lubuntu install. Or, any Linux LiveCD should work as long as you have a place for over 5 gigs of files.
Unzip nx300.tar.gz and pull out a few files into a new directory:
tar xvf nx300.tar.gz
cp ./TIZEN/build/fw_generator ./tailored_fw
cp ./TIZEN/project/NX300/image/rootdir_3-5/etc/version.info ./tailored_fw
(Note: The version.info file can be edited to specify a version or match an existing header. For this writeup, I'm using the v1.42 binary with the v1.41 source package. I'll modify the strings to match.)
Also put the "nx300.bin" firmware file in the tailored_fw directory. Rename it so it doesn't get overwritten:
mv nx300.bin nx300_original.bin
You'll need to write down the values from the nx300_original.bin metadata for each of the files. I use "vbindiff" to view the hex because it formats it neatly into 16-byte lines, which aligns perfectly for getting the values. Here's all the values for v1.42: (Remember that the pcache.list metadata is after the platform.img contents.)
vImage size: 0x004F4148 (5194056)
vImage CRC: 0xA54839A6
vImage offset: 0x00000090 (144)
D4_IPL.bin size: 0x00001B4C (6988)
D4_IPL.bin CRC: 0x3E2CDCC9
D4_IPL.bin offset: 0x004F41D8 (5194200)
D4_PNLBL.bin size: 0x0000F5D0 (62928)
D4_PNLBL.bin CRC: 0x1D3B7206
D4_PNLBL.bin offset: 0x004F5D24 (5201188)
uImage size: 0x0029E178 (2744696)
uImage CRC: 0xC46D6F14
uImage offset: 0x005052F4 (5264116)
platform.img size: 0x13D20000 (332529664)
platform.img CRC: 0xA353C393
platform.img offset: 0x007A346C (8008812)
pcache.list size: 0x00009000 (36864)
pcache.list CRC: 0x289E0951
pcache.list offset: 0x144C347C (340538492)
Extract each of the files from the binary with:
dd skip=[offset] count=[size] if=nx300_original.bin of=[file] bs=1
Where [file] is the filename, and [offset] and [size] are the respective integer numbers. Note: platform.img will take a while (an hour or so).
Optionally, check each of the CRCs with jacksum.
jacksum -x -a crc:32,04c11db7,ffffffff,true,true,00000000 *
3e2cdcc9 6988 D4_IPL.bin
1d3b7206 62928 D4_PNLBL.bin
289e0951 36864 pcache.list
a353c393 332529664 platform.img
c46d6f14 2744696 uImage
a54839a6 5194056 vImage
The easier way to make sure everything is correct is to reassemble the files and validate the new binary:
shasum nx300.bin nx300_original.bin
The checksums should match. If not, use vbindiff to figure out what might be wrong. Most likely, the version.info file doesn't match the firmware, or one of the files was extracted incorrectly.
Note: All of the files that were pulled from the nx300_original.bin file are used by fw_generator. It will open the files by the names listed above, and output "nx300.bin". So be sure to have the names correct and expect nx300.bin to be overwritten.
At this point, you're ready to edit the platform.img file and customize your camera.
You can't directly edit platform.img in a hex editor. It's a UBI image file which uses compression. But, you can mount it in a simulated device and reconstruct the file after you tailor the contents.
Backup your original platform.img file since it'll be overwritten:
cp platform.img platform_original.img
Obtain the UBI configuration file and put it in the tailored_fw directory:
cp ../TIZEN/project/NX300/image/ubi_rootdir.conf ./
FYI, the contents of ubi_rootdir.conf are:
Install the utility needed to work with UBI images.
sudo apt-get install mtd-utils
Simulating the UBI
I assume you're still in the tailored_fw directory. The steps below for simulating the NAND and recreating the platform.img file should all be done in one sitting. Rebooting gets rid of the simulated NAND device. Everthing below needs root access, so log in as root:
Create a simulated 512mb NAND flash with 2048 byte pages. Note that this uses RAM by default. Here, I include the cache_file parameter to use disk instead.
modprobe nandsim cache_file=./temp_nand.dat first_id_byte=0x20 second_id_byte=0xac third_id_byte=0x00 fourth_id_byte=0x15
Show it with:
dev: size erasesize name
mtd0: 20000000 00020000 "NAND simulator partition 0"
Copy the platform.img (original) over to the NAND:
dd if=platform_original.img of=/dev/mtd0 bs=2048
Attach UBI to the NAND MTD:
ubiattach -m 0 -O 2048
mount -t ubifs ubi0_0 /mnt/ubi
At this point, /mnt/ubi is a read-write directory with the camera software.
Although you can run scripts from the MMC, I'd like a more permanent solution. My update is to run a custom script from the read-write UBI1 partition on the camera, which is the same place where the settings seem to be stored. I can test the script from the MMC first, then move it to UBI1 when I'm comfortable with making it "semi-permanent". System boot seems to call /sbin/init (which is busybox), which calls /etc/init.d/rcS by default. Beware though, from trial and error, I found that rcS can't seem to access /mnt/ubi1 for a few seconds. (Tested with a 10 second delay, but the camera seems to fully boot in 2 seconds. I'm guessing 3 is fine.)
Edit /mnt/ubi/etc/init.d/rcS and add this to the end:
Then, root the device and copy in whatever script you want. It'll run when the camera boots. Best of all, you can tweak it without generating new firmware and reflashing the camera.
Repackaging the Firmware
FYI, the camera's MTD information is as follows. The numbers in the commands below come from here.
nx300:/# mtdinfo /dev/mtd4 -u
Eraseblock size: 131072 bytes, 128.0 KiB
Amount of eraseblocks: 3200 (419430400 bytes, 400.0 MiB)
Minimum input/output unit size: 2048 bytes
Sub-page size: 2048 bytes
OOB size: 64 bytes
Character device major/minor: 90:8
Bad blocks are allowed: true
Device is writable: true
Default UBI VID header offset: 2048
Default UBI data offset: 4096
Default UBI LEB size: 126976 bytes, 124.0 KiB
Maximum UBI volumes count: 128
Create the platform.img file with the following commands. You don't need to be root for these, and I assume you're in the tailored_fw directory.
mkfs.ubifs -r /mnt/ubi -m 2048 -e 126976 -c 3200 -o rootfs.ubifs
ubinize -o platform.img -p 128KiB -m 2048 ubi_rootdir.conf
It would be wise to put this new platform.img into a simulated NAND MTD just to be sure things look correct and that the UBI drivers correctly read the data. You'll need to reboot and follow the "Simulating the UBI" steps with this new file.
Then, rebuild the nx300.bin:
I'd also check to make sure the headers look correct:
vbindiff nx300_original.bin nx300.bin
Follow Samsung's steps for upgrading the firmware to install the tailored nx300.bin into the camera. Good luck!