I recently figured out the cause of a nasty bug I've been working on with an Atmel AT91SAM9G20 SBC running U-boot, an open source bootloader. The core of the problem was that U-boot expected the hardware to be configured differently than I had built it, so some of the device registers were misconfigured.
Now that I've figured out the problem, I need to tweak U-boot to configure the registers correctly. I can do this blindly by adding a few lines of code at the end of the program, but that's messy.
This brings me to my question: how can I figure out how U-boot works more efficiently than starting at main() and reading all possible code paths across all files? I've tried grepping around in the files and looking at the code near relevant identifiers. This has proved ineffective; it seems that most of the code is drivers for subsystems I don't care about. I actually understand how the bootloader works pretty well by now, but I'm hoping there exists a better method than my naive approach.