Well, there wasn't much (i.e. any) excitement about being able to log in to a shell on the PRS600 via USB, oh well.

Anyway, the "arbitrary code execution" so far has been rather academic. I figured out using the broadsheet driver to update the display, but I couldn't use the buttons or touchscreen, so couldn't write any interesting apps. Well, that's changed now. I can detect button press/release, and at least get touchscreen messages, though I'm not sure what they represent yet.

The "subcpu" appears to be a touchscreen/button controller wired to the second serial port of the iMX system-on-chip that the reader runs on. It's visible as /dev/ttymxc1 and is a standard character device.
The other serial port isn't connected, and there are posts by awesome russians disassembling their readers and getting a console by attaching needles to the first serial port pins. I do this over USB, without needles, and without the need for a login/password, but the idea is similar.

Communications with this controller happen in 8-byte blocks. The first byte of the raw message has bit 8 set, the other 7 do not. The messages are encoded in some weird form that involves either encryption or error detection or something.

Once decoded, you get a message. For the buttons, you get one for a press, and one for a release:

I found it kind of silly that three bytes change just to indicate a key release...
EDIT: but then I realised that the last two bytes are just checksums, and that a message only contains six bytes of actual information. D'oh. Time for bed.

Touching the touchscreen releases a flood of messages while you're touching it, and then a "released" message that gets repeated over and over until you send the subcpu an acknowledgement. It turns out that all messages which, when decoded, have bit 8 set in byte 0, should get an ACK. The ACK message is just the original message with two bits changed (which actually doesn't seem to matter, but I followed the firmware on this). To send messages to the subcpu, you need to encode them again.

So, please find attached code and the compiled executable which talks to the subcpu, reliably decodes messages and sends an ACK when necessary, properly encoded. The code is reasonably documented at the points I understand.

The encoding/decoding convolution is interesting, it was a pain to figure out from the disassembly. Now that it's in nice C code, if someone recognises what is might be, I'd love to hear your theory.

I don't really know how to answer. I don't think I discovered anything monumental, more of an increasingly coherent idea of how things fit together...

As far as the linux kernel and drivers were concerned, I didn't really know much at all. When trying to figure out the screen, I noticed there was a /dev/fb, which indicated a framebuffer device. Trying to write to it though did nothing. After digging a bit, I remembered that many devices are controlled through ioctl calls on their representative filenames. To figure out which driver it was, I pulled out the kernel messages (dmesg), and the kernel config which sony thanfully left in there (/proc/config.gz) and found that it was a "broadsheet" driver that they use. So to make the screen display the framebuffer contents I read the source code for the driver and found where the ioctl handling entry point was, and traced from there what info to give it to make the screen transfer, then had to look through it again when it froze the machine, until I figured out how to change the power mode. So reading over the souce code gave me a better idea of how drivers are written.

Also, the whole "USB gadget" and "USB on-the-go" stuff was something I didn't know about. The fact that a driver can make a device look like a disk, a serial port, a network card, etc, I find awesome. That OTG (on-the-go) can also flip things around and allow you to plug another device into your reader was cool too. In order to compile the g_serial module, I learned to cross-compile the kernel. Since sony modified the OTG drivers (but provided the modified source), I learned that the kernel attaches checksums to all kernel module symbols to prevent modules for a different kernel from being loaded. I also learned to build a kernel module by itself in a separate directory. I checked out what they modified, to see if it was anything interesting. I learned that for one USB gadget module to work, you need to unload the others. Then I had to dig through the init scripts in /etc/init.d looking for how to restore the g_file_storage module so that tinyhttp can come back to at least a marginally usable state. Also, you can just "create" a serial port with "mknod /dev/ttygserial c 127 0" and it magically works through g_serial when you connect the reader to a PC!

With ELF executables and dynamically linked modules, I basically had to learn how the whole dynamic symbol resolution mechanism works. It's actually quite complicated.The best info I've found was http://em386.blogspot.com/2006/10/re...e-symbols.html
I think I talked about this when I posted the first version of my disassembly-annotating tool. That tool is more advanced now, figures out returns, call sites, performs simple symbolic execution to find memory addresses and strings, as well as collecting a call graph. It can then export that call graph in DOT (graphviz) form which one can then plot into other formats (svg/pdf/png/whatever).

I'm attaching the latest version of the tool, as well as two partial graphs produced from it, for ebookSystem.so and ebook.so (these are the modules where all the hardware control happens). I'd advise against trying to view them in anything other than inkscape or an intelligent vector graphics viewer (e.g. ImgMagick runs the system out of memory).
I actually hacked together another simple program to generate those SVGs from DOT files with positioning such that inkscape sees the arrows as connectors (read: you can reposition nodes), but it's kind of dodgy.

