Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

QEMU VC (graphical terminal) fixes #4660

Merged
merged 2 commits into from
Mar 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pkg/xen-tools/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ COPY initrd/poweroff /sbin/poweroff
COPY initrd/chroot2.c initrd/hacf.c /tmp/
COPY initrd/00000080 /etc/acpi/PWRF/
COPY initrd/eve-enter-container /bin/
COPY initrd/dotprofile /root/.profile
RUN gcc -s -o /chroot2 /tmp/chroot2.c -Wall -Werror
RUN gcc -s -o /hacf /tmp/hacf.c -Wall -Werror
RUN mkinitfs -n -F base -i /init-initrd -o /runx-initrd
Expand Down
1 change: 1 addition & 0 deletions pkg/xen-tools/initrd/base.files
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@
/etc/acpi/PWRF/00000080
/usr/sbin/chronyd
/var/lib/chrony/chrony.drift
/root/.profile
2 changes: 2 additions & 0 deletions pkg/xen-tools/initrd/dotprofile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# That what you should see in the shim VM prompt
PS1="\u@shim \W# "
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
From 075c5c40d6762c0f4e005ad114e35a2db7b102bc Mon Sep 17 00:00:00 2001
From: Roman Penyaev <[email protected]>
Date: Wed, 19 Feb 2025 10:35:59 +0100
Subject: [PATCH 1/3] ui/console-vc: introduce parsing for 'ESC ( B' sequence

This change introduces parsing of the 'ESC ( <ch>' sequence, which is
supposed to change character set [1]. In the QEMU case, the
introduced parsing logic does not actually change the character set, but
simply parses the sequence and does not let output of a tool to be
corrupted with leftovers: `top` sends 'ESC ( B', so if character
sequence is not parsed correctly, chracter 'B' appears in the output:

Btop - 11:08:42 up 5 min, 1 user, load average: 0BB
Tasks:B 158 Btotal,B 1 Brunning,B 157 Bsleeping,B 0 BsBB
%Cpu(s):B 0.0 Bus,B 0.0 Bsy,B 0.0 Bni,B 99.8 Bid,B 0.2 BB
MiB Mem :B 7955.6 Btotal,B 7778.6 Bfree,B 79.6 BB
MiB Swap:B 0.0 Btotal,B 0.0 Bfree,B 0.0 BB

PID USER PR NI VIRT RES SHR S B
B 735 root 20 0 9328 3540 3152 R B
B 1 root 20 0 20084 10904 8404 S B
B 2 root 20 0 0 0 0 S B

[1] https://vt100.net/docs/vt100-ug/chapter3.html#SCS

Signed-off-by: Roman Penyaev <[email protected]>
Cc: "Marc-André Lureau" <[email protected]>
Cc: [email protected]
Reviewed-by: Marc-André Lureau <[email protected]>
Message-ID: <[email protected]>
---
ui/console.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)

diff --git a/tools/qemu-xen/ui/console.c b/tools/qemu-xen/ui/console.c
index 7461446e711f..d5aaa34f669b 100644
--- a/tools/qemu-xen/ui/console.c
+++ b/tools/qemu-xen/ui/console.c
@@ -67,6 +67,8 @@ enum TTYState {
TTY_STATE_NORM,
TTY_STATE_ESC,
TTY_STATE_CSI,
+ TTY_STATE_G0,
+ TTY_STATE_G1,
};

typedef enum {
@@ -997,6 +999,10 @@ static void console_putchar(QemuConsole *s, int ch)
s->esc_params[i] = 0;
s->nb_esc_params = 0;
s->state = TTY_STATE_CSI;
+ } else if (ch == '(') {
+ s->state = TTY_STATE_G0;
+ } else if (ch == ')') {
+ s->state = TTY_STATE_G1;
} else {
s->state = TTY_STATE_NORM;
}
@@ -1147,6 +1153,16 @@ static void console_putchar(QemuConsole *s, int ch)
}
break;
}
+ break;
+ case TTY_STATE_G0: /* set character sets */
+ case TTY_STATE_G1: /* set character sets */
+ switch (ch) {
+ case 'B':
+ /* Latin-1 map */
+ break;
+ }
+ s->state = TTY_STATE_NORM;
+ break;
}
}

--
2.43.0

Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
From 84bc76e2c23fb4a677990e9b45ee68f9a323ff4c Mon Sep 17 00:00:00 2001
From: Roman Penyaev <[email protected]>
Date: Wed, 19 Feb 2025 10:37:19 +0100
Subject: [PATCH 2/3] ui/console-vc: report to the application instead of
screen rendering

