Rockbox Development > Starting Development and Compiling

Beginning steps in kernel disassembly and analysis

<< < (2/9) > >>

you're on the right track. Another tip, I think I might've have discovered platform_device_add using this string: "". It's the only user of that string. platform_device_register is a small wrapper which calls platform_device_add, but it is hard to identify on its own. The latter function doesn't have many other callers though.

The chain of references should look something like this--

--- Code: ---[initcall array] -> board_base_init() -> platform_device_register() -> platform_device_add()

--- End code ---
knowing the two "ends" you just need to chase down the references and find board_base_init in the middle. BTW, the platform device array is an array of structs like struct { void* pdevice; void* pdata; int size; }. pdevice is a struct whose first member points to a name string so you can see what device you are dealing with, and pdata is a blob containing the useful info. And convieniently, size tells you how big the pdata struct is.

Well, I'm not sure if I'm barking up the wrong tree or what. I thought I had located board_base_init(), but none of the data it links to seem to quite be right. A bunch of pointers to strings are there, but between them are all zeroes (see screenshots).

I may need to backtrack and try to find something else, but I've done a lot of aimless scrolling in the hopes I would stumble across something, but that's probably futile.

One other thing I found that looks halfway interesting (see screenshot)

That's definitely the platform_devices_array at 80572854. Those extra references near the beginning that Ghidra adds are noise -- direct references that happen to occur from the loop. I guess its analysis is not very deep and it has a hard time understanding the difference between things added by the compiler to implement the loop guard condition vs. "genuine" data accesses... but whatever.

The pointers like PTR_s_gpio-keys_XXXX are pointing to struct platform_device instances, I think. That's a huge struct I believe, mainly members used at runtime, that's why there are so many zeros. But you should see the grey text like = 804b8c6c off to the side if there is any nonzero data inside which looks like an address, those addresses are clickable and you can follow the links in case they point to useful data or functions... I think there are tables of function pointers for driver ops. Maybe other things, I'm not sure.

DAT_80511180 for example should be one of the platform data blobs, in the case of jzmmc_v1.2 it will be struct jzmmc_platform_data. Cf. arch/mips/xburst/soc-x1000/chip-x1000/halley2/common/mmc.c. You should have another driver named something like jz-fb, and its platform data blob should define details of your LCD's interface. See struct jzfb_platform_data.

Go look at one of the other LCD drivers to get an idea of what you're looking for, mainly you want to figure out bpp, smart_config.bus_width, smart_config.write_gram_command, and smart_config.data_table. There are also the LCD ops for powering on the panel (GPIOs, levels, timings, etc. needed to power it up.)

FUN_805614c0 is most likely i2c_register_board_info. 1st argument is the bus number -- 0,1, or 2 corresponding to the same number bus on the X1000 -- and type of the 2nd argument is an array of struct i2c_board_info. That will contain at least your I2C device addresses, and possibly platform data blobs.

Another thing you can try is identifying gpiolib functions (drivers/gpio/gpiolib.c). Each function tends to have a WARN_ON statement or some other debug message which causes the functions to reference their own name. Most useful: gpiod_request and from there it is not hard to find the public API gpio_request. Often that is called with hardcoded GPIO numbers. And you can find the probe() functions of any drivers using a GPIO, since they all must call gpio_request before doing anything with the GPIO. gpio_direction_output/input are useful to find other driver functions. The GPIO numbering scheme is port*32 + pin. Ports are A = 0, B = 1, etc.

Those strings ldo0, ldo1, vdd_cpu... probably part of AXP192's axp_mfd driver. There's a copy of that driver in the M0 kernel sources (download links are on the Shanling Q1 wiki page). I did diassemble that driver quite a bit for the Q1, but I don't remember if I ever found the one voltage setting I needed to change in there, or if I just grabbed it from the running OF's sysfs. I think all I may have concluded from the diassembly was that the Q1 almost certainly had an AXP192, based on which #ifdef'd code appeared to be in the binary. There's a lot of data tables and boilerplate code, fairly straightforward but tedious to handle. Probably the interrupt line GPIO is the only easy-to-find thing.

Oh, excellent! I was thinking it wasn't it due to how it didn't seem to rigorously follow the struct pattern of pointer to string, pointer to data, size, but I guess I just didn't quite understand what I was looking for (data sure looks different when you're looking directly at bits and bytes, I guess)

Thanks for the explanations, I'll start digging and see what details I can find!


[0] Message Index

[#] Next page

[*] Previous page

Go to full version