chdk in the DIGIC6 world

  • 130 Replies
  • 38425 Views
Re: chdk in the DIGIC6 world
« Reply #110 on: 04 / August / 2017, 09:27:25 »
Advertisements
Hi,
after dumping my G3X back in 2015, I finally got back to try porting it.
I am not yet confident enough, if I will make progress in near future, therefore I think it is too early to open a dedicated 'G3X porting thread yet'.
But I have some general questions regarding [digic 6] porting.

1) Digic 6 firmwares using thumb mode require function addresses with bit0 set.
Therefore, I simply did this for now and ORed bit0 to 1:
Code: [Select]
NHSTUB(malloc, 0xFC381480|1)But if I now run the sigfinder again, the stubs_entry.S will contain the following line:
Code: [Select]
//NHSTUB(malloc                               ,0xfc381481) //  0        *** != 0xfc381480So, it complains about my action?

What is the correct way to handle thumb addresses?


2) What *stubs* files should be generated by the sigfinder?
Currently, I only get stubs_entry.S.
stubs_entry_2.S is created by me, okay.
But what about stubs_auto.S and stubs_min.S?


3) Referencing functions in the binary by their 'default' name:

Code: [Select]
"    blx     sub_FC31BE9C\n" // -> ExitTaskResults in:
Code: [Select]
capt_seq.c:(.text+0xc4): undefined reference to `sub_FC31BE9C'To I have to add any reference to sub_[0-9a-f]{8} to stubs_entry_2.S as NHSTUB?

Many more questions, but I try to do little steps ;) :)

*

Offline srsa_4c

  • ******
  • 3474
Re: chdk in the DIGIC6 world
« Reply #111 on: 04 / August / 2017, 12:20:57 »
1) Digic 6 firmwares using thumb mode require function addresses with bit0 set.
Therefore, I simply did this for now and ORed bit0 to 1:
Code: [Select]
NHSTUB(malloc, 0xFC381480|1)But if I now run the sigfinder again, the stubs_entry.S will contain the following line:
Code: [Select]
//NHSTUB(malloc                               ,0xfc381481) //  0        *** != 0xfc381480So, it complains about my action?
It's simple: the sigfinder expects a regular number, not an expression. Since it can't parse the OR operation, it will work with the number it found.
Usual practice is that stubs, that are found correctly, don't need to be overridden in stubs_entry_2.S.
Quote
What is the correct way to handle thumb addresses?
If your method is accepted by the compiler then I guess you can continue doing that.
You can also take a look at the existing D6 ports in the source.
Quote
2) What *stubs* files should be generated by the sigfinder?
Currently, I only get stubs_entry.S.
That's the only stub file that is generated.
Quote
stubs_entry_2.S is created by me, okay.
But what about stubs_auto.S and stubs_min.S?
Entries in stubs_entry_2.S and stubs_min.S are for overriding stubs_entry.S, or providing stubs/addresses that are not found automatically.
stubs_auto.S should be re-generated during build. This fails to happen sometimes, and you get build errors like
Quote
Code: [Select]
"    blx     sub_FC31BE9C\n" // -> ExitTaskResults in:
Code: [Select]
capt_seq.c:(.text+0xc4): undefined reference to `sub_FC31BE9C'
Solution: delete stubs_auto.S manually and rebuild.

edit: make sure that the source file containing asm is listed in
STUBS_AUTO_DEPS
in the port's makefile.
Quote
To I have to add any reference to sub_[0-9a-f]{8} to stubs_entry_2.S as NHSTUB?
No.
« Last Edit: 04 / August / 2017, 12:24:38 by srsa_4c »

*

Offline srsa_4c

  • ******
  • 3474
Re: chdk in the DIGIC6 world
« Reply #112 on: 08 / August / 2017, 16:18:49 »
Another POC, (ab)using the mzrm system. Since there are unused message IDs on the Xtensa side, it is possible to replace the NULL entries in the message handler table with pointers to our custom functions. I chose ID #1.
Addresses are for sx280 102b.
Code: [Select]
// mzrm_create's typical return pointer is 0xBFF004D8
int mzrmtrial1(int a1, int a2, int a3) {
    extern int* _mzrm_create(int handle, int type, int id, int length);
    extern int _mzrm_send(int handle, int* msg);

    int * p = _mzrm_create(*(int*)0x17f8c, a1, a2, a3); // the firmware uses 0x17f8c as the pointer to the handle
    if (a3>3) {
        *(p+3) = 0xcafecafe;
    }
    return _mzrm_send(*(int*)0x17f8c, p);
    //return (int)p;
}

void mypoke1() {

    char myprg[] = {
    0x36, 0x41, 0x00,      // entry     a1, 32
    0xA2, 0x22, 0x00,      // l32i      a10, a2, 0
    0xA0, 0x2A, 0x20,      // or        a2, a10, a10
    0x1D, 0xF0,            // retw.n   
    0x00
    };

    memcpy((void*)0xbff25800, myprg, 12);
    *(int*)0x80a001d4 = 0xbff25800; // msg1 (dodgy, xtensa has a cache too)
}
Code: [Select]
NHSTUB(mzrm_create, 0xFC254691)
NHSTUB(mzrm_send, 0xFC25476D)
After compilation, I looked up the address of mzrmtrial1() and mypoke1() and used them in chdkptp, with call_func_ptr.
mypoke1() copies a short function to the TCM-like code memory of the Zico core. I'm using a location in its unused part (the 0xbff20000 blob ends earlier than 0xbff25800). the word at 0x80a001d4 is the second entry in the message handler table, it is NULL originally.
My Xtensa message handler returns the first word of the message (or something random if the message is zero sized). Surprisingly(?), the return value is actually passed back to the ARM side and becomes the return value of mzrm_send.