So as you can see, it's been quite a learning adventure with my PRS600. Not to mention, I've read a lot on it too I honestly don't know if any of this helps or interests you, but, you're the author of PRS+, so I figured it's worth a shot. Also, I find it a lot of fun. I would drag everyone into it if they let me!

I wonder if your findings could help openinkpot guys (or other way round ).

So, to summarize, you know how to update the screen as well as how to decode button press events. The remaining "white spot" is understanding touchscreen messages.

My questions:

1) If tinyhttp is already started and has obviously opened /dev/ttymxc1 could an app that's started afterwards (without killing tiny) get access to it?

2) Do you (incidentally ) know how screen rotation works? I had an illusion, that it's done somewhere on driver level, and that code changing it's state is in ebook.so and if disassembled, it could be easily determined, whether rotating screen in the opposite direction was possible.

I wonder if your findings could help openinkpot guys (or other way round ).

OpenInkpot sounds interesting, but regarding the 505 and 600 they didn't get very far. Once I have the touch screen figured out, I may be able to suggest something. The general app concept looks interesting, and may well be worth porting to the PRS600.

Quote:

So, to summarize, you know how to update the screen as well as how to decode button press events. The remaining "white spot" is understanding touchscreen messages.

That's right. Other things that are left: interfacing to the battery/charger controller (to at least know how much battery is left), controlling sleep modes (e.g. telling the touchscreen to stop scanning for input), audio (this shouldn't be too hard, I think it runs ALSA and has a /dev/dsp).

I'd also like to put the functionality for running stuff off the SD card automatically upon its insertion into the porkupan firmware and maybe asking him release a new version with that in it, so I don't have to repeat the "hold VOL+ and HOME while inserting SD card" instructions every time.

Quote:

1) If tinyhttp is already started and has obviously opened /dev/ttymxc1 could an app that's started afterwards (without killing tiny) get access to it?

At first I thought the answer would be "no". However, I've logged in to the device via USB and forgot to kill tinyhttp, then ran my subcpu logging program and it worked fine. I think there's a possibility of losing the very first message it sends (e.g. you press a button, but only get a button release event), but after that it works reliably.

Note that this is while having tinyhttp run a script via the "fskLoad" mechanism, so tinyhttp thinks it's in the middle of loading a module/extension. If you were to actually run a daemon alongside a running tinyhttp, my guess would be that you'd get some subset of the messages, and tinyhttp would get the rest, which would be amusing. However, as I don't see the point running two UIs simultaneously, I guess the answer to your question is "yes"

Quote:

2) Do you (incidentally ) know how screen rotation works? I had an illusion, that it's done somewhere on driver level, and that code changing it's state is in ebook.so and if disassembled, it could be easily determined, whether rotating screen in the opposite direction was possible.

The question, however, becomes what this actually *does*. As far as I understand it, there are 480000 bytes in the frame buffer. This makes it possible to have 800x600, 600x800, and the "upside-down" variations for each. For switching from an orientation to its upside-down form, I'm guessing the software writing to the framebuffer doesn't need to do anything special, but obviously to rotate by 90 degrees, the "width" of the screen changes, so the software needs to adjust what it's doing. I can test this theory, but the soonest I can get back to you about it is in about a week.

If you just want to modify ebook.so to change its "sideways" rotation to be clockwise instead of counterclockwise, that should be doable.

In ebook.so, the assembly for EInkSetOrientation supports all four possible orientations (by the looks of it, it does a switch on some value, goes down four possible branches figuring out the new width and height of the screen, does an ioctl on the framebuffer device, then announces the new event to the Fsk world). Looking at ebookEinkDoRotate, it only supports two orientations: 0 and 1 (90 degrees). So changing it to be 2 and 1 would be trivial, however adding functionality to support all orientations, or even 0/1/2 would require more knowledge of the Fsk system than I currently have.

The problem is that I can't see the mapping between the functions I see at the assembler level and the functions at the Fsk level. This is because the Fsk thing loads up some bizarre structures into a strange array, then does stuff like in FskCore.xsb (using igorsk's DeFsk):

Code:

this.FskInclude.load = this.@[170]

I have no idea how to figure out what this corresponds to at the .so level. The 170 is arbitrary, and I don't even know which .so module it comes from. At a random guess ebookSystem.so, but I wouldn't be able to prove it. I showed it to a friend, who said it looks vaguely like the magic mozilla does with their XUL<->C interfacing, but he didn't have a clue how to resolve it either.
So, in conclusion, the best I can offer you with my current knowledge is an ebook.so that rotates to orientation 2 instead of orientation 0.

Quote:

3) Does device respond to power switch, if tiny is dead?