Terminal Device Status Report (DSR) [1] should be sent to an
application, not rendered to the screen. This patch fixes rendering of
terminal report, which appear only on the graphical screen of the
terminal (console "vc") and can be reproduced by the following
command:

echo -en '\e[6n'; IFS='[;' read -sdR _ row col; echo $row:$col

Command requests cursor position and waits for terminal response, but
instead, the response is rendered to the graphical screen and never
sent to an application.

Why bother? Busybox shell (ash) in Alpine distribution requests cursor
position on each shell prompt (once <ENTER> is pressed), which makes a
prompt on a graphical screen corrupted with repeating Cursor Position
Report (CPR) [2]:

[root@alpine ~]# \033[57;1R]

Which is very annoying and incorrect.

[1] https://vt100.net/docs/vt100-ug/chapter3.html#DSR
[2] https://vt100.net/docs/vt100-ug/chapter3.html#CPR

Signed-off-by: Roman Penyaev <[email protected]>
Cc: "Marc-André Lureau" <[email protected]>
Cc: [email protected]
Reviewed-by: Marc-André Lureau <[email protected]>
Message-ID: <[email protected]>
---
ui/console.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/tools/qemu-xen/ui/console.c b/tools/qemu-xen/ui/console.c
index d5aaa34f669b..8226a17b37e5 100644
--- a/tools/qemu-xen/ui/console.c
+++ b/tools/qemu-xen/ui/console.c
@@ -923,10 +923,7 @@ static void console_put_one(QemuConsole *s, int ch)

static void console_respond_str(QemuConsole *s, const char *buf)
{
- while (*buf) {
- console_put_one(s, *buf);
- buf++;
- }
+ qemu_chr_be_write(s->chr, (const uint8_t *)buf, strlen(buf));
}

/* set cursor, checking bounds */
--
2.43.0

Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
From 703cf69423fe1342e2716e93b74d87b319a9f6fc Mon Sep 17 00:00:00 2001
From: Roman Penyaev <[email protected]>
Date: Wed, 19 Feb 2025 10:39:54 +0100
Subject: [PATCH 3/3] ui/console-vc: report viewport row number, not of the
whole scroll buffer

The format of the CSI cursor position report is `ESC[row;columnR`,
where `row` is a row of a cursor in the screen, not in the scrollback
buffer. What's the difference? Let's say the terminal screen has 24
lines, no matter how long the scrollback buffer may be, the last line
is the 24th.

For example the following command can be executed in xterm on the last
screen line:

$ echo -en '\e[6n'; IFS='[;' read -sdR _ row col; echo $row:$col
24:1

It shows the cursor position on the current screen and not relative
to the backscroll buffer.

Before this change the row number was always increasing for the QEMU
VC and represents the cursor position relative to the backscroll
buffer.

Signed-off-by: Roman Penyaev <[email protected]>
Cc: "Marc-André Lureau" <[email protected]>
Cc: [email protected]
Reviewed-by: Marc-André Lureau <[email protected]>
Message-ID: <[email protected]>
---
ui/console.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/tools/qemu-xen/ui/console.c b/tools/qemu-xen/ui/console.c
index 8226a17b37e5..10ea34aea1b1 100644
--- a/tools/qemu-xen/ui/console.c
+++ b/tools/qemu-xen/ui/console.c
@@ -1128,8 +1128,7 @@ static void console_putchar(QemuConsole *s, int ch)
case 6:
/* report cursor position */
sprintf(response, "\033[%d;%dR",
- (s->y_base + s->y) % s->total_height + 1,
- s->x + 1);
+ s->y + 1, s->x + 1);
console_respond_str(s, response);
break;
}
--
2.43.0

Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
From 276ec776b18bb4b82e83ddfe68029ca0db845287 Mon Sep 17 00:00:00 2001
From: Roman Penyaev <[email protected]>
Date: Sun, 23 Feb 2025 10:31:24 +0100
Subject: [PATCH 1/1] ui/console-vc: implement DCH (delete) and ICH (insert)
commands
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This patch implements DCH (delete character) and ICH (insert
character) commands.

DCH - Delete Character:
"As characters are deleted, the remaining characters between the
cursor and right margin move to the left. Character attributes move
with the characters. The terminal adds blank spaces with no visual
character attributes at the right margin. DCH has no effect outside
the scrolling margins" [1].

