[U-Boot] [Question] Driver-Model UART on NOR-boot ? Work?

Hi Simon,
I am looking at the driver-model serial code.
I notice driver-model serial code uses ".data" section for storing the current device even before relocation.
This code in drivers/serial/serial-uclass.c:
/* The currently-selected console serial device */ struct udevice *cur_dev __attribute__ ((section(".data")));
In my understanding, we should not write any data to .data section before relocation.
Let's say we are booting U-Boot from NOR flash.
Before relocation, everything (including .data section) is placed on NOR flash which is read-only. (Please point out if I am wrong.)
We are only allowed to write data to the stack, gd_t, bd_t and malloc area (if CONFIG_SYS_MALLOC_F_LEN is defined) before relocation, I think.
I think that is why pre-driver-model serial uses a hard-coded default serial port before relocation.
This code in driver/serial/serial.c:
if (!(gd->flags & GD_FLG_RELOC)) dev = default_serial_console(); else if (!serial_current) dev = default_serial_console(); else dev = serial_current;
My question is, does printf() work with driver-model UART and XIP device such NOR flash?
Best Regards Masahiro Yamada

Hi Masahiro,
On 1 October 2014 05:23, Masahiro Yamada yamada.m@jp.panasonic.com wrote:
Hi Simon,
I am looking at the driver-model serial code.
I notice driver-model serial code uses ".data" section for storing the current device even before relocation.
This code in drivers/serial/serial-uclass.c:
/* The currently-selected console serial device */ struct udevice *cur_dev __attribute__ ((section(".data")));
In my understanding, we should not write any data to .data section before relocation.
Let's say we are booting U-Boot from NOR flash.
Before relocation, everything (including .data section) is placed on NOR flash which is read-only. (Please point out if I am wrong.)
We are only allowed to write data to the stack, gd_t, bd_t and malloc area (if CONFIG_SYS_MALLOC_F_LEN is defined) before relocation, I think.
I think that is why pre-driver-model serial uses a hard-coded default serial port before relocation.
This code in driver/serial/serial.c:
if (!(gd->flags & GD_FLG_RELOC)) dev = default_serial_console(); else if (!serial_current) dev = default_serial_console(); else dev = serial_current;
My question is, does printf() work with driver-model UART and XIP device such NOR flash?
The global_data structure needs to go somewhere, even before relocation. On ARM this is general SRAM I suppose. In your case I think you have some cache RAM to use. Do you use SPL?
The pre-reloc malloc() area goes below global_data so uses the same mechanism.
Yes it is true that strictly speaking we should not use data before relocation. I suppose we could move cur_dev to global_data instead for this particular case. It doesn't really scale to other drivers, but then I expect that only serial needs to keep a 'current' pointer before relocation, and even that will eventually go away once the serial stuff is cleaned up.
So let me know if that solution works.
Regards, Simon

Hi Simon,
2014-10-02 0:31 GMT+09:00 Simon Glass sjg@chromium.org:
Hi Masahiro,
On 1 October 2014 05:23, Masahiro Yamada yamada.m@jp.panasonic.com wrote:
Hi Simon,
I am looking at the driver-model serial code.
I notice driver-model serial code uses ".data" section for storing the current device even before relocation.
This code in drivers/serial/serial-uclass.c:
/* The currently-selected console serial device */ struct udevice *cur_dev __attribute__ ((section(".data")));
In my understanding, we should not write any data to .data section before relocation.
Let's say we are booting U-Boot from NOR flash.
Before relocation, everything (including .data section) is placed on NOR flash which is read-only. (Please point out if I am wrong.)
We are only allowed to write data to the stack, gd_t, bd_t and malloc area (if CONFIG_SYS_MALLOC_F_LEN is defined) before relocation, I think.
I think that is why pre-driver-model serial uses a hard-coded default serial port before relocation.
This code in driver/serial/serial.c:
if (!(gd->flags & GD_FLG_RELOC)) dev = default_serial_console(); else if (!serial_current) dev = default_serial_console(); else dev = serial_current;
My question is, does printf() work with driver-model UART and XIP device such NOR flash?
The global_data structure needs to go somewhere, even before relocation. On ARM this is general SRAM I suppose. In your case I think you have some cache RAM to use. Do you use SPL?
UniPhier SoCs support various boot-modes.
I use SPL for NAND and MMC card boot, but I don't for NOR boot.
For NAND boot or MMC card boot, yes, .data section is on some cache RAM, i.e. it is writable.
For NOR boot, the program is running eXecutable-In-Place; therefore before relocation, .data section is remaining on NOR flash and it is read-only.
The pre-reloc malloc() area goes below global_data so uses the same mechanism.
Yes it is true that strictly speaking we should not use data before relocation. I suppose we could move cur_dev to global_data instead for this particular case. It doesn't really scale to other drivers, but then I expect that only serial needs to keep a 'current' pointer before relocation, and even that will eventually go away once the serial stuff is cleaned up.
So let me know if that solution works.
I think it will work.
Moving cur_dev to struct global_data is easy. My concern is only that struct global_data is already too cluttered.
Some other options I have come up with are:
[1] Before relocation, cur_dev is set to a fixed-device by a board file. This is the same solution as pre-driver-model UART does.
This would be unfortunate. We are using Device-Tree more and more these days. Run-time choosing would be more flexible.
[2] Make .data section writable even before relocation.
The boot sequence would be:
1. Copy .data to the temporary SRAM and clear .bss section 2. board_init_f() 3. Relocate all sections to SDRAM 4. board_init_r()

