Well, let's rock
I don't know who can commit to the repository, so I decided to post it here.
In the attached archive you can find header files with internal task and context structures and with constants for the task states.
I have reversed task structures for the following OS's:
1. VxWorks 5.5, kernel WIND version 2.6 - this is all VxWorks based cameras
2. DRYOS version 2.3, release #0023 - based on analysis of A720 firmware
3. DRYOS version 2.3, release #0031 - based on analysis of SX10 firmware
4. DRYOS version 2.3, release #0039 - based on analysis of G11 firmware
Structures and constants for releases #0031 and #0039 are the same and located in the DryOS31.h
I think it's much better to see this code:
void createHook(task_t *pTcb)
{
if(!strncmp(pTcb->name, "tStartup", 10)) // Startup
{
pTcb->entry = (void*)startup_task;
}
// ...
}
instead of this one:
void createHook (void *pNewTcb)
{
char *name = (char*)(*(long*)((char*)pNewTcb+0x34));
long *entry = (long*)((char*)pNewTcb+0x74);
if (my_ncmp(name, "tSwitchChe", 10) == 0){
*entry = (long)mykbd_task;
}
// ...
}
Now I would like to say a couple of words about hooks in DryOS.
First of all - this technique was partially used by EWAVR in the SX10 and SX1 ports.
I want to explain completely how all this stuff works.
You can install task dispatch hooks by writing it's address to 0x1930 and 0x1934 dwords (0x1938, 0x193C for G11).
This hooks are called at dispatching events - task creation, sleep, exit or just task switching.
The difference between them is not clear enough.
There are two ways to terminate task (maybe more): call ExitTask() or just exit main task function.
When using different terminating methods - different hooks called.
I always install same hook function to both locations - 0x1930 and 0x1934.
The hook function prototype looks like this:
void dispatchHook(context_t **context).
The argument is pointer to (pointer to context) in the TCB - see header files.
The common hook routine looks like this:
// Dispatch hook, called at task create, sleep, ...
void dispatchHook(context_t **context)
{
// 'context' contains address of context pointer in task_t
task_t *tcb=(task_t*)((char*)context-offsetof(task_t, context));
if(!strcmp(tcb->name, "Startup")) // Startup
{
tcb->entry = (void*)startup_task;
}
// ...
}
I have completely changed A720 port to use only hooks - and everything works just fine.
Now you may ask - "Why it works?".
Really, dispatch hook is called every task switch, and we write entry point address every time.
So why it does not hang in infinite loop?
That's because entry point used only when task is created and restarted.
OS acts in this manner when creating task: it creates and initializes TCB and context, then call dispatch hook - here we modify entry point, and then OS copy entry address to PC in context and starts main task body.
Next, during normal work, entry point field of TCB is not used - program counter is stored in PC in context.
So our hook update entry point every task switch (to the same value), but who cares.
In such a way I want to thank to all who contributed to FIR and FI2 encoders development
And I want to ask you - if someone knows cameras with DryOS versions not mentioned here, please post links to firmware dumps.
I will reverse TCB structures for them too, it won't take much time.
PS: in header files structures does not have __attribute__((packed)) - this is done because of two reasons.
1. Structure members are 32-bit aligned, so we don't need this attribute.
2. GCC generates not optimal code for packed structures.
Even if structure address is aligned, and member offset is aligned to it's size - gcc generates code that read this member with series of LDRB and then merge them with shifts.
Removing "packed" attribute solves this, while offsets of members are still the same.