I have an S5 and quite some programming experience, so I looked into it a bit... unfortunately I figured out that it's quite hard to start from scratch on ARM ASM and CHDK in general (I don't really know any of the CHDK code, though ARM ASM is quite easy... but still I get lost in the disassembly), so I couldn't really contribute there. All I really managed was to get some lights to blink in C and ASM, but that's nothing compared to what you did.
You should have seen me nervously happy running around in my room after having some LED blinking and realizing that a hack would be possible
So blinking some LEDs is still quite important (and looses importance only after the display works).
As you noticed, ARM Asm is fairly simple and easy to read, but there are still some powerful statements that might do three things intermixed with each other in five lines of code. I had to rewrite a fraction of code to clarify what it does more than once.
Anyway, if you need any help on the S5 part (I understand you do not have it), I'd be happy to help out whereever I can.
Right, I don't have an S5, I just have an A720.
So let's get you started.
You will need:
Firmware-dumps of S5IS, A720, A710 and maybe S3 or S2.
Reason:
S5 because it's your own (make sure that your cam has the same version as the dump)
A720 because it's the reference-dryos-firmware, lots of functions have been named and I use it for my CHDK-port
A710 because I use the A710-platform-dependent code as starting point for my port. There may be references to this model.
S3/S2 because S-Series cameras may do things totally different as A-Series (kbd-handling is said to be different) and you will need to merge S3/S2-chdk-code into my dryos-modified sources.
You find the files
http://www.zshare.net/download/590221805aee35/ and
http://www.zshare.net/download/3711689d229885/ (thx to GrAnd for uploading).
You also need CHDK trunk. I used it to start, made a copy of the A710-directories and removed everything else device-dependent (to minimize confusion). So neither clean A710 nor S2/S3-code is in the archives I posted and you will need to get them from a clean CHDK trunk.
I suppose you already read everything in the wiki. If you didn't then read at least the developer section. Useful information might also be mentioned in articles that don't obviously seem interesting (i.e. the camera articles).
Nearly forgot to mention: You need IDA, but I guess you already have it. You also need something to compile CHDK. I assume you have that also. I build CHDK in linux (
http://chdk.wikia.com/wiki/Compiling_CHDK_under_Linux). I also tried the win32 toolchain but it didn't compile CHDK!
Now you're ready to start.
What you do to get the port is basically:
- read a function in existing CHDK code
- find out how it interacts with the firmware
- read the part of the (Vx) firmware that it interacts with
- find the corresponding part in the (Dry) firmware
- change the CHDK function code to interact with the (Dry) firmware
To know how to proceed, here's a few details about CHDK:
- The entrypoint for the code is always the entry.S file. No libc, no "int main()".
- There are three entry.S files:
- loader/<dev>/entry.S: This is the starting point.
At this point, diskboot.bin has been load to 0x1900 by the firmware and needs to be relocated to a safe location.
This entry.S calls my_restart which calls code in loader/<dev>/resetcode.
There's a little glitch. my_restart defines a function called copy_and_restart. This one points actually to the next entry.S. - loader/<dev>/resetcode/entry.S
Calls copy_and_restart which relocates the CHDK-code, executes the restart-code and continues execution in the relocated CHDK.
The reset-code (asm-fraction) is a duplicate from the original firmware. Look for the string "Restart called".
At the end of the reset-code execution continues in the next entry.S
- core/entry.S
calls "startup()" in platform/generic/main.c. From here on everything is in its place and works like a normal c program. No weird relocations anymore.
- "startup()" calls "boot()" in platform/<dev>/sub/<ver>/boot.c
This function controls the boot process and calls functions that were relocated from the original firmware since they need minor modifications like changed addresses or just skipping of a particular function.
There are a couple differences between Vx and Dry in boot.c. Reasons:
- Both OSes have "Tasks". They are somewhat like processes on a full-blown OS, only here we have cooperative multitasking. It means that a Task has to call SleepTask to return control to the OS and allow other tasks to run.
- A new task is created by calling CreateTask and passing it a reference to the c-function that has to run as task as well as a descriptive name of the task.
- during Startup a number of tasks are spawned.
- VxWorks had a function called taskCreateHookAdd(cb) allowing an override to CreateTask. A callback would be executed if a new task has to be spawned. By knowing the function names it was easy to replace a few particular tasks by own ones.
- DryOs OTOH doesn't seem to have this function. This requires us to duplicate quite a lot of code from the firmware until we can change the CreateTask call.
- There's another reason why more code has to be duplicated than earlier needed: The diskboot-loader. In VxWorks a OS-function was used to create a device named "A/DISKBOOT.BIN". When the diskboot-loader tried to open the file of that name it got the device - not our file - thus preventing a boot loop. If DryOS had a function that allowed similar action it is at least not found (yet?). What I did was copying more code and just skipping the call to the diskboot-loader.
An important function is called "Startup" or "task_Startup" (as it is installed as task). It exists in both Vx and Dry and directly calls the diskboot-loader ("StartDiskboot") as well a task called "PhySw". The latter handles the keyboard and needs to be diverted.
CHDK also spawns a task called "spytask" which is the core of CHDK. I'm currently trying to figure out why this function doesn't even get called after CreateTask-ing it. Probably some stupid misunderstanding between source files.
To find out how task hooking worked in Vx, check createHook() in platform/generic/main.c
The things you will want to do now are
- Take my code (link at the end of the posting), duplicate/rename the A720-directories in loader/ and platform/ to S5IS. Don't forget the firmware-version in platform/s5is/sub/
- change makefile.inc to point to your camera and firmware-revision
- make fir (to test if compile works), resulting diskboot.bin is in bin/
- manage to get the resetcode to work. If you did this, you will find the rest by yourself.
Here's a few little hints to get things working:
- Use the LEDs to check if code is executed.
- Progress in little steps. ie. don't change the whole resetcode and boot.c at once but first add a jump to the original resetcode and see if you get a boot-loop.
Then duplicate the resetcode to your source and see if you still have a boot-loop.
Then change the jump at the end of the reset-code, change boot() to jump to the firmware start and check for boot-loop.
And so on until you get the camera starting.
Occasionally you will want to break out of the boot-loop to check if a complete startup still works. It's pretty unsatisfying if you duplicate all the boot-code until finally skipping StartDiskboot just to find out that the cam doesn't boot anyways.
This is what I did: I blinked an LED on startup, thus delaying the boot process by a short time. I also made some minor hack that allowed me to run the camera with opened battery/card-cover. This way I could remove the card after diskboot.bin has started, stopping the boot-loop and get a regular startup.
I hope I mentioned everything. If you still have questions: Just ask.
Edit:Nearly forgot the link:
http://www.zshare.net/download/6055482b209930/Cheers.[/list]