If you mean the power slider on the top of the device, then you can see from my log that it only registers as a normal button press/release. It is no longer linked to any power functions when tinyhttp is killed. Relating to your question 1, since opening up /dev/ttymxc1 works during an fskLoad event, the power slider also does not function in those circumstances (e.g. running a script from the igorsk/porkupan loader).

So if anything goes wrong, you'll be needing to poke the reset button with your stylus. This is why I like working through the shell, if I make a stupid mistake, I hit ctrl+z to background the program, ps to get its pid, and then I kill it. When I'm done, I execute poweroff which turns off the device.

So, in conclusion, the best I can offer you with my current knowledge is an ebook.so that rotates to orientation 2 instead of orientation 0.

If it's easy to do, I'd have ebook.so that rotates using 2 and 3. (sony already rotates screen by 90 degrees, so functionality is there at least for 180 degrees version) Even if there will be no progress on this, mount --bind-ing stuff would still work.

Oh, or even better, if rotating the screen could be done via call to external app, that basically solves the problem. I could rotate screen between 2 positions using javascript (so that UI correctly responds to it) and then call external proggy, that would add 180 degrees to it.

Quote:

this.FskInclude.load = this.@[170]
I have no idea how to figure out what this corresponds to at the .so level. The 170 is arbitrary

170 is an index in some table, I thought it was easy to spot what that table is, when examining ebook.so. Forgot, that xsb files also have such links, while NOT having any kind of symb table...

Not sure if I am mentioning something that you haven't already seen, but just in case:

Using "readelf -a" I can see that each of the functions mentioned above, seems to have corresponding eBook_* entry in .dynsym symbol table, eBook_rotate, eBook_doneSleep and so on. (ebookSubcpuDoRotate )

UPDATE:
Checked FskCore.xsb file, it contains NO additional information, only javascript symtable and bytecode... So the "system function" table is, uhm, outside. I'd bet on libtinyhttp.so's to contain such functions and on xs_System_loadExtension to correspond to FskInclude.load.

The function table is filled in a what I call "bind function" pointed by the structure at the fskGrammar symbol. In case of ebook.so, fskGrammar -> ebookGrammar -> "bind function". That function fills the "@" array with wrapped functions, constructors and destructors, usually taken from a table with the entries of the following format:

For example, in 600's ebook.so function @[0] is eBook_checkScreenLock, function @[1] is eBook_debugProcess and so on.
The actual functions all call into the Fsk bytecode machine and can be pretty hard to follow.

@kartu: I had a little time to test something today and I'm embarrassed to say I told you something which was wrong. You cannot reliably get data from /dev/ttymxc1 while tinyhttp has it open, I tested the wrong scenario. However, you can stop tinyhttp and then resume it when you're done with /dev/ttymxc1. I've just tested that and it works. Stopping:

Code:

kill -STOP 447

Resuming:

Code:

kill -CONT 447

(where 447 is the PID you want to stop/restart).
Sorry for any confusion caused.

@igorsk: thanks for that. From what I can see there is some kind of an array and every time an extension gets loaded it adds some pointers to functions to that array in FskLoad. Then the Fsk system just assumes symbols are in a certain order. I can't say I'm a fan of it... from what kartu and yourself are saying, it seems like an enormous amount of work to figure out, for example, how to add a C function to the Fsk javascript interface.

@igorsk: thanks for that. From what I can see there is some kind of an array and every time an extension gets loaded it adds some pointers to functions to that array in FskLoad. Then the Fsk system just assumes symbols are in a certain order. I can't say I'm a fan of it... from what kartu and yourself are saying, it seems like an enormous amount of work to figure out, for example, how to add a C function to the Fsk javascript interface.

Well, I'm sure the toolchain that Kinoma/Sony use provides a simple way to do that

However, it casts a shadow on my dream of having an FskRunSystemCommand instead of the fskLoad magic (which is I believe your creation; respect, dear sir!)

Since I've managed to get your attention, I was wondering if you had any thoughts on the "pressure" reading and why there are *two* numbers you get for it. I've almost got the touchscreen protocol figured out, but that's what I'm missing. If you go to the normal "test" screen (not our hacked one) and do the touchscreen test, you get the X and Y, rawX and rawY, and under "pressure" two numbers that make no sense to me.

kartu: I've looked at flipping the screen outside of tinyhttp. Interaction with the driver tells me that the flip succeeded, but when control comes back to tinyhttp it resets back to the normal orientation. Sorry. Here's the code and executable.

EDIT: I also edited ebook.so to play around with the orientation, but I'm not sure if those are the functions called (EinkSetOrientation and ebookEinkDoRotate) by Fsk. I only tried so far to restart tinyhttp with LD_PRELOAD, but that didn't work. Might need to do a proper mount --bind, but since I need to go sleep, I'll give the .so to you and maybe you'll have better luck than me.