I'm no expert, but I'd like to take a stab at this one.
If I understand your problem correctly, you want to take a mass produced product, compile all the chips with identical code, then go back and alter individual UUIDs, handles, etc. but not necessarily change large aspects of the GATT db.
Given the information found in How to change the GATT database after init (bleapp_set_cfg) ? you have code to switch between two GATT db's. Speaking abstractly, we could potentially use the second GATT db as a buffer for when you wish to alter the main GATT.
You could compile the original default GATT. Then, access the boards EEPROM by the i2c line, writing to it from some other MCU at a designated address. Next, we would trigger an interrupt GPIO that then tells the BRCM chip to read the EEPROM at the appropriate memory address, load that read data into the buffer GATT, and finally switch to the buffer GATT as the primary GATT.
This is all under the assumption that the code to switch between GATT db's is functional. Also, I opted for use of i2c only because my knowledge of UART is minimal. I'm sure two masters on an i2c bus is against protocol, but I don't see any reason for it to cause problems in the span of a short write process.
I have not tried it, but I guess it should be doable. At startup you can initialize DB with some minimum configuration. You probably do not need to initialize DB, but I do not think anybody tried that. Do not start scan advertisements or scan at that time. After that MCU can tell you the size of the DB, you can allocate a memory chunk and download the DB you need into this memory (see for example uart_firmware_upgrade how to use UART). When download is complete you can swap the DB as you found in one of the discussion threads. After that your code can go through the DB and figure out the handles that it uses (see for example automation_io_db_init in the automation_io_server).
I guess the challenging part is to construct the memory array so that 20737 can use it, but you can reuse the same macros on the MCU side as it is done in the SDK.
Having said I am not sure if this is what you want to do. When you mentioned that you want to use 20737 as LE modem, do you want to process GATT read/writes... in the 20737 or on the MCU side. You can definitely keep DB on the MCU and pass all the L2CAP packets up to the MCU. There will be very small chunk of code on 20737 that you need to do.
Thanks for the ideas. The goal is to come up with a generic 20737 firmware image that we can use in multiple projects, configuring the GATT database via serial commands. That way we don't need to create a different 20737 firmware build for each project.
I'd rather not have to use I2C to reprogram the EEPROM of the '20737; it would be much preferable to just do it all via serial commands. Having dual masters on I2C is doable, but usually we hold one of them in reset so that it doesn't interfere with the other master.
We didn't want to pass up all the L2CAP packets to the MCU; we wanted the 20737 to process them, and just notify the MCU when an attribute was written to over BLE. And then the MCU could send a command to the 20737 to update a value in the GATT database too.
It sounds like doing this on the BCM20737 will be more difficult than I thought.