ICH - Insert Character:
"The ICH sequence inserts Pn blank characters with the normal
character attribute. The cursor remains at the beginning of the
blank characters. Text between the cursor and right margin moves to
the right. Characters scrolled past the right margin are lost. ICH
has no effect outside the scrolling margins" [2].

Without these commands console is barely usable.

[1] https://vt100.net/docs/vt510-rm/DCH.html
[2] https://vt100.net/docs/vt510-rm/ICH.html

Signed-off-by: Roman Penyaev <[email protected]>
Cc: "Marc-André Lureau" <[email protected]>
Cc: [email protected]
Reviewed-by: Marc-André Lureau <[email protected]>
Message-ID: <[email protected]>
---
tools/qemu-xen/ui/console.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 98 insertions(+), 6 deletions(-)

diff --git a/tools/qemu-xen/ui/console.c b/tools/qemu-xen/ui/console.c
index a8eb28b937a1..a7aa23be328b 100644
--- a/tools/qemu-xen/ui/console.c
+++ b/tools/qemu-xen/ui/console.c
@@ -946,6 +952,86 @@ static void set_cursor(QemuConsole *s, int x, int y)
s->y = y;
}

+/**
+ * vc_csi_P() - (DCH) deletes one or more characters from the cursor
+ * position to the right. As characters are deleted, the remaining
+ * characters between the cursor and right margin move to the
+ * left. Character attributes move with the characters.
+ */
+static void vc_csi_P(struct QemuConsole *s, unsigned int nr)
+{
+ TextCell *c1, *c2;
+ unsigned int x1, x2, y;
+ unsigned int end, len;
+
+ if (!nr) {
+ nr = 1;
+ }
+ if (nr > s->width - s->x) {
+ nr = s->width - s->x;
+ if (!nr) {
+ return;
+ }
+ }
+
+ x1 = s->x;
+ x2 = s->x + nr;
+ len = s->width - x2;
+ if (len) {
+ y = (s->y_base + s->y) % s->total_height;
+ c1 = &s->cells[y * s->width + x1];
+ c2 = &s->cells[y * s->width + x2];
+ memmove(c1, c2, len * sizeof(*c1));
+ for (end = x1 + len; x1 < end; x1++) {
+ update_xy(s, x1, s->y);
+ }
+ }
+ /* Clear the rest */
+ for (; x1 < s->width; x1++) {
+ console_clear_xy(s, x1, s->y);
+ }
+}
+
+/**
+ * vc_csi_at() - (ICH) inserts `nr` blank characters with the default
+ * character attribute. The cursor remains at the beginning of the
+ * blank characters. Text between the cursor and right margin moves to
+ * the right. Characters scrolled past the right margin are lost.
+ */
+static void vc_csi_at(struct QemuConsole *s, unsigned int nr)
+{
+ TextCell *c1, *c2;
+ unsigned int x1, x2, y;
+ unsigned int end, len;
+
+ if (!nr) {
+ nr = 1;
+ }
+ if (nr > s->width - s->x) {
+ nr = s->width - s->x;
+ if (!nr) {
+ return;
+ }
+ }
+
+ x1 = s->x + nr;
+ x2 = s->x;
+ len = s->width - x1;
+ if (len) {
+ y = (s->y_base + s->y) % s->total_height;
+ c1 = &s->cells[y * s->width + x1];
+ c2 = &s->cells[y * s->width + x2];
+ memmove(c1, c2, len * sizeof(*c1));
+ for (end = x1 + len; x1 < end; x1++) {
+ update_xy(s, x1, s->y);
+ }
+ }
+ /* Insert blanks */
+ for (x1 = s->x; x1 < s->x + nr; x1++) {
+ console_clear_xy(s, x1, s->y);
+ }
+}
+
static void console_putchar(QemuConsole *s, int ch)
{
int i;
@@ -1116,6 +1202,9 @@ static void console_putchar(QemuConsole *s, int ch)
break;
}
break;
+ case 'P':
+ vc_csi_P(s, s->esc_params[0]);
+ break;
case 'm':
console_handle_escape(s);
break;
@@ -1143,6 +1232,9 @@ static void console_putchar(QemuConsole *s, int ch)
s->x = s->x_saved;
s->y = s->y_saved;
break;
+ case '@':
+ vc_csi_at(s, s->esc_params[0]);
+ break;
default:
trace_console_putchar_unhandled(ch);
break;
--
2.43.0

Loading