Skip to contentSkip to conversation

Driver-Model UART on NOR-boot ? Work?

U-Boot Masahiro Yamada 2 participants 6 messages Oct 1, 2014 – Oct 4, 2014

lore
Share & tools
lore
#0 lore raw

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

#1 lore raw

Hi Masahiro,

Quoted 50 lines · Masahiro Yamada

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;
Quoted 2 lines

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

#2 lore raw

Hi Simon,

2014-10-02 0:31 GMT+09:00 Simon Glass <[email protected]>:

Quoted 53 lines

Hi Masahiro,

Quoted 50 lines · Masahiro Yamada

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;
Quoted 6 lines
Quoted 2 lines

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.

Quoted 10 lines

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()
Signature · 2 lines
Best Regards
Masahiro Yamada
#3 lore raw

Hi Masahiro,

Quoted 66 lines · Masahiro YAMADA

Hi Simon,

2014-10-02 0:31 GMT+09:00 Simon Glass <[email protected]>:

Quoted 53 lines

Hi Masahiro,

Quoted 50 lines · Masahiro Yamada

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;
Quoted 6 lines
Quoted 2 lines

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.

Quoted 9 lines

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.

Quoted 10 lines
Quoted 10 lines

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.

Quoted 7 lines
Quoted 1 line

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.

Quoted 9 lines

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.

Quoted 5 lines

[2]
Make .data section writable even before relocation.

Quoted 7 lines

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()

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

#4 lore raw

Hi Simon,

Quoted 10 lines · On Wed, 1 Oct 2014 17:43:19 -0600 Simon Glass <[email protected]> wrote:
Quoted 10 lines
Quoted 10 lines

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

#5 lore raw

Hi Masahiro,

Quoted 20 lines · Masahiro Yamada

Hi Simon,

Quoted 10 lines · On Wed, 1 Oct 2014 17:43:19 -0600 Simon Glass <[email protected]> wrote:
Quoted 10 lines
Quoted 10 lines

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.

Quoted 4 lines

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