This is one possible way to execute code on the Xtensa. The other way is to modify the blobs before the Zico core is started. zicokick_start (the routine that copies the Xtensa blobs) does attempt to call an optional function pointer for logging purposes - that would very likely be usable as a point to hijack the routine and modify the binaries.

*

Offline reyalp

  • ******
  • 10949
Re: chdk in the DIGIC6 world
« Reply #113 on: 08 / August / 2017, 17:17:05 »
Nice work again :D

One potentially interesting thing would be if there are CPUID type instructions that would tell us more about how the Xtensa is configured.

It might also be relatively simple to hook existing handlers to ignore messages at certain times, though it wouldn't be surprising if that had fatal side effects.
Don't forget what the H stands for.


*

Offline Ant

  • ****
  • 318
Re: chdk in the DIGIC6 world
« Reply #114 on: 08 / August / 2017, 17:57:34 »
I found that Xtensa sometimes generates an interrupt (0x145) during its operation. Its ISR also sets an event flag.
Is this used for messages' "flow control" ?
Are there another ways to inform ARM core about Xtensa activity?

In attachment you can find M3 log taken in playback mode without OSD.
Only "Low Battery" icon is flashing.

P.S. I am using _exmem_alloc() for debug buffer. It gives me 8 or 16 MB at least.
But how to get from memory the argument for "rmem" function in chdkptp?

*

Offline reyalp

  • ******
  • 10949
Re: chdk in the DIGIC6 world
« Reply #115 on: 08 / August / 2017, 22:17:02 »
P.S. I am using _exmem_alloc() for debug buffer. It gives me 8 or 16 MB at least.
But how to get from memory the argument for "rmem" function in chdkptp?
Assuming you store the address in a global variable, you can get the address of the variable from the platform/.../sub/.../main.bin.dump of your build, and rmem or peek that.
Don't forget what the H stands for.

*

Offline srsa_4c

  • ******
  • 3474
Re: chdk in the DIGIC6 world
« Reply #116 on: 09 / August / 2017, 12:25:55 »
One potentially interesting thing would be if there are CPUID type instructions that would tell us more about how the Xtensa is configured.
The closest I could find so far is the PRID (processor ID) register which reads 0x21c0. But I'm afraid that doesn't tell anything.

The one use (idea) I could come up with is using Xtensa side malloc to get some nice allocations (I don't currently know the available pool sizes though).

Are there another ways to inform ARM core about Xtensa activity?
If a somewhat larger latency is okay, you could use the 0xbff00000 region's unused space (the region is 0x8000 bytes long) and poll the address on the ARM side.

*

Offline srsa_4c

  • ******
  • 3474
Re: chdk in the DIGIC6 world
« Reply #117 on: 12 / August / 2017, 12:39:24 »
Some notes on Xtensa related stuff.

Getting a toolchain is not as easy as for ARM. One has to decide prior to compilation, which core / configuration the built binaries should support.

I'm not sure if we need a full toolchain, so I started by building an assembler.
I found a repo that may or may not have better support for this architecture:
https://github.com/jcmvbkbc/binutils-gdb-xtensa

The following change needs to be made before starting the build process:
In include/xtensa-config.h, find the line with
Code: [Select]
#define XCHAL_HAVE_BE and change it to
#define XCHAL_HAVE_BE 0
to make the resulting binaries (including the assembler) little endian. All endianness options of the built binaries are ineffective.
The assembler can also make changes to the generated code, so the rest of that config header may need to be reviewed to increase compatibility with the core we have...
To build binutils and the assembler,
configure with
./configure --target=xtensa-none-elf --disable-nls
then run make.


*

Offline reyalp

  • ******
  • 10949
Re: chdk in the DIGIC6 world
« Reply #118 on: 27 / October / 2017, 01:44:09 »
I noticed in digic 7 firmware, the dry shell prompt for the main DryOS ROM is

Dry[MusaPUX]>

Rather than

Dry[MARIUS]>
Don't forget what the H stands for.

*

Offline philmoz

  • *****
  • 3049
    • Photos
Re: chdk in the DIGIC6 world
« Reply #119 on: 05 / November / 2017, 00:56:15 »
I noticed a possible issue with the Digic6 build changes while working on the G5X port.


The FONT_WIDTH and FONT_HEIGHT values change in gui_draw.h based on the THUMB_FW value.


Unfortunately gui_draw.h is included by lib/font/rbf_font.c and many of the modules & games.


All the lib & module code is supposed to be platform independent and is only built once by the autobuild process (based on the first camera settings - A1000).


This means that for an autobuild the Digic6 cameras will have the wrong value for the font size built into the lib code and the module code.


Edit: Ignore the above. As reyalp pointed out the build system should take care of this.


I think it would be better to keep the FONT_WIDTH and FONT_HEIGHT values constant at their current values (8x16) and handle the Digic6 scaling within the gui_draw.c code and platform settings. This way the rest of the code continues to work with the same CHDK 'virtual' co-ordinate system.


I'm doing this for the G5X which has yet another drawing system (32bpp bitmap, with X2 scaling in both directions).

Edit: May be an issue for the G5X which currently uses the old FONT_WIDTH & FONT_HEIGHT values. Need to think about this some more.

Phil.
« Last Edit: 05 / November / 2017, 17:22:10 by philmoz »
CHDK ports:
  sx30is (1.00c, 1.00h, 1.00l, 1.00n & 1.00p)
  g12 (1.00c, 1.00e, 1.00f & 1.00g)
  sx130is (1.01d & 1.01f)
  ixus310hs (1.00a & 1.01a)
  sx40hs (1.00d, 1.00g & 1.00i)
  g1x (1.00e, 1.00f & 1.00g)

 

Related Topics