diff mbox

[v2] s390-ccw: print carriage return with new lines

Message ID 1509043965-5852-1-git-send-email-walling@linux.vnet.ibm.com (mailing list archive)
State New, archived
Headers show

Commit Message

Collin L. Walling Oct. 26, 2017, 6:52 p.m. UTC
The sclp console in the s390 bios writes raw data,
leading console emulators (such as virsh console) to
treat a new line ('\n') as just a new line instead
of as a Unix line feed. Because of this, output
appears in a "stair case" pattern.

Let's print \r\n on every occurrence of a new line
in the string passed to write to amend this issue.

This is in sync with the guest Linux code in
drivers/s390/char/sclp_vt220.c which also does a line feed
conversion  in the console part of the driver. 

This fixes the s390-ccw and s390-netboot output like
$ virsh start test --console
Domain test started
Connected to domain test
Escape character is ^]
Network boot starting...
                          Using MAC address: 02:01:02:03:04:05
                                                                Requesting information via DHCP:  010

Signed-off-by: Collin L. Walling <walling@linux.vnet.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
---
 pc-bios/s390-ccw/sclp.c | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

Comments

Alexander Graf Oct. 26, 2017, 8:25 p.m. UTC | #1
On 26.10.17 20:52, Collin L. Walling wrote:
> The sclp console in the s390 bios writes raw data,
> leading console emulators (such as virsh console) to
> treat a new line ('\n') as just a new line instead
> of as a Unix line feed. Because of this, output
> appears in a "stair case" pattern.
> 
> Let's print \r\n on every occurrence of a new line
> in the string passed to write to amend this issue.
> 
> This is in sync with the guest Linux code in
> drivers/s390/char/sclp_vt220.c which also does a line feed
> conversion  in the console part of the driver. 
> 
> This fixes the s390-ccw and s390-netboot output like
> $ virsh start test --console
> Domain test started
> Connected to domain test
> Escape character is ^]
> Network boot starting...
>                           Using MAC address: 02:01:02:03:04:05
>                                                                 Requesting information via DHCP:  010
> 
> Signed-off-by: Collin L. Walling <walling@linux.vnet.ibm.com>
> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
> ---
>  pc-bios/s390-ccw/sclp.c | 16 +++++++++++++---
>  1 file changed, 13 insertions(+), 3 deletions(-)
> 
> diff --git a/pc-bios/s390-ccw/sclp.c b/pc-bios/s390-ccw/sclp.c
> index 486fce1..f8ad5ae 100644
> --- a/pc-bios/s390-ccw/sclp.c
> +++ b/pc-bios/s390-ccw/sclp.c
> @@ -68,17 +68,27 @@ void sclp_setup(void)
>  long write(int fd, const void *str, size_t len)
>  {
>      WriteEventData *sccb = (void *)_sccb;
> +    const char *p = str;
> +    size_t data_len = 0;
> +    size_t i;
>  
>      if (fd != 1 && fd != 2) {
>          return -EIO;
>      }
>  
> -    sccb->h.length = sizeof(WriteEventData) + len;
> +    for (i = len; i > 0; i--) {

Where did the bounds check go? If you write(max) before, you were
writing max bytes. If you do it now, you end up writing max + n bytes
and potentially overflow the array, no?


Alex

> +        if (*p == '\n') {
> +            sccb->data[data_len++] = '\r';
> +        }
> +        sccb->data[data_len++] = *p;
> +        p++;
> +    }
> +
> +    sccb->h.length = sizeof(WriteEventData) + data_len;
>      sccb->h.function_code = SCLP_FC_NORMAL_WRITE;
> -    sccb->ebh.length = sizeof(EventBufferHeader) + len;
> +    sccb->ebh.length = sizeof(EventBufferHeader) + data_len;
>      sccb->ebh.type = SCLP_EVENT_ASCII_CONSOLE_DATA;
>      sccb->ebh.flags = 0;
> -    memcpy(sccb->data, str, len);
>  
>      sclp_service_call(SCLP_CMD_WRITE_EVENT_DATA, sccb);
>  
>
Collin L. Walling Oct. 26, 2017, 8:37 p.m. UTC | #2
On 10/26/2017 04:25 PM, Alexander Graf wrote:
>
> On 26.10.17 20:52, Collin L. Walling wrote:
>> The sclp console in the s390 bios writes raw data,
>> leading console emulators (such as virsh console) to
>> treat a new line ('\n') as just a new line instead
>> of as a Unix line feed. Because of this, output
>> appears in a "stair case" pattern.
>>
>> Let's print \r\n on every occurrence of a new line
>> in the string passed to write to amend this issue.
>>
>> This is in sync with the guest Linux code in
>> drivers/s390/char/sclp_vt220.c which also does a line feed
>> conversion  in the console part of the driver.
>>
>> This fixes the s390-ccw and s390-netboot output like
>> $ virsh start test --console
>> Domain test started
>> Connected to domain test
>> Escape character is ^]
>> Network boot starting...
>>                            Using MAC address: 02:01:02:03:04:05
>>                                                                  Requesting information via DHCP:  010
>>
>> Signed-off-by: Collin L. Walling <walling@linux.vnet.ibm.com>
>> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
>> ---
>>   pc-bios/s390-ccw/sclp.c | 16 +++++++++++++---
>>   1 file changed, 13 insertions(+), 3 deletions(-)
>>
>> diff --git a/pc-bios/s390-ccw/sclp.c b/pc-bios/s390-ccw/sclp.c
>> index 486fce1..f8ad5ae 100644
>> --- a/pc-bios/s390-ccw/sclp.c
>> +++ b/pc-bios/s390-ccw/sclp.c
>> @@ -68,17 +68,27 @@ void sclp_setup(void)
>>   long write(int fd, const void *str, size_t len)
>>   {
>>       WriteEventData *sccb = (void *)_sccb;
>> +    const char *p = str;
>> +    size_t data_len = 0;
>> +    size_t i;
>>   
>>       if (fd != 1 && fd != 2) {
>>           return -EIO;
>>       }
>>   
>> -    sccb->h.length = sizeof(WriteEventData) + len;
>> +    for (i = len; i > 0; i--) {
> Where did the bounds check go? If you write(max) before, you were
> writing max bytes. If you do it now, you end up writing max + n bytes
> and potentially overflow the array, no?
>
>
> Alex

I wasn't a fan of the code aesthetics and being that the SCCB write buffer
allows about 4k bytes of data to be written to it, I felt it was safe to
remove it.  It's unlikely we'd be writing that much data in the bios, plus
that check did not exist prior to this fixup.

Though, reading that out loud, it probably isn't the best idea to sacrifice
code robustness for code aesthetics.

for (i = len; i > 0; i--) {
     if (data_len > SCCB_DATA_LEN - 1) {
         return -SOME_ERROR
     }
     if (*p == '\n') {
         sccb->data[data_len++] = '\r';
     }
     sccb->data[data_len++] = *p;
     p++;
}

What do you think?

- Collin

>
>> +        if (*p == '\n') {
>> +            sccb->data[data_len++] = '\r';
>> +        }
>> +        sccb->data[data_len++] = *p;
>> +        p++;
>> +    }
>> +
>> +    sccb->h.length = sizeof(WriteEventData) + data_len;
>>       sccb->h.function_code = SCLP_FC_NORMAL_WRITE;
>> -    sccb->ebh.length = sizeof(EventBufferHeader) + len;
>> +    sccb->ebh.length = sizeof(EventBufferHeader) + data_len;
>>       sccb->ebh.type = SCLP_EVENT_ASCII_CONSOLE_DATA;
>>       sccb->ebh.flags = 0;
>> -    memcpy(sccb->data, str, len);
>>   
>>       sclp_service_call(SCLP_CMD_WRITE_EVENT_DATA, sccb);
>>   
>>
Alexander Graf Oct. 26, 2017, 8:48 p.m. UTC | #3
On 26.10.17 22:37, Collin L. Walling wrote:
> On 10/26/2017 04:25 PM, Alexander Graf wrote:
>>
>> On 26.10.17 20:52, Collin L. Walling wrote:
>>> The sclp console in the s390 bios writes raw data,
>>> leading console emulators (such as virsh console) to
>>> treat a new line ('\n') as just a new line instead
>>> of as a Unix line feed. Because of this, output
>>> appears in a "stair case" pattern.
>>>
>>> Let's print \r\n on every occurrence of a new line
>>> in the string passed to write to amend this issue.
>>>
>>> This is in sync with the guest Linux code in
>>> drivers/s390/char/sclp_vt220.c which also does a line feed
>>> conversion  in the console part of the driver.
>>>
>>> This fixes the s390-ccw and s390-netboot output like
>>> $ virsh start test --console
>>> Domain test started
>>> Connected to domain test
>>> Escape character is ^]
>>> Network boot starting...
>>>                            Using MAC address: 02:01:02:03:04:05
>>>                                                                 
>>> Requesting information via DHCP:  010
>>>
>>> Signed-off-by: Collin L. Walling <walling@linux.vnet.ibm.com>
>>> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
>>> ---
>>>   pc-bios/s390-ccw/sclp.c | 16 +++++++++++++---
>>>   1 file changed, 13 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/pc-bios/s390-ccw/sclp.c b/pc-bios/s390-ccw/sclp.c
>>> index 486fce1..f8ad5ae 100644
>>> --- a/pc-bios/s390-ccw/sclp.c
>>> +++ b/pc-bios/s390-ccw/sclp.c
>>> @@ -68,17 +68,27 @@ void sclp_setup(void)
>>>   long write(int fd, const void *str, size_t len)
>>>   {
>>>       WriteEventData *sccb = (void *)_sccb;
>>> +    const char *p = str;
>>> +    size_t data_len = 0;
>>> +    size_t i;
>>>         if (fd != 1 && fd != 2) {
>>>           return -EIO;
>>>       }
>>>   -    sccb->h.length = sizeof(WriteEventData) + len;
>>> +    for (i = len; i > 0; i--) {
>> Where did the bounds check go? If you write(max) before, you were
>> writing max bytes. If you do it now, you end up writing max + n bytes
>> and potentially overflow the array, no?
>>
>>
>> Alex
> 
> I wasn't a fan of the code aesthetics and being that the SCCB write buffer
> allows about 4k bytes of data to be written to it, I felt it was safe to
> remove it.  It's unlikely we'd be writing that much data in the bios, plus
> that check did not exist prior to this fixup.
> 
> Though, reading that out loud, it probably isn't the best idea to sacrifice
> code robustness for code aesthetics.
> 
> for (i = len; i > 0; i--) {
>     if (data_len > SCCB_DATA_LEN - 1) {
>         return -SOME_ERROR
>     }
>     if (*p == '\n') {
>         sccb->data[data_len++] = '\r';
>     }
>     sccb->data[data_len++] = *p;
>     p++;
> }
> 
> What do you think?

Normally write() would just write less bytes than it was requested to
write and tell you that in the return value. So how about

for (i = 0; i < len; i++) {
    if ((data_len + 1) >= SCCB_DATA_LEN) {
        /* We would overflow the sccb buffer, abort early */
        len = i;
        break;
    }

    if (*p == '\n') {
        /* Terminal emulators might need \r\n, so generate it */
        sccb->data[data_len++] = '\r';
    }

    sccb->data[data_len++] = *p;
    p++;
}


Alex
Collin L. Walling Oct. 26, 2017, 8:54 p.m. UTC | #4
On 10/26/2017 04:48 PM, Alexander Graf wrote:
>
> On 26.10.17 22:37, Collin L. Walling wrote:
>> On 10/26/2017 04:25 PM, Alexander Graf wrote:
>>> On 26.10.17 20:52, Collin L. Walling wrote:
>>>> The sclp console in the s390 bios writes raw data,
>>>> leading console emulators (such as virsh console) to
>>>> treat a new line ('\n') as just a new line instead
>>>> of as a Unix line feed. Because of this, output
>>>> appears in a "stair case" pattern.
>>>>
>>>> Let's print \r\n on every occurrence of a new line
>>>> in the string passed to write to amend this issue.
>>>>
>>>> This is in sync with the guest Linux code in
>>>> drivers/s390/char/sclp_vt220.c which also does a line feed
>>>> conversion  in the console part of the driver.
>>>>
>>>> This fixes the s390-ccw and s390-netboot output like
>>>> $ virsh start test --console
>>>> Domain test started
>>>> Connected to domain test
>>>> Escape character is ^]
>>>> Network boot starting...
>>>>                             Using MAC address: 02:01:02:03:04:05
>>>>                                                                  
>>>> Requesting information via DHCP:  010
>>>>
>>>> Signed-off-by: Collin L. Walling <walling@linux.vnet.ibm.com>
>>>> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
>>>> ---
>>>>    pc-bios/s390-ccw/sclp.c | 16 +++++++++++++---
>>>>    1 file changed, 13 insertions(+), 3 deletions(-)
>>>>
>>>> diff --git a/pc-bios/s390-ccw/sclp.c b/pc-bios/s390-ccw/sclp.c
>>>> index 486fce1..f8ad5ae 100644
>>>> --- a/pc-bios/s390-ccw/sclp.c
>>>> +++ b/pc-bios/s390-ccw/sclp.c
>>>> @@ -68,17 +68,27 @@ void sclp_setup(void)
>>>>    long write(int fd, const void *str, size_t len)
>>>>    {
>>>>        WriteEventData *sccb = (void *)_sccb;
>>>> +    const char *p = str;
>>>> +    size_t data_len = 0;
>>>> +    size_t i;
>>>>          if (fd != 1 && fd != 2) {
>>>>            return -EIO;
>>>>        }
>>>>    -    sccb->h.length = sizeof(WriteEventData) + len;
>>>> +    for (i = len; i > 0; i--) {
>>> Where did the bounds check go? If you write(max) before, you were
>>> writing max bytes. If you do it now, you end up writing max + n bytes
>>> and potentially overflow the array, no?
>>>
>>>
>>> Alex
>> I wasn't a fan of the code aesthetics and being that the SCCB write buffer
>> allows about 4k bytes of data to be written to it, I felt it was safe to
>> remove it.  It's unlikely we'd be writing that much data in the bios, plus
>> that check did not exist prior to this fixup.
>>
>> Though, reading that out loud, it probably isn't the best idea to sacrifice
>> code robustness for code aesthetics.
>>
>> for (i = len; i > 0; i--) {
>>      if (data_len > SCCB_DATA_LEN - 1) {
>>          return -SOME_ERROR
>>      }
>>      if (*p == '\n') {
>>          sccb->data[data_len++] = '\r';
>>      }
>>      sccb->data[data_len++] = *p;
>>      p++;
>> }
>>
>> What do you think?
> Normally write() would just write less bytes than it was requested to
> write and tell you that in the return value. So how about
>
> for (i = 0; i < len; i++) {
>      if ((data_len + 1) >= SCCB_DATA_LEN) {
>          /* We would overflow the sccb buffer, abort early */
>          len = i;
>          break;
>      }
>
>      if (*p == '\n') {
>          /* Terminal emulators might need \r\n, so generate it */
>          sccb->data[data_len++] = '\r';
>      }
>
>      sccb->data[data_len++] = *p;
>      p++;
> }
>
>
> Alex
>
Makes sense to me.  I'll let this patch sit on the list for a little
while longer before fixing up for v3 in case Imight have missed
something else :)

Thanks for your time, Alex.
Cornelia Huck Oct. 27, 2017, 8:24 a.m. UTC | #5
On Thu, 26 Oct 2017 14:52:45 -0400
"Collin L. Walling" <walling@linux.vnet.ibm.com> wrote:

> The sclp console in the s390 bios writes raw data,
> leading console emulators (such as virsh console) to
> treat a new line ('\n') as just a new line instead
> of as a Unix line feed. Because of this, output
> appears in a "stair case" pattern.
> 
> Let's print \r\n on every occurrence of a new line
> in the string passed to write to amend this issue.
> 
> This is in sync with the guest Linux code in
> drivers/s390/char/sclp_vt220.c which also does a line feed
> conversion  in the console part of the driver. 
> 
> This fixes the s390-ccw and s390-netboot output like
> $ virsh start test --console
> Domain test started
> Connected to domain test
> Escape character is ^]
> Network boot starting...
>                           Using MAC address: 02:01:02:03:04:05
>                                                                 Requesting information via DHCP:  010
> 
> Signed-off-by: Collin L. Walling <walling@linux.vnet.ibm.com>
> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>

I'm a bit confused about that s-o-b chain... where does Christian come
in here?

[Nothing further from me about the actual code change.]

> ---
>  pc-bios/s390-ccw/sclp.c | 16 +++++++++++++---
>  1 file changed, 13 insertions(+), 3 deletions(-)
Christian Borntraeger Oct. 27, 2017, 2:14 p.m. UTC | #6
On 10/26/2017 10:54 PM, Collin L. Walling wrote:
> On 10/26/2017 04:48 PM, Alexander Graf wrote:
>>
>> On 26.10.17 22:37, Collin L. Walling wrote:
>>> On 10/26/2017 04:25 PM, Alexander Graf wrote:
>>>> On 26.10.17 20:52, Collin L. Walling wrote:
>>>>> The sclp console in the s390 bios writes raw data,
>>>>> leading console emulators (such as virsh console) to
>>>>> treat a new line ('\n') as just a new line instead
>>>>> of as a Unix line feed. Because of this, output
>>>>> appears in a "stair case" pattern.
>>>>>
>>>>> Let's print \r\n on every occurrence of a new line
>>>>> in the string passed to write to amend this issue.
>>>>>
>>>>> This is in sync with the guest Linux code in
>>>>> drivers/s390/char/sclp_vt220.c which also does a line feed
>>>>> conversion  in the console part of the driver.
>>>>>
>>>>> This fixes the s390-ccw and s390-netboot output like
>>>>> $ virsh start test --console
>>>>> Domain test started
>>>>> Connected to domain test
>>>>> Escape character is ^]
>>>>> Network boot starting...
>>>>>                             Using MAC address: 02:01:02:03:04:05
>>>>>                                                                  Requesting information via DHCP:  010
>>>>>
>>>>> Signed-off-by: Collin L. Walling <walling@linux.vnet.ibm.com>
>>>>> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
>>>>> ---
>>>>>    pc-bios/s390-ccw/sclp.c | 16 +++++++++++++---
>>>>>    1 file changed, 13 insertions(+), 3 deletions(-)
>>>>>
>>>>> diff --git a/pc-bios/s390-ccw/sclp.c b/pc-bios/s390-ccw/sclp.c
>>>>> index 486fce1..f8ad5ae 100644
>>>>> --- a/pc-bios/s390-ccw/sclp.c
>>>>> +++ b/pc-bios/s390-ccw/sclp.c
>>>>> @@ -68,17 +68,27 @@ void sclp_setup(void)
>>>>>    long write(int fd, const void *str, size_t len)
>>>>>    {
>>>>>        WriteEventData *sccb = (void *)_sccb;
>>>>> +    const char *p = str;
>>>>> +    size_t data_len = 0;
>>>>> +    size_t i;
>>>>>          if (fd != 1 && fd != 2) {
>>>>>            return -EIO;
>>>>>        }
>>>>>    -    sccb->h.length = sizeof(WriteEventData) + len;
>>>>> +    for (i = len; i > 0; i--) {
>>>> Where did the bounds check go? If you write(max) before, you were
>>>> writing max bytes. If you do it now, you end up writing max + n bytes
>>>> and potentially overflow the array, no?
>>>>
>>>>
>>>> Alex
>>> I wasn't a fan of the code aesthetics and being that the SCCB write buffer
>>> allows about 4k bytes of data to be written to it, I felt it was safe to
>>> remove it.  It's unlikely we'd be writing that much data in the bios, plus
>>> that check did not exist prior to this fixup.
>>>
>>> Though, reading that out loud, it probably isn't the best idea to sacrifice
>>> code robustness for code aesthetics.
>>>
>>> for (i = len; i > 0; i--) {
>>>      if (data_len > SCCB_DATA_LEN - 1) {
>>>          return -SOME_ERROR
>>>      }
>>>      if (*p == '\n') {
>>>          sccb->data[data_len++] = '\r';
>>>      }
>>>      sccb->data[data_len++] = *p;
>>>      p++;
>>> }
>>>
>>> What do you think?
>> Normally write() would just write less bytes than it was requested to
>> write and tell you that in the return value. So how about
>>
>> for (i = 0; i < len; i++) {
>>      if ((data_len + 1) >= SCCB_DATA_LEN) {
>>          /* We would overflow the sccb buffer, abort early */
>>          len = i;
>>          break;
>>      }
>>
>>      if (*p == '\n') {
>>          /* Terminal emulators might need \r\n, so generate it */
>>          sccb->data[data_len++] = '\r';
>>      }
>>
>>      sccb->data[data_len++] = *p;
>>      p++;
>> }
>>
>>
>> Alex
>>
> Makes sense to me.  I'll let this patch sit on the list for a little
> while longer before fixing up for v3 in case Imight have missed
> something else :)

Alex version looks sane. Can you post the patch today? soft freeze is approaching soon.
diff mbox

Patch

diff --git a/pc-bios/s390-ccw/sclp.c b/pc-bios/s390-ccw/sclp.c
index 486fce1..f8ad5ae 100644
--- a/pc-bios/s390-ccw/sclp.c
+++ b/pc-bios/s390-ccw/sclp.c
@@ -68,17 +68,27 @@  void sclp_setup(void)
 long write(int fd, const void *str, size_t len)
 {
     WriteEventData *sccb = (void *)_sccb;
+    const char *p = str;
+    size_t data_len = 0;
+    size_t i;
 
     if (fd != 1 && fd != 2) {
         return -EIO;
     }
 
-    sccb->h.length = sizeof(WriteEventData) + len;
+    for (i = len; i > 0; i--) {
+        if (*p == '\n') {
+            sccb->data[data_len++] = '\r';
+        }
+        sccb->data[data_len++] = *p;
+        p++;
+    }
+
+    sccb->h.length = sizeof(WriteEventData) + data_len;
     sccb->h.function_code = SCLP_FC_NORMAL_WRITE;
-    sccb->ebh.length = sizeof(EventBufferHeader) + len;
+    sccb->ebh.length = sizeof(EventBufferHeader) + data_len;
     sccb->ebh.type = SCLP_EVENT_ASCII_CONSOLE_DATA;
     sccb->ebh.flags = 0;
-    memcpy(sccb->data, str, len);
 
     sclp_service_call(SCLP_CMD_WRITE_EVENT_DATA, sccb);