Hi Star,

On 08/04/17 10:29, Star Zeng wrote:
> https://lists.01.org/pipermail/edk2-devel/2017-July/012385.html
> reported the timeout processing in SerialRead is not consistent.
>
> Since SerialPortPoll only checks the status of serial port and
> returns immediately, and SerialPortRead does not really implement
> a time out mechanism and will always wait for enough input,
> it will cause below results:
> 1. If there is no serial input at all, this interface will return
> timeout immediately without any waiting;
> 2. If there is A characters in serial port FIFO, and caller requires
> A+1 characters, it will wait until a new input is coming and timeout
> will not really occur.
>
> This patch is to update SerialRead() to check SerialPortPoll() and
> read data through SerialPortRead() one byte by one byte, and check
> timeout against mSerialIoMode.Timeout if no input.
>
> Cc: Heyi Guo <heyi....@linaro.org>
> Cc: Ruiyu Ni <ruiyu...@intel.com>
> Cc: Laszlo Ersek <ler...@redhat.com>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Star Zeng <star.z...@intel.com>
> ---
>  MdeModulePkg/Universal/SerialDxe/SerialIo.c | 18 ++++++++++++++++--
>  1 file changed, 16 insertions(+), 2 deletions(-)
>
> diff --git a/MdeModulePkg/Universal/SerialDxe/SerialIo.c 
> b/MdeModulePkg/Universal/SerialDxe/SerialIo.c
> index d2383e56dd8f..43d33dba0c2a 100644
> --- a/MdeModulePkg/Universal/SerialDxe/SerialIo.c
> +++ b/MdeModulePkg/Universal/SerialDxe/SerialIo.c
> @@ -465,11 +465,25 @@ SerialRead (
>    )
>  {
>    UINTN Count;
> +  UINTN TimeOut;
>
>    Count = 0;
>
> -  if (SerialPortPoll ()) {
> -    Count = SerialPortRead (Buffer, *BufferSize);
> +  while (Count < *BufferSize) {
> +    TimeOut = 0;
> +    while (TimeOut < mSerialIoMode.Timeout) {
> +      if (SerialPortPoll ()) {
> +        break;
> +      }
> +      gBS->Stall (10);
> +      TimeOut += 10;
> +    }
> +    if (TimeOut >= mSerialIoMode.Timeout) {
> +      break;
> +    }
> +    SerialPortRead (Buffer, 1);
> +    Count++;
> +    Buffer = (VOID *) ((UINT8 *) Buffer + 1);
>    }
>
>    if (Count != *BufferSize) {
>

This patch breaks the ArmVirtQemu platform's boot process -- it seems to
fall into an infinite loop. I guess the above loop(s) never complete?

If I revert this patch on top of current master (af0364f01e8c,
"Nt32/PlatformBootManagerLib: Enable STD_ERROR on all consoles",
2017-08-14), then ArmVirtQemu boots fine.

I found this commit with bisection:

> 4cf3f37c87ba1f9d58072444bd735e40e4779e70 is the first bad commit
> commit 4cf3f37c87ba1f9d58072444bd735e40e4779e70
> Author: Star Zeng <star.z...@intel.com>
> Date:   Tue Jul 18 16:32:16 2017 +0800
>
>     MdeModulePkg SerialDxe: Process timeout consistently in SerialRead
>
>     https://lists.01.org/pipermail/edk2-devel/2017-July/012385.html
>     reported the timeout processing in SerialRead is not consistent.
>
>     Since SerialPortPoll only checks the status of serial port and
>     returns immediately, and SerialPortRead does not really implement
>     a time out mechanism and will always wait for enough input,
>     it will cause below results:
>     1. If there is no serial input at all, this interface will return
>     timeout immediately without any waiting;
>     2. If there is A characters in serial port FIFO, and caller requires
>     A+1 characters, it will wait until a new input is coming and timeout
>     will not really occur.
>
>     This patch is to update SerialRead() to check SerialPortPoll() and
>     read data through SerialPortRead() one byte by one byte, and check
>     timeout against mSerialIoMode.Timeout if no input.
>
>     Cc: Heyi Guo <heyi....@linaro.org>
>     Cc: Ruiyu Ni <ruiyu...@intel.com>
>     Cc: Laszlo Ersek <ler...@redhat.com>
>     Contributed-under: TianoCore Contribution Agreement 1.0
>     Signed-off-by: Star Zeng <star.z...@intel.com>
>     Reviewed-by: Ruiyu Ni <ruiyu...@intel.com>
>
> :040000 040000 aaa8b75d378ec613b828db938c36a16723583906 
> d034044918d7f5b8d30783e0a9eccdf3cf21e5c5 M      MdeModulePkg

Bisection log:

> git bisect start
> # bad: [af0364f01e8cac95afad01437f13beef90f6640b] 
> Nt32/PlatformBootManagerLib: Enable STD_ERROR on all consoles
> git bisect bad af0364f01e8cac95afad01437f13beef90f6640b
> # good: [c325e41585e374d40fb36b434e61a1ab0fca5b1c] MdeModulePkg: Fix coding 
> style issues
> git bisect good c325e41585e374d40fb36b434e61a1ab0fca5b1c
> # good: [636cda51903b4b28e1c9b099c4f22a84e61b09da] OvmfPkg/OvmfPkg.fdf.inc: 
> extract VARS_LIVE_SIZE and VARS_SPARE_SIZE macros
> git bisect good 636cda51903b4b28e1c9b099c4f22a84e61b09da
> # good: [997b2c543751cb4a3473270c1a7016ade311f01b] BaseTools/GenCrc32: Fix a 
> bug to hand empty file for decode
> git bisect good 997b2c543751cb4a3473270c1a7016ade311f01b
> # good: [f1658838c267723139711c0b15d98a74980ae4c5] OvmfPkg/IoMmuDxe: abort 
> harder on memory encryption mask failures
> git bisect good f1658838c267723139711c0b15d98a74980ae4c5
> # bad: [9458afa33728e64049d465f052b2c5c3ca3e881c] IntelFrameworkModulePkg: 
> Fix Xcode 9 Beta treating 32-bit left shift as undefined
> git bisect bad 9458afa33728e64049d465f052b2c5c3ca3e881c
> # good: [6e414300b5f19d3045a0d21ad90ac2fe965478a5] 
> EmbeddedPkg/AndroidFastboot: split android boot header
> git bisect good 6e414300b5f19d3045a0d21ad90ac2fe965478a5
> # bad: [416d48f755518fd1d202b97be2e9944df6e8f0d4] ShellPkg/drivers: Show 
> Image Name in non-SFO mode
> git bisect bad 416d48f755518fd1d202b97be2e9944df6e8f0d4
> # bad: [2913ebb2b550f50a14f105e26995dd095e627ba4] NetworkPkg/HttpBootDxe: 
> Refine the coding style.
> git bisect bad 2913ebb2b550f50a14f105e26995dd095e627ba4
> # bad: [9e2a8e928995c3b1bb664b73fd59785055c6b5f6] OvmfPkg/AcpiPlatformDxe: 
> short-circuit the transfer of an empty S3_CONTEXT
> git bisect bad 9e2a8e928995c3b1bb664b73fd59785055c6b5f6
> # bad: [4cf3f37c87ba1f9d58072444bd735e40e4779e70] MdeModulePkg SerialDxe: 
> Process timeout consistently in SerialRead
> git bisect bad 4cf3f37c87ba1f9d58072444bd735e40e4779e70
> # first bad commit: [4cf3f37c87ba1f9d58072444bd735e40e4779e70] MdeModulePkg 
> SerialDxe: Process timeout consistently in SerialRead

In retrospect, I see that you asked me for feedback in the original
discussion, at the following URL:

  https://lists.01.org/pipermail/edk2-devel/2017-July/012406.html

Unfortunately, this was on July 18th, and I was on vacation then. (I
think I configured my email account to send an automated out-of-office
reply.)

Looking at the patch now, one idea I have is to keep the time running
across all bytes read; that is, use mSerialIoMode.Timeout as a global
timeout for the entire SerialRead() call.

Unfortunately, the UEFI-2.7 spec defines the "SERIAL_IO_MODE.Timeout"
field, and the Timeout parameter of
EFI_SERIAL_IO_PROTOCOL.SetAttributes(), inconsistently with each other.
First it says (about the field):

  Timeout  If applicable, the number of microseconds to wait before
           timing out a Read or Write operation.

(This is compatible with my idea.)

But then it says (in the general description, and about the
SetAttributes() parameter):

  The default attributes for all UART-style serial device interfaces
  are: [...] a 1,000,000 microsecond timeout *per character* [...]

  Timeout  The requested time out *for a single character* in
           microseconds. This timeout applies to both the transmit and
           receive side of the interface. A Timeout value of 0 will use
           the device's default time out value.

(Emphases mine.)

... I added some debug messages to the loops, and the first invocation
of the function seems to hang with the following parameters:

> SerialRead: BufferSize=1 mSerialIoMode.Timeout=1000000

That is, the caller wants to read a single character (which is not
arriving). The timeout is the default 1 second. However, the wait takes
much-much longer than 1 second (it appears to be infinite). It seems
that gBS->Stall(10) takes much longer than 10 microseconds. According to
the UEFI spec,

  The Stall() function stalls execution on the processor for at least
  the requested number of microseconds. [...]

So Stall() is allowed to wait longer (possibly a lot longer) -- I guess
it depends on some timer's resolution.

I have another idea related to this -- let me research it a bit later. I
might post some patches.

Thanks
Laszlo
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to