Hi Masahiro,
On 1 October 2014 10:27, Masahiro YAMADA yamada.m@jp.panasonic.com wrote:
Hi Simon,
2014-10-02 0:31 GMT+09:00 Simon Glass sjg@chromium.org:
Hi Masahiro,
On 1 October 2014 05:23, Masahiro Yamada yamada.m@jp.panasonic.com wrote:
Hi Simon,
I am looking at the driver-model serial code.
I notice driver-model serial code uses ".data" section for storing the current device even before relocation.
This code in drivers/serial/serial-uclass.c:
/* The currently-selected console serial device */ struct udevice *cur_dev __attribute__ ((section(".data")));
In my understanding, we should not write any data to .data section before relocation.
Let's say we are booting U-Boot from NOR flash.
Before relocation, everything (including .data section) is placed on NOR flash which is read-only. (Please point out if I am wrong.)
We are only allowed to write data to the stack, gd_t, bd_t and malloc area (if CONFIG_SYS_MALLOC_F_LEN is defined) before relocation, I think.
I think that is why pre-driver-model serial uses a hard-coded default serial port before relocation.
This code in driver/serial/serial.c:
if (!(gd->flags & GD_FLG_RELOC)) dev = default_serial_console(); else if (!serial_current) dev = default_serial_console(); else dev = serial_current;
My question is, does printf() work with driver-model UART and XIP device such NOR flash?
The global_data structure needs to go somewhere, even before relocation. On ARM this is general SRAM I suppose. In your case I think you have some cache RAM to use. Do you use SPL?
UniPhier SoCs support various boot-modes.
I use SPL for NAND and MMC card boot, but I don't for NOR boot.
For NAND boot or MMC card boot, yes, .data section is on some cache RAM, i.e. it is writable.
For NOR boot, the program is running eXecutable-In-Place; therefore before relocation, .data section is remaining on NOR flash and it is read-only.
OK I see.
The pre-reloc malloc() area goes below global_data so uses the same mechanism.
Yes it is true that strictly speaking we should not use data before relocation. I suppose we could move cur_dev to global_data instead for this particular case. It doesn't really scale to other drivers, but then I expect that only serial needs to keep a 'current' pointer before relocation, and even that will eventually go away once the serial stuff is cleaned up.
So let me know if that solution works.
I think it will work.
Moving cur_dev to struct global_data is easy. My concern is only that struct global_data is already too cluttered.
Oh well, at least there is only one now.
Some other options I have come up with are:
[1] Before relocation, cur_dev is set to a fixed-device by a board file. This is the same solution as pre-driver-model UART does.
This would be unfortunate. We are using Device-Tree more and more these days. Run-time choosing would be more flexible.
Agreed.
[2] Make .data section writable even before relocation.
The boot sequence would be:
- Copy .data to the temporary SRAM and clear .bss section
- board_init_f()
- Relocate all sections to SDRAM
- board_init_r()
There might be a lot of .data, and this feels like a double-relocation. When moving .data we would need to fix up all the relocations that refer to it, then fix the rest after the 'real' relocation.
I prefer option [0] :-)
Regards, Simon

Hi Simon,
On Wed, 1 Oct 2014 17:43:19 -0600 Simon Glass sjg@chromium.org wrote:
The pre-reloc malloc() area goes below global_data so uses the same mechanism.
Yes it is true that strictly speaking we should not use data before relocation. I suppose we could move cur_dev to global_data instead for this particular case. It doesn't really scale to other drivers, but then I expect that only serial needs to keep a 'current' pointer before relocation, and even that will eventually go away once the serial stuff is cleaned up.
Do you expect any other drivers that must be bound before relocation? (except DEMO driver of sandbox)
Only UART?
Best Regards Masahiro Yamada

Hi Masahiro,
On 1 October 2014 23:18, Masahiro Yamada yamada.m@jp.panasonic.com wrote:
Hi Simon,
On Wed, 1 Oct 2014 17:43:19 -0600 Simon Glass sjg@chromium.org wrote:
The pre-reloc malloc() area goes below global_data so uses the same mechanism.
Yes it is true that strictly speaking we should not use data before relocation. I suppose we could move cur_dev to global_data instead for this particular case. It doesn't really scale to other drivers, but then I expect that only serial needs to keep a 'current' pointer before relocation, and even that will eventually go away once the serial stuff is cleaned up.
Do you expect any other drivers that must be bound before relocation? (except DEMO driver of sandbox)
Only UART?
Mostly UART, but as more boards are added there may be others. For example, SPI and I2C, But none will need the 'current device' concept I think. And remember that serial likely only needs it for legacy reasons.
Regards, Simon
participants (3)
-
Masahiro YAMADA
-
Masahiro Yamada
-
Simon Glass