[PATCH v2 5/5] arm: apple: Do not list bootflows on boot
From: Janne Grunau The bootflow list is only seen briefly and is probably more confusing than helpful. Signed-off-by: Janne Grunau --- configs/apple_m1_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/apple_m1_defconfig b/configs/apple_m1_defconfig index c30aec7c55..4eac1a9e2d 100644 --- a/configs/apple_m1_defconfig +++ b/configs/apple_m1_defconfig @@ -8,6 +8,7 @@ CONFIG_SYS_CBSIZE=256 CONFIG_SYS_PBSIZE=276 # CONFIG_DISPLAY_CPUINFO is not set CONFIG_DISPLAY_BOARDINFO_LATE=y +CONFIG_BOOTCOMMAND="bootflow scan -b" CONFIG_BOARD_LATE_INIT=y CONFIG_CMD_SELECT_FONT=y # CONFIG_NET is not set -- 2.44.0
[PATCH v2 1/5] apple_m1_defconfig: Turn on CONFIG_SYS_64BIT_LBA
From: Hector Martin This makes USB HDDs >2TiB work. The only reason this hasn't bitten us for the internal NVMe yet is the 4K sector size, because the largest SSD Apple sells is 8TB and we can handle up to 16TiB with that sector size. Close call. Signed-off-by: Hector Martin Reviewed-by: Mark Kettenis Reviewed-by: Neal Gompa Signed-off-by: Janne Grunau --- configs/apple_m1_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/apple_m1_defconfig b/configs/apple_m1_defconfig index e00d72e8be..31d966f0ab 100644 --- a/configs/apple_m1_defconfig +++ b/configs/apple_m1_defconfig @@ -10,6 +10,7 @@ CONFIG_SYS_PBSIZE=276 CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_BOARD_LATE_INIT=y # CONFIG_NET is not set +CONFIG_SYS_64BIT_LBA=y CONFIG_APPLE_SPI_KEYB=y # CONFIG_MMC is not set CONFIG_NVME_APPLE=y -- 2.44.0
[PATCH v2 3/5] configs: apple: Enable CMD_SELECT_FONT and FONT_16X32
From: Janne Grunau Apple devices have high DPI displays so the larger fonts are preferable for improved readability. This does not yet change the used font based on the display's pixel density so the standard 8x16 font is still used by default. Reviewed-by: Mark Kettenis Reviewed-by: Neal Gompa Signed-off-by: Janne Grunau --- configs/apple_m1_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configs/apple_m1_defconfig b/configs/apple_m1_defconfig index 31d966f0ab..c30aec7c55 100644 --- a/configs/apple_m1_defconfig +++ b/configs/apple_m1_defconfig @@ -9,6 +9,7 @@ CONFIG_SYS_PBSIZE=276 # CONFIG_DISPLAY_CPUINFO is not set CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_BOARD_LATE_INIT=y +CONFIG_CMD_SELECT_FONT=y # CONFIG_NET is not set CONFIG_SYS_64BIT_LBA=y CONFIG_APPLE_SPI_KEYB=y @@ -19,6 +20,7 @@ CONFIG_USB_XHCI_DWC3=y CONFIG_USB_XHCI_PCI=y CONFIG_USB_DWC3=y CONFIG_USB_KEYBOARD=y +CONFIG_VIDEO_FONT_16X32=y CONFIG_SYS_WHITE_ON_BLACK=y CONFIG_NO_FB_CLEAR=y CONFIG_VIDEO_SIMPLE=y -- 2.44.0
[PATCH v2 0/5] configs: apple: Switch to standard boot + small adjustments
This series contains a few misc config changes for Apple silicon systems: - switch from the deprecated distro boot scripts to standard boot - allows EFI console resizing based on the video console size - enables 16x32 bitmap fonts as Apple devices come with high DPI displays - enables 64-bit LBA addressing Signed-off-by: Janne Grunau --- Changes in v2: - added Reviewed-by: tags - switched to BOOTSTD_FULL to enable efi_bootmgr and make interactive use easier - override BOOTCOMMAND to not list the bootflows - rebased onto v2024.04 - Link to v1: https://lore.kernel.org/r/20240317-apple_config-v1-0-1b862bc14...@jannau.net --- Hector Martin (1): apple_m1_defconfig: Turn on CONFIG_SYS_64BIT_LBA Janne Grunau (4): configs: apple: Use "vidconsole,serial" as stdout/stderr configs: apple: Enable CMD_SELECT_FONT and FONT_16X32 arm: apple: Switch to standard boot arm: apple: Do not list bootflows on boot arch/arm/Kconfig | 2 +- configs/apple_m1_defconfig | 4 include/configs/apple.h| 24 3 files changed, 9 insertions(+), 21 deletions(-) --- base-commit: 25049ad560826f7dc1c4740883b0016014a59789 change-id: 20240317-apple_config-981fcd9028b9 Best regards, -- Janne Grunau
[PATCH v2 2/5] configs: apple: Use "vidconsole,serial" as stdout/stderr
From: Janne Grunau The display size querying in efi_console relies on this order. The display should be the primary output device and should be used to display more than 80x25 chars. Reviewed-by: Mark Kettenis Reviewed-by: Neal Gompa Signed-off-by: Janne Grunau --- include/configs/apple.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/configs/apple.h b/include/configs/apple.h index 0576bc04c9..a70440b3ad 100644 --- a/include/configs/apple.h +++ b/include/configs/apple.h @@ -6,8 +6,8 @@ /* Environment */ #define ENV_DEVICE_SETTINGS \ "stdin=serial,usbkbd,spikbd\0" \ - "stdout=serial,vidconsole\0" \ - "stderr=serial,vidconsole\0" + "stdout=vidconsole,serial\0" \ + "stderr=vidconsole,serial\0" #if IS_ENABLED(CONFIG_CMD_NVME) #define BOOT_TARGET_NVME(func) func(NVME, nvme, 0) -- 2.44.0
[PATCH v2 4/5] arm: apple: Switch to standard boot
From: Janne Grunau Use standard boot instead of the distro boot scripts. Use BOOTSTD_FULL instead of BOOTSTD_DEFAULTS for easier interactive use. Signed-off-by: Janne Grunau --- arch/arm/Kconfig| 2 +- include/configs/apple.h | 20 ++-- 2 files changed, 3 insertions(+), 19 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 01d6556c42..9b83b2e6f8 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1034,7 +1034,7 @@ config ARCH_APPLE select USB imply CMD_DM imply CMD_GPT - imply DISTRO_DEFAULTS + imply BOOTSTD_FULL imply OF_HAS_PRIOR_STAGE config ARCH_OWL diff --git a/include/configs/apple.h b/include/configs/apple.h index a70440b3ad..1e08b11448 100644 --- a/include/configs/apple.h +++ b/include/configs/apple.h @@ -9,26 +9,10 @@ "stdout=vidconsole,serial\0" \ "stderr=vidconsole,serial\0" -#if IS_ENABLED(CONFIG_CMD_NVME) - #define BOOT_TARGET_NVME(func) func(NVME, nvme, 0) -#else - #define BOOT_TARGET_NVME(func) -#endif - -#if IS_ENABLED(CONFIG_CMD_USB) - #define BOOT_TARGET_USB(func) func(USB, usb, 0) -#else - #define BOOT_TARGET_USB(func) -#endif - -#define BOOT_TARGET_DEVICES(func) \ - BOOT_TARGET_NVME(func) \ - BOOT_TARGET_USB(func) - -#include +#define BOOT_TARGETS "nvme usb" #define CFG_EXTRA_ENV_SETTINGS \ ENV_DEVICE_SETTINGS \ - BOOTENV + "boot_targets=" BOOT_TARGETS "\0" #endif -- 2.44.0
[PATCH v4 1/6] usb: xhci: refactor xhci_set_configuration
From: Janne Grunau In the next step endpoints for multiple interfaces are set up. Move most of the per endpoint initialization to separate function to avoid another identation level. Reviewed-by: Marek Vasut Reviewed-by: Neal Gompa Signed-off-by: Janne Grunau --- drivers/usb/host/xhci.c | 119 +--- 1 file changed, 73 insertions(+), 46 deletions(-) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index d13cbff9b3..534c4b973f 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -475,67 +475,34 @@ static int xhci_configure_endpoints(struct usb_device *udev, bool ctx_change) } /** - * Configure the endpoint, programming the device contexts. + * Fill endpoint contexts for interface descriptor ifdesc. * - * @param udev pointer to the USB device structure - * Return: returns the status of the xhci_configure_endpoints + * @param udev pointer to the USB device structure + * @param ctrl pointer to the xhci pravte device structure + * @param virt_dev pointer to the xhci virtual device structure + * @param ifdesc pointer to the USB interface config descriptor + * Return: returns the status of xhci_init_ep_contexts_if */ -static int xhci_set_configuration(struct usb_device *udev) +static int xhci_init_ep_contexts_if(struct usb_device *udev, + struct xhci_ctrl *ctrl, + struct xhci_virt_device *virt_dev, + struct usb_interface *ifdesc + ) { - struct xhci_container_ctx *in_ctx; - struct xhci_container_ctx *out_ctx; - struct xhci_input_control_ctx *ctrl_ctx; - struct xhci_slot_ctx *slot_ctx; struct xhci_ep_ctx *ep_ctx[MAX_EP_CTX_NUM]; int cur_ep; - int max_ep_flag = 0; int ep_index; unsigned int dir; unsigned int ep_type; - struct xhci_ctrl *ctrl = xhci_get_ctrl(udev); - int num_of_ep; - int ep_flag = 0; u64 trb_64 = 0; - int slot_id = udev->slot_id; - struct xhci_virt_device *virt_dev = ctrl->devs[slot_id]; - struct usb_interface *ifdesc; u32 max_esit_payload; unsigned int interval; unsigned int mult; unsigned int max_burst; unsigned int avg_trb_len; unsigned int err_count = 0; + int num_of_ep = ifdesc->no_of_ep; - out_ctx = virt_dev->out_ctx; - in_ctx = virt_dev->in_ctx; - - num_of_ep = udev->config.if_desc[0].no_of_ep; - ifdesc = >config.if_desc[0]; - - ctrl_ctx = xhci_get_input_control_ctx(in_ctx); - /* Initialize the input context control */ - ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG); - ctrl_ctx->drop_flags = 0; - - /* EP_FLAG gives values 1 & 4 for EP1OUT and EP2IN */ - for (cur_ep = 0; cur_ep < num_of_ep; cur_ep++) { - ep_flag = xhci_get_ep_index(>ep_desc[cur_ep]); - ctrl_ctx->add_flags |= cpu_to_le32(1 << (ep_flag + 1)); - if (max_ep_flag < ep_flag) - max_ep_flag = ep_flag; - } - - xhci_inval_cache((uintptr_t)out_ctx->bytes, out_ctx->size); - - /* slot context */ - xhci_slot_copy(ctrl, in_ctx, out_ctx); - slot_ctx = xhci_get_slot_ctx(ctrl, in_ctx); - slot_ctx->dev_info &= ~(cpu_to_le32(LAST_CTX_MASK)); - slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(max_ep_flag + 1) | 0); - - xhci_endpoint_copy(ctrl, in_ctx, out_ctx, 0); - - /* filling up ep contexts */ for (cur_ep = 0; cur_ep < num_of_ep; cur_ep++) { struct usb_endpoint_descriptor *endpt_desc = NULL; struct usb_ss_ep_comp_descriptor *ss_ep_comp_desc = NULL; @@ -561,7 +528,8 @@ static int xhci_set_configuration(struct usb_device *udev) avg_trb_len = max_esit_payload; ep_index = xhci_get_ep_index(endpt_desc); - ep_ctx[ep_index] = xhci_get_ep_ctx(ctrl, in_ctx, ep_index); + ep_ctx[ep_index] = xhci_get_ep_ctx(ctrl, virt_dev->in_ctx, + ep_index); /* Allocate the ep rings */ virt_dev->eps[ep_index].ring = xhci_ring_alloc(ctrl, 1, true); @@ -614,6 +582,65 @@ static int xhci_set_configuration(struct usb_device *udev) } } + return 0; +} + +/** + * Configure the endpoint, programming the device contexts. + * + * @param udev pointer to the USB device structure + * Return: returns the status of the xhci_configure_endpoints + */ +static int xhci_set_configuration(struct usb_device *udev) +{ + struct xhci_container_ctx *out_ctx; + struct xhci_container_ctx *in_ctx; + struct xhci_input_control_ctx *ctrl_ctx; + struct xhci_slot_ctx *slot_ctx; + int err; + int cur_ep; + int max_ep_flag = 0; + struct xhci_ctrl *ctrl = xhci_get_ctrl(udev); + int
[PATCH v4 2/6] usb: xhci: Set up endpoints for the first 2 interfaces
From: Janne Grunau The xhci driver currently only does the necessary initialization for endpoints found in the first interface descriptor. Apple USB keyboards (released 2021) use the second interface descriptor for the HID keyboard boot protocol. To allow USB drivers to use endpoints from other interface descriptors the xhci driver needs to ensure these endpoints are initialized as well. Use USB_MAX_ACTIVE_INTERFACES to control how many interface descriptors are considered during endpoint initialisation. For now define it to 2 as that is sufficient for supporting the Apple keyboards. Reviewed-by: Marek Vasut Reviewed-by: Neal Gompa Signed-off-by: Janne Grunau --- drivers/usb/host/xhci.c | 31 +++ include/usb.h | 6 ++ 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 534c4b973f..741e186ee0 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -606,24 +606,28 @@ static int xhci_set_configuration(struct usb_device *udev) int slot_id = udev->slot_id; struct xhci_virt_device *virt_dev = ctrl->devs[slot_id]; struct usb_interface *ifdesc; + unsigned int ifnum; + unsigned int max_ifnum = min((unsigned int)USB_MAX_ACTIVE_INTERFACES, +(unsigned int)udev->config.no_of_if); out_ctx = virt_dev->out_ctx; in_ctx = virt_dev->in_ctx; - num_of_ep = udev->config.if_desc[0].no_of_ep; - ifdesc = >config.if_desc[0]; - ctrl_ctx = xhci_get_input_control_ctx(in_ctx); /* Initialize the input context control */ ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG); ctrl_ctx->drop_flags = 0; - /* EP_FLAG gives values 1 & 4 for EP1OUT and EP2IN */ - for (cur_ep = 0; cur_ep < num_of_ep; cur_ep++) { - ep_flag = xhci_get_ep_index(>ep_desc[cur_ep]); - ctrl_ctx->add_flags |= cpu_to_le32(1 << (ep_flag + 1)); - if (max_ep_flag < ep_flag) - max_ep_flag = ep_flag; + for (ifnum = 0; ifnum < max_ifnum; ifnum++) { + ifdesc = >config.if_desc[ifnum]; + num_of_ep = ifdesc->no_of_ep; + /* EP_FLAG gives values 1 & 4 for EP1OUT and EP2IN */ + for (cur_ep = 0; cur_ep < num_of_ep; cur_ep++) { + ep_flag = xhci_get_ep_index(>ep_desc[cur_ep]); + ctrl_ctx->add_flags |= cpu_to_le32(1 << (ep_flag + 1)); + if (max_ep_flag < ep_flag) + max_ep_flag = ep_flag; + } } xhci_inval_cache((uintptr_t)out_ctx->bytes, out_ctx->size); @@ -637,9 +641,12 @@ static int xhci_set_configuration(struct usb_device *udev) xhci_endpoint_copy(ctrl, in_ctx, out_ctx, 0); /* filling up ep contexts */ - err = xhci_init_ep_contexts_if(udev, ctrl, virt_dev, ifdesc); - if (err < 0) - return err; + for (ifnum = 0; ifnum < max_ifnum; ifnum++) { + ifdesc = >config.if_desc[ifnum]; + err = xhci_init_ep_contexts_if(udev, ctrl, virt_dev, ifdesc); + if (err < 0) + return err; + } return xhci_configure_endpoints(udev, false); } diff --git a/include/usb.h b/include/usb.h index 09e3f0cb30..3aafdc8bfd 100644 --- a/include/usb.h +++ b/include/usb.h @@ -49,6 +49,12 @@ extern bool usb_started; /* flag for the started/stopped USB status */ */ #define USB_TIMEOUT_MS(pipe) (usb_pipebulk(pipe) ? 5000 : 1000) +/* + * The xhcd hcd driver prepares only a limited number interfaces / endpoints. + * Define this limit so that drivers do not exceed it. + */ +#define USB_MAX_ACTIVE_INTERFACES 2 + /* device request (setup) */ struct devrequest { __u8requesttype; -- 2.44.0
[PATCH v4 4/6] usb: Add environment based device ignorelist
From: Janne Grunau Add the environment variable "usb_ignorelist" to prevent USB devices listed in it from being bound to drivers. This allows to ignore devices which are undesirable or trigger bugs in u-boot's USB stack. Devices emulating keyboards are one example of undesirable devices as u-boot currently supports only a single USB keyboard device. Most commonly, people run into this with Yubikeys, so let's ignore those in the default environment. Based on previous USB keyboard specific patches for the same purpose. Link: https://lore.kernel.org/u-boot/7ab604fb-0fec-4f5e-8708-7a3a7e2cb...@denx.de/ Reviewed-by: Neal Gompa Reviewed-by: Marek Vasut Signed-off-by: Janne Grunau --- common/usb.c | 64 +++ doc/usage/environment.rst | 13 ++ include/env_default.h | 11 3 files changed, 88 insertions(+) diff --git a/common/usb.c b/common/usb.c index 836506dcd9..44db07742e 100644 --- a/common/usb.c +++ b/common/usb.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -1084,6 +1085,48 @@ static int usb_prepare_device(struct usb_device *dev, int addr, bool do_read, return 0; } +static int usb_device_is_ignored(u16 id_vendor, u16 id_product) +{ + ulong vid, pid; + char *end; + const char *cur = env_get("usb_ignorelist"); + + /* parse "usb_ignorelist" strictly */ + while (cur && cur[0] != '\0') { + vid = simple_strtoul(cur, , 0); + /* +* If strtoul did not parse a single digit or the next char is +* not ':' the ignore list is malformed. +*/ + if (cur == end || end[0] != ':') + return -EINVAL; + + cur = end + 1; + pid = simple_strtoul(cur, , 0); + /* Consider '*' as wildcard for the product ID */ + if (cur == end && end[0] == '*') { + pid = U16_MAX + 1; + end++; + } + /* +* The ignore list is malformed if no product ID / wildcard was +* parsed or entries are not separated by ',' or terminated with +* '\0'. +*/ + if (cur == end || (end[0] != ',' && end[0] != '\0')) + return -EINVAL; + + if (id_vendor == vid && (pid > U16_MAX || id_product == pid)) + return -ENODEV; + + if (end[0] == '\0') + break; + cur = end + 1; + } + + return 0; +} + int usb_select_config(struct usb_device *dev) { unsigned char *tmpbuf = NULL; @@ -1099,6 +1142,27 @@ int usb_select_config(struct usb_device *dev) le16_to_cpus(>descriptor.idProduct); le16_to_cpus(>descriptor.bcdDevice); + /* ignore devices from usb_ignorelist */ + err = usb_device_is_ignored(dev->descriptor.idVendor, + dev->descriptor.idProduct); + if (err == -ENODEV) { + dev_dbg(dev->dev, "Ignoring USB device 0x%x:0x%x\n", + dev->descriptor.idVendor, dev->descriptor.idProduct); + return err; + } else if (err == -EINVAL) { + /* +* Continue on "usb_ignorelist" parsing errors. The list is +* parsed for each device returning the error would result in +* ignoring all USB devices. +* Since the parsing error is independent of the probed device +* report errors with printf instead of dev_err. +*/ + printf("usb_ignorelist parse error in \"%s\"\n", + env_get("usb_ignorelist")); + } else if (err < 0) { + return err; + } + /* * Kingston DT Ultimate 32GB USB 3.0 seems to be extremely sensitive * about this first Get Descriptor request. If there are any other diff --git a/doc/usage/environment.rst b/doc/usage/environment.rst index ebf75fa948..7d4b448cb3 100644 --- a/doc/usage/environment.rst +++ b/doc/usage/environment.rst @@ -366,6 +366,19 @@ tftpwindowsize This means the count of blocks we can receive before sending ack to server. +usb_ignorelist +Ignore USB devices to prevent binding them to an USB device driver. This can +be used to ignore devices are for some reason undesirable or causes crashes +u-boot's USB stack. +An example for undesired behavior is the keyboard emulation of security keys +like Yubikeys. U-boot currently supports only a single USB keyboard device +so try to probe an useful keyboard device. The default environment blocks +Yubico devices as common devices emulating keyboards. +Devices are matched by idVendor and idProduct. The variable contains a comma +separated list of idVendor:idProduct pairs
[PATCH v4 0/6] USB keyboard improvements for asahi / desktop systems
Apple USB Keyboards from 2021 need quirks to be useable. The boot HID keyboard protocol is unfortunately not described in the first interface descriptor but the second. This needs several changes. The USB keyboard driver has to look at all (2) interface descriptors during probing. Since I didn't want to rebuild the USB driver probe code the Apple keyboards are bound to the keyboard driver via USB vendor and product IDs. To make the keyboards useable on Apple silicon devices the xhci driver needs to initializes rings for the endpoints of the first two interface descriptors. If this is causes concerns regarding regressions or memory use the USB_MAX_ACTIVE_INTERFACES define could be turned into a CONFIG option. Even after this changes the keyboards still do not probe successfully since they apparently do not behave HID standard compliant. They only generate reports on key events. This leads the final check whether the keyboard is operational to fail unless the user presses keys during the probe. Skip this check for known keyboards. Keychron seems to emulate Apple keyboards (some models even "re-use" Apple's USB vendor ID) so apply this quirk as well. Some devices like Yubikeys emulate a keyboard. since u-boot only binds a single keyboard block this kind of devices from the USB keyboard driver. Signed-off-by: Janne Grunau --- Changes in v4: - collects "Reviewed-by:" tagDITME: describe what is new in this series revision. - adds comment about usb_ignorelist parse errors - Link to v3: https://lore.kernel.org/r/20240322-asahi-keyboards-v3-0-3106dd4c4...@jannau.net Changes in v3: - collected "Reviewed-by:" tags - rename usb_blocklist to usb_ignorelist - use BIT macro for USB KBD quirk bit - refactor usb_device_is_blocked() to use 0 / negated errors as return value, sed -e 's/block/ignore/', simplify it and add comments - rewritten usb_ignorelist documentation - Link to v2: https://lore.kernel.org/r/20240317-asahi-keyboards-v2-0-d3f4b8384...@jannau.net Changes in v2: - rewritten commit message for "[PATCH 2/6] usb: xhci: Set up endpoints for the first 2 interfaces" - Replaced the usb keyboard Yubikey block with an env based USB device blocklist - Use "-EINVAL" as return value in "[PATCH 3/6] usb: xhci: Abort transfers with unallocated rings" - added "Reviewed-by:" tags - Link to v1: https://lore.kernel.org/r/20240221-asahi-keyboards-v1-0-814b2e741...@jannau.net --- Janne Grunau (6): usb: xhci: refactor xhci_set_configuration usb: xhci: Set up endpoints for the first 2 interfaces usb: xhci: Abort transfers with unallocated rings usb: Add environment based device ignorelist usb: kbd: support Apple Magic Keyboards (2021) usb: kbd: Add probe quirk for Apple and Keychron keyboards common/usb.c | 64 ++ common/usb_kbd.c | 59 ++-- doc/usage/environment.rst| 13 + drivers/usb/host/xhci-ring.c | 5 ++ drivers/usb/host/xhci.c | 126 +++ include/env_default.h| 11 include/usb.h| 6 +++ 7 files changed, 235 insertions(+), 49 deletions(-) --- base-commit: 37345abb97ef0dd9c50a03b2a72617612dcae585 change-id: 20240218-asahi-keyboards-f2ddaf0022b2 Best regards, -- Janne Grunau
[PATCH v4 5/6] usb: kbd: support Apple Magic Keyboards (2021)
From: Janne Grunau Apple USB keyboards (Magic Keyboard from 2021 (product id 0x029c)) carry the HID keyboard boot protocol on the second interface descriptor. Probe via vendor and product IDs since the class/subclass/protocol match uses the first interface descriptor. Probe the two first interface descriptors for the HID keyboard boot protocol. USB configuration descriptor for reference: | Bus 003 Device 002: ID 05ac:029c Apple, Inc. Magic Keyboard | Device Descriptor: | bLength18 | bDescriptorType 1 | bcdUSB 2.00 | bDeviceClass0 [unknown] | bDeviceSubClass 0 [unknown] | bDeviceProtocol 0 | bMaxPacketSize064 | idVendor 0x05ac Apple, Inc. | idProduct 0x029c Magic Keyboard | bcdDevice3.90 | iManufacturer 1 Apple Inc. | iProduct2 Magic Keyboard | iSerial 3 ... | bNumConfigurations 1 | Configuration Descriptor: | bLength 9 | bDescriptorType 2 | wTotalLength 0x003b | bNumInterfaces 2 | bConfigurationValue 1 | iConfiguration 4 Keyboard | bmAttributes 0xa0 | (Bus Powered) | Remote Wakeup | MaxPower 500mA | Interface Descriptor: | bLength 9 | bDescriptorType 4 | bInterfaceNumber0 | bAlternateSetting 0 | bNumEndpoints 1 | bInterfaceClass 3 Human Interface Device | bInterfaceSubClass 0 [unknown] | bInterfaceProtocol 0 | iInterface 5 Device Management | HID Device Descriptor: | bLength 9 | bDescriptorType33 | bcdHID 1.10 | bCountryCode0 Not supported | bNumDescriptors 1 | bDescriptorType34 Report | wDescriptorLength 83 | Report Descriptors: | ** UNAVAILABLE ** | Endpoint Descriptor: | bLength 7 | bDescriptorType 5 | bEndpointAddress 0x81 EP 1 IN | bmAttributes3 | Transfer TypeInterrupt | Synch Type None | Usage Type Data | wMaxPacketSize 0x0010 1x 16 bytes | bInterval 8 | Interface Descriptor: | bLength 9 | bDescriptorType 4 | bInterfaceNumber1 | bAlternateSetting 0 | bNumEndpoints 1 | bInterfaceClass 3 Human Interface Device | bInterfaceSubClass 1 Boot Interface Subclass | bInterfaceProtocol 1 Keyboard | iInterface 6 Keyboard / Boot | HID Device Descriptor: | bLength 9 | bDescriptorType33 | bcdHID 1.10 | bCountryCode 13 International (ISO) | bNumDescriptors 1 | bDescriptorType34 Report | wDescriptorLength 207 | Report Descriptors: | ** UNAVAILABLE ** | Endpoint Descriptor: | bLength 7 | bDescriptorType 5 | bEndpointAddress 0x82 EP 2 IN | bmAttributes3 | Transfer TypeInterrupt | Synch Type None | Usage Type Data | wMaxPacketSize 0x0010 1x 16 bytes | bInterval 8 Reviewed-by: Marek Vasut Reviewed-by: Neal Gompa Signed-off-by: Janne Grunau --- common/usb_kbd.c | 37 ++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/common/usb_kbd.c b/common/usb_kbd.c index 4cbc9acb73..b2361bbf18 100644 --- a/common/usb_kbd.c +++ b/common/usb_kbd.c @@ -23,6 +23,14 @@ #include +/* + * USB vendor and product IDs used for quirks. + */ +#define USB_VENDOR_ID_APPLE0x05ac +#define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_20210x029c +#define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_20210x029a +#define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021 0x029f + /* * If overwrite_console returns 1, the stdin, stderr and stdout * are switched to the serial port, else the settings in the @@ -106,6 +114,8 @@ struct usb_kbd_pdata { unsigned long last_report; struct int_queue *intq; + uint32_tifnum; + uint32_trepeat_delay; uint32_tusb_in_pointer; @@ -150,8 +160,8 @@ static void usb_kbd_put_queue(struct usb_kbd_pdata *data, u8 c) */ static void usb_kbd_setled(struct usb_device *dev) { - struct usb_interface *iface = >config.if_desc[0]; struct usb_kbd_pdata *data = dev->privptr; + struct usb_interface
[PATCH v4 3/6] usb: xhci: Abort transfers with unallocated rings
From: Janne Grunau Discovered while trying to use the second interface in the USB keyboard driver necessary on Apple USB keyboards. Reviewed-by: Marek Vasut Reviewed-by: Neal Gompa Signed-off-by: Janne Grunau --- drivers/usb/host/xhci-ring.c | 5 + 1 file changed, 5 insertions(+) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index b60661fe05..910c5f3352 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -685,6 +685,9 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe, reset_ep(udev, ep_index); ring = virt_dev->eps[ep_index].ring; + if (!ring) + return -EINVAL; + /* * How much data is (potentially) left before the 64KB boundary? * XHCI Spec puts restriction( TABLE 49 and 6.4.1 section of XHCI Spec) @@ -871,6 +874,8 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe, ep_index = usb_pipe_ep_index(pipe); ep_ring = virt_dev->eps[ep_index].ring; + if (!ep_ring) + return -EINVAL; /* * Check to see if the max packet size for the default control -- 2.44.0
[PATCH v4 6/6] usb: kbd: Add probe quirk for Apple and Keychron keyboards
From: Janne Grunau Those keyboards do not return the current device state. Polling will timeout unless there are key presses. This is not a problem during operation but the initial device state query during probing will fail. Skip this step in usb_kbd_probe_dev() to make these devices useable. Not all Apple keyboards behave like this. A keyboard with USB vendor/product ID 05ac:0221 is reported to work with the current code. Unfortunately some Keychron keyboards "re-use" Apple's vendor ID and show the same behavior (Keychron C2, 05ac:024f for example). Reviewed-by: Marek Vasut Reviewed-by: Neal Gompa Signed-off-by: Janne Grunau --- common/usb_kbd.c | 22 ++ 1 file changed, 22 insertions(+) diff --git a/common/usb_kbd.c b/common/usb_kbd.c index b2361bbf18..820f591fc5 100644 --- a/common/usb_kbd.c +++ b/common/usb_kbd.c @@ -31,6 +31,10 @@ #define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_20210x029a #define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021 0x029f +#define USB_VENDOR_ID_KEYCHRON 0x3434 + +#define USB_HID_QUIRK_POLL_NO_REPORT_IDLE BIT(0) + /* * If overwrite_console returns 1, the stdin, stderr and stdout * are switched to the serial port, else the settings in the @@ -474,6 +478,7 @@ static int usb_kbd_probe_dev(struct usb_device *dev, unsigned int ifnum) struct usb_interface *iface; struct usb_endpoint_descriptor *ep; struct usb_kbd_pdata *data; + unsigned int quirks = 0; int epNum; if (dev->descriptor.bNumConfigurations != 1) @@ -506,6 +511,15 @@ static int usb_kbd_probe_dev(struct usb_device *dev, unsigned int ifnum) debug("USB KBD: found interrupt EP: 0x%x\n", ep->bEndpointAddress); + switch (dev->descriptor.idVendor) { + case USB_VENDOR_ID_APPLE: + case USB_VENDOR_ID_KEYCHRON: + quirks |= USB_HID_QUIRK_POLL_NO_REPORT_IDLE; + break; + default: + break; + } + data = malloc(sizeof(struct usb_kbd_pdata)); if (!data) { printf("USB KBD: Error allocating private data\n"); @@ -546,6 +560,14 @@ static int usb_kbd_probe_dev(struct usb_device *dev, unsigned int ifnum) usb_set_idle(dev, iface->desc.bInterfaceNumber, 0, 0); #endif + /* +* Apple and Keychron keyboards do not report the device state. Reports +* are only returned during key presses. +*/ + if (quirks & USB_HID_QUIRK_POLL_NO_REPORT_IDLE) { + debug("USB KBD: quirk: skip testing device state\n"); + return 1; + } debug("USB KBD: enable interrupt pipe...\n"); #ifdef CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE data->intq = create_int_queue(dev, data->intpipe, 1, -- 2.44.0
[PATCH v3 0/6] USB keyboard improvements for asahi / desktop systems
Apple USB Keyboards from 2021 need quirks to be useable. The boot HID keyboard protocol is unfortunately not described in the first interface descriptor but the second. This needs several changes. The USB keyboard driver has to look at all (2) interface descriptors during probing. Since I didn't want to rebuild the USB driver probe code the Apple keyboards are bound to the keyboard driver via USB vendor and product IDs. To make the keyboards useable on Apple silicon devices the xhci driver needs to initializes rings for the endpoints of the first two interface descriptors. If this is causes concerns regarding regressions or memory use the USB_MAX_ACTIVE_INTERFACES define could be turned into a CONFIG option. Even after this changes the keyboards still do not probe successfully since they apparently do not behave HID standard compliant. They only generate reports on key events. This leads the final check whether the keyboard is operational to fail unless the user presses keys during the probe. Skip this check for known keyboards. Keychron seems to emulate Apple keyboards (some models even "re-use" Apple's USB vendor ID) so apply this quirk as well. Some devices like Yubikeys emulate a keyboard. since u-boot only binds a single keyboard block this kind of devices from the USB keyboard driver. Signed-off-by: Janne Grunau --- Changes in v3: - collected "Reviewed-by:" tags - rename usb_blocklist to usb_ignorelist - use BIT macro for USB KBD quirk bit - refactor usb_device_is_blocked() to use 0 / negated errors as return value, sed -e 's/block/ignore/', simplify it and add comments - rewritten usb_ignorelist documentation - Link to v2: https://lore.kernel.org/r/20240317-asahi-keyboards-v2-0-d3f4b8384...@jannau.net Changes in v2: - rewritten commit message for "[PATCH 2/6] usb: xhci: Set up endpoints for the first 2 interfaces" - Replaced the usb keyboard Yubikey block with an env based USB device blocklist - Use "-EINVAL" as return value in "[PATCH 3/6] usb: xhci: Abort transfers with unallocated rings" - added "Reviewed-by:" tags - Link to v1: https://lore.kernel.org/r/20240221-asahi-keyboards-v1-0-814b2e741...@jannau.net --- Janne Grunau (6): usb: xhci: refactor xhci_set_configuration usb: xhci: Set up endpoints for the first 2 interfaces usb: xhci: Abort transfers with unallocated rings usb: Add environment based device ignorelist usb: kbd: support Apple Magic Keyboards (2021) usb: kbd: Add probe quirk for Apple and Keychron keyboards common/usb.c | 57 common/usb_kbd.c | 59 ++-- doc/usage/environment.rst| 13 + drivers/usb/host/xhci-ring.c | 5 ++ drivers/usb/host/xhci.c | 126 +++ include/env_default.h| 11 include/usb.h| 6 +++ 7 files changed, 228 insertions(+), 49 deletions(-) --- base-commit: 37345abb97ef0dd9c50a03b2a72617612dcae585 change-id: 20240218-asahi-keyboards-f2ddaf0022b2 Best regards, -- Janne Grunau
[PATCH v3 1/6] usb: xhci: refactor xhci_set_configuration
From: Janne Grunau In the next step endpoints for multiple interfaces are set up. Move most of the per endpoint initialization to separate function to avoid another identation level. Reviewed-by: Marek Vasut Reviewed-by: Neal Gompa Signed-off-by: Janne Grunau --- drivers/usb/host/xhci.c | 119 +--- 1 file changed, 73 insertions(+), 46 deletions(-) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index d13cbff9b3..534c4b973f 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -475,67 +475,34 @@ static int xhci_configure_endpoints(struct usb_device *udev, bool ctx_change) } /** - * Configure the endpoint, programming the device contexts. + * Fill endpoint contexts for interface descriptor ifdesc. * - * @param udev pointer to the USB device structure - * Return: returns the status of the xhci_configure_endpoints + * @param udev pointer to the USB device structure + * @param ctrl pointer to the xhci pravte device structure + * @param virt_dev pointer to the xhci virtual device structure + * @param ifdesc pointer to the USB interface config descriptor + * Return: returns the status of xhci_init_ep_contexts_if */ -static int xhci_set_configuration(struct usb_device *udev) +static int xhci_init_ep_contexts_if(struct usb_device *udev, + struct xhci_ctrl *ctrl, + struct xhci_virt_device *virt_dev, + struct usb_interface *ifdesc + ) { - struct xhci_container_ctx *in_ctx; - struct xhci_container_ctx *out_ctx; - struct xhci_input_control_ctx *ctrl_ctx; - struct xhci_slot_ctx *slot_ctx; struct xhci_ep_ctx *ep_ctx[MAX_EP_CTX_NUM]; int cur_ep; - int max_ep_flag = 0; int ep_index; unsigned int dir; unsigned int ep_type; - struct xhci_ctrl *ctrl = xhci_get_ctrl(udev); - int num_of_ep; - int ep_flag = 0; u64 trb_64 = 0; - int slot_id = udev->slot_id; - struct xhci_virt_device *virt_dev = ctrl->devs[slot_id]; - struct usb_interface *ifdesc; u32 max_esit_payload; unsigned int interval; unsigned int mult; unsigned int max_burst; unsigned int avg_trb_len; unsigned int err_count = 0; + int num_of_ep = ifdesc->no_of_ep; - out_ctx = virt_dev->out_ctx; - in_ctx = virt_dev->in_ctx; - - num_of_ep = udev->config.if_desc[0].no_of_ep; - ifdesc = >config.if_desc[0]; - - ctrl_ctx = xhci_get_input_control_ctx(in_ctx); - /* Initialize the input context control */ - ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG); - ctrl_ctx->drop_flags = 0; - - /* EP_FLAG gives values 1 & 4 for EP1OUT and EP2IN */ - for (cur_ep = 0; cur_ep < num_of_ep; cur_ep++) { - ep_flag = xhci_get_ep_index(>ep_desc[cur_ep]); - ctrl_ctx->add_flags |= cpu_to_le32(1 << (ep_flag + 1)); - if (max_ep_flag < ep_flag) - max_ep_flag = ep_flag; - } - - xhci_inval_cache((uintptr_t)out_ctx->bytes, out_ctx->size); - - /* slot context */ - xhci_slot_copy(ctrl, in_ctx, out_ctx); - slot_ctx = xhci_get_slot_ctx(ctrl, in_ctx); - slot_ctx->dev_info &= ~(cpu_to_le32(LAST_CTX_MASK)); - slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(max_ep_flag + 1) | 0); - - xhci_endpoint_copy(ctrl, in_ctx, out_ctx, 0); - - /* filling up ep contexts */ for (cur_ep = 0; cur_ep < num_of_ep; cur_ep++) { struct usb_endpoint_descriptor *endpt_desc = NULL; struct usb_ss_ep_comp_descriptor *ss_ep_comp_desc = NULL; @@ -561,7 +528,8 @@ static int xhci_set_configuration(struct usb_device *udev) avg_trb_len = max_esit_payload; ep_index = xhci_get_ep_index(endpt_desc); - ep_ctx[ep_index] = xhci_get_ep_ctx(ctrl, in_ctx, ep_index); + ep_ctx[ep_index] = xhci_get_ep_ctx(ctrl, virt_dev->in_ctx, + ep_index); /* Allocate the ep rings */ virt_dev->eps[ep_index].ring = xhci_ring_alloc(ctrl, 1, true); @@ -614,6 +582,65 @@ static int xhci_set_configuration(struct usb_device *udev) } } + return 0; +} + +/** + * Configure the endpoint, programming the device contexts. + * + * @param udev pointer to the USB device structure + * Return: returns the status of the xhci_configure_endpoints + */ +static int xhci_set_configuration(struct usb_device *udev) +{ + struct xhci_container_ctx *out_ctx; + struct xhci_container_ctx *in_ctx; + struct xhci_input_control_ctx *ctrl_ctx; + struct xhci_slot_ctx *slot_ctx; + int err; + int cur_ep; + int max_ep_flag = 0; + struct xhci_ctrl *ctrl = xhci_get_ctrl(udev); + int
[PATCH v3 5/6] usb: kbd: support Apple Magic Keyboards (2021)
From: Janne Grunau Apple USB keyboards (Magic Keyboard from 2021 (product id 0x029c)) carry the HID keyboard boot protocol on the second interface descriptor. Probe via vendor and product IDs since the class/subclass/protocol match uses the first interface descriptor. Probe the two first interface descriptors for the HID keyboard boot protocol. USB configuration descriptor for reference: | Bus 003 Device 002: ID 05ac:029c Apple, Inc. Magic Keyboard | Device Descriptor: | bLength18 | bDescriptorType 1 | bcdUSB 2.00 | bDeviceClass0 [unknown] | bDeviceSubClass 0 [unknown] | bDeviceProtocol 0 | bMaxPacketSize064 | idVendor 0x05ac Apple, Inc. | idProduct 0x029c Magic Keyboard | bcdDevice3.90 | iManufacturer 1 Apple Inc. | iProduct2 Magic Keyboard | iSerial 3 ... | bNumConfigurations 1 | Configuration Descriptor: | bLength 9 | bDescriptorType 2 | wTotalLength 0x003b | bNumInterfaces 2 | bConfigurationValue 1 | iConfiguration 4 Keyboard | bmAttributes 0xa0 | (Bus Powered) | Remote Wakeup | MaxPower 500mA | Interface Descriptor: | bLength 9 | bDescriptorType 4 | bInterfaceNumber0 | bAlternateSetting 0 | bNumEndpoints 1 | bInterfaceClass 3 Human Interface Device | bInterfaceSubClass 0 [unknown] | bInterfaceProtocol 0 | iInterface 5 Device Management | HID Device Descriptor: | bLength 9 | bDescriptorType33 | bcdHID 1.10 | bCountryCode0 Not supported | bNumDescriptors 1 | bDescriptorType34 Report | wDescriptorLength 83 | Report Descriptors: | ** UNAVAILABLE ** | Endpoint Descriptor: | bLength 7 | bDescriptorType 5 | bEndpointAddress 0x81 EP 1 IN | bmAttributes3 | Transfer TypeInterrupt | Synch Type None | Usage Type Data | wMaxPacketSize 0x0010 1x 16 bytes | bInterval 8 | Interface Descriptor: | bLength 9 | bDescriptorType 4 | bInterfaceNumber1 | bAlternateSetting 0 | bNumEndpoints 1 | bInterfaceClass 3 Human Interface Device | bInterfaceSubClass 1 Boot Interface Subclass | bInterfaceProtocol 1 Keyboard | iInterface 6 Keyboard / Boot | HID Device Descriptor: | bLength 9 | bDescriptorType33 | bcdHID 1.10 | bCountryCode 13 International (ISO) | bNumDescriptors 1 | bDescriptorType34 Report | wDescriptorLength 207 | Report Descriptors: | ** UNAVAILABLE ** | Endpoint Descriptor: | bLength 7 | bDescriptorType 5 | bEndpointAddress 0x82 EP 2 IN | bmAttributes3 | Transfer TypeInterrupt | Synch Type None | Usage Type Data | wMaxPacketSize 0x0010 1x 16 bytes | bInterval 8 Reviewed-by: Marek Vasut Reviewed-by: Neal Gompa Signed-off-by: Janne Grunau --- common/usb_kbd.c | 37 ++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/common/usb_kbd.c b/common/usb_kbd.c index 4cbc9acb73..b2361bbf18 100644 --- a/common/usb_kbd.c +++ b/common/usb_kbd.c @@ -23,6 +23,14 @@ #include +/* + * USB vendor and product IDs used for quirks. + */ +#define USB_VENDOR_ID_APPLE0x05ac +#define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_20210x029c +#define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_20210x029a +#define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021 0x029f + /* * If overwrite_console returns 1, the stdin, stderr and stdout * are switched to the serial port, else the settings in the @@ -106,6 +114,8 @@ struct usb_kbd_pdata { unsigned long last_report; struct int_queue *intq; + uint32_tifnum; + uint32_trepeat_delay; uint32_tusb_in_pointer; @@ -150,8 +160,8 @@ static void usb_kbd_put_queue(struct usb_kbd_pdata *data, u8 c) */ static void usb_kbd_setled(struct usb_device *dev) { - struct usb_interface *iface = >config.if_desc[0]; struct usb_kbd_pdata *data = dev->privptr; + struct usb_interface
[PATCH v3 4/6] usb: Add environment based device ignorelist
From: Janne Grunau Add the environment variable "usb_ignorelist" to prevent USB devices listed in it from being bound to drivers. This allows to ignore devices which are undesirable or trigger bugs in u-boot's USB stack. Devices emulating keyboards are one example of undesirable devices as u-boot currently supports only a single USB keyboard device. Most commonly, people run into this with Yubikeys, so let's ignore those in the default environment. Based on previous USB keyboard specific patches for the same purpose. Link: https://lore.kernel.org/u-boot/7ab604fb-0fec-4f5e-8708-7a3a7e2cb...@denx.de/ Reviewed-by: Neal Gompa Signed-off-by: Janne Grunau --- common/usb.c | 57 +++ doc/usage/environment.rst | 13 +++ include/env_default.h | 11 + 3 files changed, 81 insertions(+) diff --git a/common/usb.c b/common/usb.c index 836506dcd9..1421b1bb13 100644 --- a/common/usb.c +++ b/common/usb.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -1084,6 +1085,48 @@ static int usb_prepare_device(struct usb_device *dev, int addr, bool do_read, return 0; } +static int usb_device_is_ignored(u16 id_vendor, u16 id_product) +{ + ulong vid, pid; + char *end; + const char *cur = env_get("usb_ignorelist"); + + /* parse "usb_ignorelist" strictly */ + while (cur && cur[0] != '\0') { + vid = simple_strtoul(cur, , 0); + /* +* If strtoul did not parse a single digit or the next char is +* not ':' the ignore list is malformed. +*/ + if (cur == end || end[0] != ':') + return -EINVAL; + + cur = end + 1; + pid = simple_strtoul(cur, , 0); + /* Consider '*' as wildcard for the product ID */ + if (cur == end && end[0] == '*') { + pid = U16_MAX + 1; + end++; + } + /* +* The ignore list is malformed if no product ID / wildcard was +* parsed or entries are not separated by ',' or terminated with +* '\0'. +*/ + if (cur == end || (end[0] != ',' && end[0] != '\0')) + return -EINVAL; + + if (id_vendor == vid && (pid > U16_MAX || id_product == pid)) + return -ENODEV; + + if (end[0] == '\0') + break; + cur = end + 1; + } + + return 0; +} + int usb_select_config(struct usb_device *dev) { unsigned char *tmpbuf = NULL; @@ -1099,6 +1142,20 @@ int usb_select_config(struct usb_device *dev) le16_to_cpus(>descriptor.idProduct); le16_to_cpus(>descriptor.bcdDevice); + /* ignore devices from usb_ignorelist */ + err = usb_device_is_ignored(dev->descriptor.idVendor, + dev->descriptor.idProduct); + if (err == -ENODEV) { + dev_dbg(dev->dev, "Ignoring USB device 0x%x:0x%x\n", + dev->descriptor.idVendor, dev->descriptor.idProduct); + return err; + } else if (err == -EINVAL) { + printf("usb_ignorelist parse error in \"%s\"\n", + env_get("usb_ignorelist")); + } else if (err < 0) { + return err; + } + /* * Kingston DT Ultimate 32GB USB 3.0 seems to be extremely sensitive * about this first Get Descriptor request. If there are any other diff --git a/doc/usage/environment.rst b/doc/usage/environment.rst index ebf75fa948..7d4b448cb3 100644 --- a/doc/usage/environment.rst +++ b/doc/usage/environment.rst @@ -366,6 +366,19 @@ tftpwindowsize This means the count of blocks we can receive before sending ack to server. +usb_ignorelist +Ignore USB devices to prevent binding them to an USB device driver. This can +be used to ignore devices are for some reason undesirable or causes crashes +u-boot's USB stack. +An example for undesired behavior is the keyboard emulation of security keys +like Yubikeys. U-boot currently supports only a single USB keyboard device +so try to probe an useful keyboard device. The default environment blocks +Yubico devices as common devices emulating keyboards. +Devices are matched by idVendor and idProduct. The variable contains a comma +separated list of idVendor:idProduct pairs as hexadecimal numbers joined +by a colon. '*' functions as a wildcard for idProduct to block all devices +with the specified idVendor. + vlan When set to a value < 4095 the traffic over Ethernet is encapsulated/received over 802.1q diff --git a/include/env_default.h b/include/env_default.h index 2ca4a087d3..8ee500d170 100644 --- a/include/env_default.h +++ b/include/env_default.h @@
[PATCH v3 2/6] usb: xhci: Set up endpoints for the first 2 interfaces
From: Janne Grunau The xhci driver currently only does the necessary initialization for endpoints found in the first interface descriptor. Apple USB keyboards (released 2021) use the second interface descriptor for the HID keyboard boot protocol. To allow USB drivers to use endpoints from other interface descriptors the xhci driver needs to ensure these endpoints are initialized as well. Use USB_MAX_ACTIVE_INTERFACES to control how many interface descriptors are considered during endpoint initialisation. For now define it to 2 as that is sufficient for supporting the Apple keyboards. Reviewed-by: Marek Vasut Reviewed-by: Neal Gompa Signed-off-by: Janne Grunau --- drivers/usb/host/xhci.c | 31 +++ include/usb.h | 6 ++ 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 534c4b973f..741e186ee0 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -606,24 +606,28 @@ static int xhci_set_configuration(struct usb_device *udev) int slot_id = udev->slot_id; struct xhci_virt_device *virt_dev = ctrl->devs[slot_id]; struct usb_interface *ifdesc; + unsigned int ifnum; + unsigned int max_ifnum = min((unsigned int)USB_MAX_ACTIVE_INTERFACES, +(unsigned int)udev->config.no_of_if); out_ctx = virt_dev->out_ctx; in_ctx = virt_dev->in_ctx; - num_of_ep = udev->config.if_desc[0].no_of_ep; - ifdesc = >config.if_desc[0]; - ctrl_ctx = xhci_get_input_control_ctx(in_ctx); /* Initialize the input context control */ ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG); ctrl_ctx->drop_flags = 0; - /* EP_FLAG gives values 1 & 4 for EP1OUT and EP2IN */ - for (cur_ep = 0; cur_ep < num_of_ep; cur_ep++) { - ep_flag = xhci_get_ep_index(>ep_desc[cur_ep]); - ctrl_ctx->add_flags |= cpu_to_le32(1 << (ep_flag + 1)); - if (max_ep_flag < ep_flag) - max_ep_flag = ep_flag; + for (ifnum = 0; ifnum < max_ifnum; ifnum++) { + ifdesc = >config.if_desc[ifnum]; + num_of_ep = ifdesc->no_of_ep; + /* EP_FLAG gives values 1 & 4 for EP1OUT and EP2IN */ + for (cur_ep = 0; cur_ep < num_of_ep; cur_ep++) { + ep_flag = xhci_get_ep_index(>ep_desc[cur_ep]); + ctrl_ctx->add_flags |= cpu_to_le32(1 << (ep_flag + 1)); + if (max_ep_flag < ep_flag) + max_ep_flag = ep_flag; + } } xhci_inval_cache((uintptr_t)out_ctx->bytes, out_ctx->size); @@ -637,9 +641,12 @@ static int xhci_set_configuration(struct usb_device *udev) xhci_endpoint_copy(ctrl, in_ctx, out_ctx, 0); /* filling up ep contexts */ - err = xhci_init_ep_contexts_if(udev, ctrl, virt_dev, ifdesc); - if (err < 0) - return err; + for (ifnum = 0; ifnum < max_ifnum; ifnum++) { + ifdesc = >config.if_desc[ifnum]; + err = xhci_init_ep_contexts_if(udev, ctrl, virt_dev, ifdesc); + if (err < 0) + return err; + } return xhci_configure_endpoints(udev, false); } diff --git a/include/usb.h b/include/usb.h index 09e3f0cb30..3aafdc8bfd 100644 --- a/include/usb.h +++ b/include/usb.h @@ -49,6 +49,12 @@ extern bool usb_started; /* flag for the started/stopped USB status */ */ #define USB_TIMEOUT_MS(pipe) (usb_pipebulk(pipe) ? 5000 : 1000) +/* + * The xhcd hcd driver prepares only a limited number interfaces / endpoints. + * Define this limit so that drivers do not exceed it. + */ +#define USB_MAX_ACTIVE_INTERFACES 2 + /* device request (setup) */ struct devrequest { __u8requesttype; -- 2.44.0
[PATCH v3 6/6] usb: kbd: Add probe quirk for Apple and Keychron keyboards
From: Janne Grunau Those keyboards do not return the current device state. Polling will timeout unless there are key presses. This is not a problem during operation but the initial device state query during probing will fail. Skip this step in usb_kbd_probe_dev() to make these devices useable. Not all Apple keyboards behave like this. A keyboard with USB vendor/product ID 05ac:0221 is reported to work with the current code. Unfortunately some Keychron keyboards "re-use" Apple's vendor ID and show the same behavior (Keychron C2, 05ac:024f for example). Reviewed-by: Marek Vasut Reviewed-by: Neal Gompa Signed-off-by: Janne Grunau --- common/usb_kbd.c | 22 ++ 1 file changed, 22 insertions(+) diff --git a/common/usb_kbd.c b/common/usb_kbd.c index b2361bbf18..820f591fc5 100644 --- a/common/usb_kbd.c +++ b/common/usb_kbd.c @@ -31,6 +31,10 @@ #define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_20210x029a #define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021 0x029f +#define USB_VENDOR_ID_KEYCHRON 0x3434 + +#define USB_HID_QUIRK_POLL_NO_REPORT_IDLE BIT(0) + /* * If overwrite_console returns 1, the stdin, stderr and stdout * are switched to the serial port, else the settings in the @@ -474,6 +478,7 @@ static int usb_kbd_probe_dev(struct usb_device *dev, unsigned int ifnum) struct usb_interface *iface; struct usb_endpoint_descriptor *ep; struct usb_kbd_pdata *data; + unsigned int quirks = 0; int epNum; if (dev->descriptor.bNumConfigurations != 1) @@ -506,6 +511,15 @@ static int usb_kbd_probe_dev(struct usb_device *dev, unsigned int ifnum) debug("USB KBD: found interrupt EP: 0x%x\n", ep->bEndpointAddress); + switch (dev->descriptor.idVendor) { + case USB_VENDOR_ID_APPLE: + case USB_VENDOR_ID_KEYCHRON: + quirks |= USB_HID_QUIRK_POLL_NO_REPORT_IDLE; + break; + default: + break; + } + data = malloc(sizeof(struct usb_kbd_pdata)); if (!data) { printf("USB KBD: Error allocating private data\n"); @@ -546,6 +560,14 @@ static int usb_kbd_probe_dev(struct usb_device *dev, unsigned int ifnum) usb_set_idle(dev, iface->desc.bInterfaceNumber, 0, 0); #endif + /* +* Apple and Keychron keyboards do not report the device state. Reports +* are only returned during key presses. +*/ + if (quirks & USB_HID_QUIRK_POLL_NO_REPORT_IDLE) { + debug("USB KBD: quirk: skip testing device state\n"); + return 1; + } debug("USB KBD: enable interrupt pipe...\n"); #ifdef CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE data->intq = create_int_queue(dev, data->intpipe, 1, -- 2.44.0
[PATCH v3 3/6] usb: xhci: Abort transfers with unallocated rings
From: Janne Grunau Discovered while trying to use the second interface in the USB keyboard driver necessary on Apple USB keyboards. Reviewed-by: Marek Vasut Reviewed-by: Neal Gompa Signed-off-by: Janne Grunau --- drivers/usb/host/xhci-ring.c | 5 + 1 file changed, 5 insertions(+) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index b60661fe05..910c5f3352 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -685,6 +685,9 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe, reset_ep(udev, ep_index); ring = virt_dev->eps[ep_index].ring; + if (!ring) + return -EINVAL; + /* * How much data is (potentially) left before the 64KB boundary? * XHCI Spec puts restriction( TABLE 49 and 6.4.1 section of XHCI Spec) @@ -871,6 +874,8 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe, ep_index = usb_pipe_ep_index(pipe); ep_ring = virt_dev->eps[ep_index].ring; + if (!ep_ring) + return -EINVAL; /* * Check to see if the max packet size for the default control -- 2.44.0
[PATCH 1/4] apple_m1_defconfig: Turn on CONFIG_SYS_64BIT_LBA
From: Hector Martin This makes USB HDDs >2TiB work. The only reason this hasn't bitten us for the internal NVMe yet is the 4K sector size, because the largest SSD Apple sells is 8TB and we can handle up to 16TiB with that sector size. Close call. Signed-off-by: Hector Martin Signed-off-by: Janne Grunau --- configs/apple_m1_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/apple_m1_defconfig b/configs/apple_m1_defconfig index e00d72e8be..31d966f0ab 100644 --- a/configs/apple_m1_defconfig +++ b/configs/apple_m1_defconfig @@ -10,6 +10,7 @@ CONFIG_SYS_PBSIZE=276 CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_BOARD_LATE_INIT=y # CONFIG_NET is not set +CONFIG_SYS_64BIT_LBA=y CONFIG_APPLE_SPI_KEYB=y # CONFIG_MMC is not set CONFIG_NVME_APPLE=y -- 2.44.0
[PATCH 3/4] configs: apple: Enable CMD_SELECT_FONT and FONT_16X32
From: Janne Grunau Apple devices have high DPI displays so the larger fonts are preferable for improved readability. This does not yet change the used font based on the display's pixel density so the standard 8x16 font is still used by default. Signed-off-by: Janne Grunau --- configs/apple_m1_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configs/apple_m1_defconfig b/configs/apple_m1_defconfig index 31d966f0ab..c30aec7c55 100644 --- a/configs/apple_m1_defconfig +++ b/configs/apple_m1_defconfig @@ -9,6 +9,7 @@ CONFIG_SYS_PBSIZE=276 # CONFIG_DISPLAY_CPUINFO is not set CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_BOARD_LATE_INIT=y +CONFIG_CMD_SELECT_FONT=y # CONFIG_NET is not set CONFIG_SYS_64BIT_LBA=y CONFIG_APPLE_SPI_KEYB=y @@ -19,6 +20,7 @@ CONFIG_USB_XHCI_DWC3=y CONFIG_USB_XHCI_PCI=y CONFIG_USB_DWC3=y CONFIG_USB_KEYBOARD=y +CONFIG_VIDEO_FONT_16X32=y CONFIG_SYS_WHITE_ON_BLACK=y CONFIG_NO_FB_CLEAR=y CONFIG_VIDEO_SIMPLE=y -- 2.44.0
[PATCH 2/4] configs: apple: Use "vidconsole,serial" as stdout/stderr
From: Janne Grunau The display size querying in efi_console relies on this order. The display should be the primary output device and should be used to display more than 80x25 chars. Signed-off-by: Janne Grunau --- include/configs/apple.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/configs/apple.h b/include/configs/apple.h index 0576bc04c9..a70440b3ad 100644 --- a/include/configs/apple.h +++ b/include/configs/apple.h @@ -6,8 +6,8 @@ /* Environment */ #define ENV_DEVICE_SETTINGS \ "stdin=serial,usbkbd,spikbd\0" \ - "stdout=serial,vidconsole\0" \ - "stderr=serial,vidconsole\0" + "stdout=vidconsole,serial\0" \ + "stderr=vidconsole,serial\0" #if IS_ENABLED(CONFIG_CMD_NVME) #define BOOT_TARGET_NVME(func) func(NVME, nvme, 0) -- 2.44.0
[PATCH 4/4] arm: apple: Switch to standard boot
From: Janne Grunau Use standard boot instead of the distro boot scripts. Signed-off-by: Janne Grunau --- arch/arm/Kconfig| 2 +- include/configs/apple.h | 20 ++-- 2 files changed, 3 insertions(+), 19 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 01d6556c42..ad89abde41 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1034,7 +1034,7 @@ config ARCH_APPLE select USB imply CMD_DM imply CMD_GPT - imply DISTRO_DEFAULTS + imply BOOTSTD_DEFAULTS imply OF_HAS_PRIOR_STAGE config ARCH_OWL diff --git a/include/configs/apple.h b/include/configs/apple.h index a70440b3ad..1e08b11448 100644 --- a/include/configs/apple.h +++ b/include/configs/apple.h @@ -9,26 +9,10 @@ "stdout=vidconsole,serial\0" \ "stderr=vidconsole,serial\0" -#if IS_ENABLED(CONFIG_CMD_NVME) - #define BOOT_TARGET_NVME(func) func(NVME, nvme, 0) -#else - #define BOOT_TARGET_NVME(func) -#endif - -#if IS_ENABLED(CONFIG_CMD_USB) - #define BOOT_TARGET_USB(func) func(USB, usb, 0) -#else - #define BOOT_TARGET_USB(func) -#endif - -#define BOOT_TARGET_DEVICES(func) \ - BOOT_TARGET_NVME(func) \ - BOOT_TARGET_USB(func) - -#include +#define BOOT_TARGETS "nvme usb" #define CFG_EXTRA_ENV_SETTINGS \ ENV_DEVICE_SETTINGS \ - BOOTENV + "boot_targets=" BOOT_TARGETS "\0" #endif -- 2.44.0
[PATCH 0/4] configs: apple: Switch to standard boot + small adjustments
This series contains a few misc config changes for Apple silicon systems: - switch from the deprecated distro boot scripts to standard boot - allows EFI console resizing based on the video console size - enables 16x32 bitmap fonts as Apple devices come with high DPI displays - enables 64-bit LBA addressing for USB storage devices larger than 2TB Signed-off-by: Janne Grunau --- Hector Martin (1): apple_m1_defconfig: Turn on CONFIG_SYS_64BIT_LBA Janne Grunau (3): configs: apple: Use "vidconsole,serial" as stdout/stderr configs: apple: Enable CMD_SELECT_FONT and FONT_16X32 arm: apple: Switch to standard boot arch/arm/Kconfig | 2 +- configs/apple_m1_defconfig | 3 +++ include/configs/apple.h| 24 3 files changed, 8 insertions(+), 21 deletions(-) --- base-commit: f3c979dd0053c082d2df170446923e7ce5edbc2d change-id: 20240317-apple_config-981fcd9028b9 Best regards, -- Janne Grunau
[PATCH v2 0/6] USB keyboard improvements for asahi / desktop systems
Apple USB Keyboards from 2021 need quirks to be useable. The boot HID keyboard protocol is unfortunately not described in the first interface descriptor but the second. This needs several changes. The USB keyboard driver has to look at all (2) interface descriptors during probing. Since I didn't want to rebuild the USB driver probe code the Apple keyboards are bound to the keyboard driver via USB vendor and product IDs. To make the keyboards useable on Apple silicon devices the xhci driver needs to initializes rings for the endpoints of the first two interface descriptors. If this is causes concerns regarding regressions or memory use the USB_MAX_ACTIVE_INTERFACES define could be turned into a CONFIG option. Even after this changes the keyboards still do not probe successfully since they apparently do not behave HID standard compliant. They only generate reports on key events. This leads the final check whether the keyboard is operational to fail unless the user presses keys during the probe. Skip this check for known keyboards. Keychron seems to emulate Apple keyboards (some models even "re-use" Apple's USB vendor ID) so apply this quirk as well. Some devices like Yubikeys emulate a keyboard. since u-boot only binds a single keyboard block this kind of devices from the USB keyboard driver. Signed-off-by: Janne Grunau --- Changes in v2: - rewritten commit message for "[PATCH 2/6] usb: xhci: Set up endpoints for the first 2 interfaces" - Replaced the usb keyboard Yubikey block with an env based USB device blocklist - Use "-EINVAL" as return value in "[PATCH 3/6] usb: xhci: Abort transfers with unallocated rings" - added "Reviewed-by:" tags - Link to v1: https://lore.kernel.org/r/20240221-asahi-keyboards-v1-0-814b2e741...@jannau.net --- Janne Grunau (6): usb: xhci: refactor xhci_set_configuration usb: xhci: Set up endpoints for the first 2 interfaces usb: xhci: Abort transfers with unallocated rings usb: Add environment based device blocklist usb: kbd: support Apple Magic Keyboards (2021) usb: kbd: Add probe quirk for Apple and Keychron keyboards common/usb.c | 56 +++ common/usb_kbd.c | 61 +++-- doc/usage/environment.rst| 12 + drivers/usb/host/xhci-ring.c | 5 ++ drivers/usb/host/xhci.c | 126 +++ include/env_default.h| 11 include/usb.h| 6 +++ 7 files changed, 227 insertions(+), 50 deletions(-) --- base-commit: 37345abb97ef0dd9c50a03b2a72617612dcae585 change-id: 20240218-asahi-keyboards-f2ddaf0022b2 Best regards, -- Janne Grunau
[PATCH v2 5/6] usb: kbd: support Apple Magic Keyboards (2021)
From: Janne Grunau Apple USB keyboards (Magic Keyboard from 2021 (product id 0x029c)) carry the HID keyboard boot protocol on the second interface descriptor. Probe via vendor and product IDs since the class/subclass/protocol match uses the first interface descriptor. Probe the two first interface descriptors for the HID keyboard boot protocol. USB configuration descriptor for reference: | Bus 003 Device 002: ID 05ac:029c Apple, Inc. Magic Keyboard | Device Descriptor: | bLength18 | bDescriptorType 1 | bcdUSB 2.00 | bDeviceClass0 [unknown] | bDeviceSubClass 0 [unknown] | bDeviceProtocol 0 | bMaxPacketSize064 | idVendor 0x05ac Apple, Inc. | idProduct 0x029c Magic Keyboard | bcdDevice3.90 | iManufacturer 1 Apple Inc. | iProduct2 Magic Keyboard | iSerial 3 ... | bNumConfigurations 1 | Configuration Descriptor: | bLength 9 | bDescriptorType 2 | wTotalLength 0x003b | bNumInterfaces 2 | bConfigurationValue 1 | iConfiguration 4 Keyboard | bmAttributes 0xa0 | (Bus Powered) | Remote Wakeup | MaxPower 500mA | Interface Descriptor: | bLength 9 | bDescriptorType 4 | bInterfaceNumber0 | bAlternateSetting 0 | bNumEndpoints 1 | bInterfaceClass 3 Human Interface Device | bInterfaceSubClass 0 [unknown] | bInterfaceProtocol 0 | iInterface 5 Device Management | HID Device Descriptor: | bLength 9 | bDescriptorType33 | bcdHID 1.10 | bCountryCode0 Not supported | bNumDescriptors 1 | bDescriptorType34 Report | wDescriptorLength 83 | Report Descriptors: | ** UNAVAILABLE ** | Endpoint Descriptor: | bLength 7 | bDescriptorType 5 | bEndpointAddress 0x81 EP 1 IN | bmAttributes3 | Transfer TypeInterrupt | Synch Type None | Usage Type Data | wMaxPacketSize 0x0010 1x 16 bytes | bInterval 8 | Interface Descriptor: | bLength 9 | bDescriptorType 4 | bInterfaceNumber1 | bAlternateSetting 0 | bNumEndpoints 1 | bInterfaceClass 3 Human Interface Device | bInterfaceSubClass 1 Boot Interface Subclass | bInterfaceProtocol 1 Keyboard | iInterface 6 Keyboard / Boot | HID Device Descriptor: | bLength 9 | bDescriptorType33 | bcdHID 1.10 | bCountryCode 13 International (ISO) | bNumDescriptors 1 | bDescriptorType34 Report | wDescriptorLength 207 | Report Descriptors: | ** UNAVAILABLE ** | Endpoint Descriptor: | bLength 7 | bDescriptorType 5 | bEndpointAddress 0x82 EP 2 IN | bmAttributes3 | Transfer TypeInterrupt | Synch Type None | Usage Type Data | wMaxPacketSize 0x0010 1x 16 bytes | bInterval 8 Signed-off-by: Janne Grunau --- common/usb_kbd.c | 39 +++ 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/common/usb_kbd.c b/common/usb_kbd.c index 4cbc9acb73..8cc3345075 100644 --- a/common/usb_kbd.c +++ b/common/usb_kbd.c @@ -23,6 +23,14 @@ #include +/* + * USB vendor and product IDs used for quirks. + */ +#define USB_VENDOR_ID_APPLE0x05ac +#define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_20210x029c +#define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_20210x029a +#define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021 0x029f + /* * If overwrite_console returns 1, the stdin, stderr and stdout * are switched to the serial port, else the settings in the @@ -106,6 +114,8 @@ struct usb_kbd_pdata { unsigned long last_report; struct int_queue *intq; + uint32_tifnum; + uint32_trepeat_delay; uint32_tusb_in_pointer; @@ -150,8 +160,8 @@ static void usb_kbd_put_queue(struct usb_kbd_pdata *data, u8 c) */ static void usb_kbd_setled(struct usb_device *dev) { - struct usb_interface *iface = >config.if_desc[0]; struct usb_kbd_pdata *data = dev->privptr; + struct usb_interface *iface = >config.if_desc[data->ifnum];
[PATCH v2 1/6] usb: xhci: refactor xhci_set_configuration
From: Janne Grunau In the next step endpoints for multiple interfaces are set up. Move most of the per endpoint initialization to separate function to avoid another identation level. Reviewed-by: Marek Vasut Signed-off-by: Janne Grunau --- drivers/usb/host/xhci.c | 119 +--- 1 file changed, 73 insertions(+), 46 deletions(-) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index d13cbff9b3..534c4b973f 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -475,67 +475,34 @@ static int xhci_configure_endpoints(struct usb_device *udev, bool ctx_change) } /** - * Configure the endpoint, programming the device contexts. + * Fill endpoint contexts for interface descriptor ifdesc. * - * @param udev pointer to the USB device structure - * Return: returns the status of the xhci_configure_endpoints + * @param udev pointer to the USB device structure + * @param ctrl pointer to the xhci pravte device structure + * @param virt_dev pointer to the xhci virtual device structure + * @param ifdesc pointer to the USB interface config descriptor + * Return: returns the status of xhci_init_ep_contexts_if */ -static int xhci_set_configuration(struct usb_device *udev) +static int xhci_init_ep_contexts_if(struct usb_device *udev, + struct xhci_ctrl *ctrl, + struct xhci_virt_device *virt_dev, + struct usb_interface *ifdesc + ) { - struct xhci_container_ctx *in_ctx; - struct xhci_container_ctx *out_ctx; - struct xhci_input_control_ctx *ctrl_ctx; - struct xhci_slot_ctx *slot_ctx; struct xhci_ep_ctx *ep_ctx[MAX_EP_CTX_NUM]; int cur_ep; - int max_ep_flag = 0; int ep_index; unsigned int dir; unsigned int ep_type; - struct xhci_ctrl *ctrl = xhci_get_ctrl(udev); - int num_of_ep; - int ep_flag = 0; u64 trb_64 = 0; - int slot_id = udev->slot_id; - struct xhci_virt_device *virt_dev = ctrl->devs[slot_id]; - struct usb_interface *ifdesc; u32 max_esit_payload; unsigned int interval; unsigned int mult; unsigned int max_burst; unsigned int avg_trb_len; unsigned int err_count = 0; + int num_of_ep = ifdesc->no_of_ep; - out_ctx = virt_dev->out_ctx; - in_ctx = virt_dev->in_ctx; - - num_of_ep = udev->config.if_desc[0].no_of_ep; - ifdesc = >config.if_desc[0]; - - ctrl_ctx = xhci_get_input_control_ctx(in_ctx); - /* Initialize the input context control */ - ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG); - ctrl_ctx->drop_flags = 0; - - /* EP_FLAG gives values 1 & 4 for EP1OUT and EP2IN */ - for (cur_ep = 0; cur_ep < num_of_ep; cur_ep++) { - ep_flag = xhci_get_ep_index(>ep_desc[cur_ep]); - ctrl_ctx->add_flags |= cpu_to_le32(1 << (ep_flag + 1)); - if (max_ep_flag < ep_flag) - max_ep_flag = ep_flag; - } - - xhci_inval_cache((uintptr_t)out_ctx->bytes, out_ctx->size); - - /* slot context */ - xhci_slot_copy(ctrl, in_ctx, out_ctx); - slot_ctx = xhci_get_slot_ctx(ctrl, in_ctx); - slot_ctx->dev_info &= ~(cpu_to_le32(LAST_CTX_MASK)); - slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(max_ep_flag + 1) | 0); - - xhci_endpoint_copy(ctrl, in_ctx, out_ctx, 0); - - /* filling up ep contexts */ for (cur_ep = 0; cur_ep < num_of_ep; cur_ep++) { struct usb_endpoint_descriptor *endpt_desc = NULL; struct usb_ss_ep_comp_descriptor *ss_ep_comp_desc = NULL; @@ -561,7 +528,8 @@ static int xhci_set_configuration(struct usb_device *udev) avg_trb_len = max_esit_payload; ep_index = xhci_get_ep_index(endpt_desc); - ep_ctx[ep_index] = xhci_get_ep_ctx(ctrl, in_ctx, ep_index); + ep_ctx[ep_index] = xhci_get_ep_ctx(ctrl, virt_dev->in_ctx, + ep_index); /* Allocate the ep rings */ virt_dev->eps[ep_index].ring = xhci_ring_alloc(ctrl, 1, true); @@ -614,6 +582,65 @@ static int xhci_set_configuration(struct usb_device *udev) } } + return 0; +} + +/** + * Configure the endpoint, programming the device contexts. + * + * @param udev pointer to the USB device structure + * Return: returns the status of the xhci_configure_endpoints + */ +static int xhci_set_configuration(struct usb_device *udev) +{ + struct xhci_container_ctx *out_ctx; + struct xhci_container_ctx *in_ctx; + struct xhci_input_control_ctx *ctrl_ctx; + struct xhci_slot_ctx *slot_ctx; + int err; + int cur_ep; + int max_ep_flag = 0; + struct xhci_ctrl *ctrl = xhci_get_ctrl(udev); + int num_of_ep; + int ep_flag
[PATCH v2 6/6] usb: kbd: Add probe quirk for Apple and Keychron keyboards
From: Janne Grunau Those keyboards do not return the current device state. Polling will timeout unless there are key presses. This is not a problem during operation but the inital device state query during probing will fail. Skip this step in usb_kbd_probe_dev() to make these devices useable. Not all Apple keyboards behave like this. A keyboard with USB vendor/product ID 05ac:0221 is reported to work with the current code. Unfortunately some Keychron keyboards "re-use" Apple's vendor ID and show the same behavior (Keychron C2, 05ac:024f for example). Reviewed-by: Marek Vasut Signed-off-by: Janne Grunau --- common/usb_kbd.c | 22 ++ 1 file changed, 22 insertions(+) diff --git a/common/usb_kbd.c b/common/usb_kbd.c index 8cc3345075..43c7668671 100644 --- a/common/usb_kbd.c +++ b/common/usb_kbd.c @@ -31,6 +31,10 @@ #define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_20210x029a #define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021 0x029f +#define USB_VENDOR_ID_KEYCHRON 0x3434 + +#define USB_HID_QUIRK_POLL_NO_REPORT_IDLE (1 << 0) + /* * If overwrite_console returns 1, the stdin, stderr and stdout * are switched to the serial port, else the settings in the @@ -474,6 +478,7 @@ static int usb_kbd_probe_dev(struct usb_device *dev, unsigned int ifnum) struct usb_interface *iface; struct usb_endpoint_descriptor *ep; struct usb_kbd_pdata *data; + unsigned int quirks = 0; int epNum; if (dev->descriptor.bNumConfigurations != 1) @@ -506,6 +511,15 @@ static int usb_kbd_probe_dev(struct usb_device *dev, unsigned int ifnum) debug("USB KBD: found interrupt EP: 0x%x\n", ep->bEndpointAddress); + switch (dev->descriptor.idVendor) { + case USB_VENDOR_ID_APPLE: + case USB_VENDOR_ID_KEYCHRON: + quirks |= USB_HID_QUIRK_POLL_NO_REPORT_IDLE; + break; + default: + break; + } + data = malloc(sizeof(struct usb_kbd_pdata)); if (!data) { printf("USB KBD: Error allocating private data\n"); @@ -546,6 +560,14 @@ static int usb_kbd_probe_dev(struct usb_device *dev, unsigned int ifnum) usb_set_idle(dev, iface->desc.bInterfaceNumber, 0, 0); #endif + /* +* Apple and Keychron keyboards do not report the device state. Reports +* are only returned during key presses. +*/ + if (quirks & USB_HID_QUIRK_POLL_NO_REPORT_IDLE) { + debug("USB KBD: quirk: skip testing device state\n"); + return 1; + } debug("USB KBD: enable interrupt pipe...\n"); #ifdef CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE data->intq = create_int_queue(dev, data->intpipe, 1, -- 2.44.0
[PATCH v2 2/6] usb: xhci: Set up endpoints for the first 2 interfaces
From: Janne Grunau The xhci driver currently only does the necessary initialization for endpoints found in the first interface descriptor. Apple USB keyboards (released 2021) use the second interface descriptor for the HID keyboard boot protocol. To allow USB drivers to use endpoints from other interface descriptors the xhci driver needs to ensure these endpoints are initialized as well. Use USB_MAX_ACTIVE_INTERFACES to control how many interface descriptors are considered during endpoint initialisation. For now define it to 2 as that is sufficient for supporting the Apple keyboards. Reviewed-by: Marek Vasut Signed-off-by: Janne Grunau --- drivers/usb/host/xhci.c | 31 +++ include/usb.h | 6 ++ 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 534c4b973f..741e186ee0 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -606,24 +606,28 @@ static int xhci_set_configuration(struct usb_device *udev) int slot_id = udev->slot_id; struct xhci_virt_device *virt_dev = ctrl->devs[slot_id]; struct usb_interface *ifdesc; + unsigned int ifnum; + unsigned int max_ifnum = min((unsigned int)USB_MAX_ACTIVE_INTERFACES, +(unsigned int)udev->config.no_of_if); out_ctx = virt_dev->out_ctx; in_ctx = virt_dev->in_ctx; - num_of_ep = udev->config.if_desc[0].no_of_ep; - ifdesc = >config.if_desc[0]; - ctrl_ctx = xhci_get_input_control_ctx(in_ctx); /* Initialize the input context control */ ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG); ctrl_ctx->drop_flags = 0; - /* EP_FLAG gives values 1 & 4 for EP1OUT and EP2IN */ - for (cur_ep = 0; cur_ep < num_of_ep; cur_ep++) { - ep_flag = xhci_get_ep_index(>ep_desc[cur_ep]); - ctrl_ctx->add_flags |= cpu_to_le32(1 << (ep_flag + 1)); - if (max_ep_flag < ep_flag) - max_ep_flag = ep_flag; + for (ifnum = 0; ifnum < max_ifnum; ifnum++) { + ifdesc = >config.if_desc[ifnum]; + num_of_ep = ifdesc->no_of_ep; + /* EP_FLAG gives values 1 & 4 for EP1OUT and EP2IN */ + for (cur_ep = 0; cur_ep < num_of_ep; cur_ep++) { + ep_flag = xhci_get_ep_index(>ep_desc[cur_ep]); + ctrl_ctx->add_flags |= cpu_to_le32(1 << (ep_flag + 1)); + if (max_ep_flag < ep_flag) + max_ep_flag = ep_flag; + } } xhci_inval_cache((uintptr_t)out_ctx->bytes, out_ctx->size); @@ -637,9 +641,12 @@ static int xhci_set_configuration(struct usb_device *udev) xhci_endpoint_copy(ctrl, in_ctx, out_ctx, 0); /* filling up ep contexts */ - err = xhci_init_ep_contexts_if(udev, ctrl, virt_dev, ifdesc); - if (err < 0) - return err; + for (ifnum = 0; ifnum < max_ifnum; ifnum++) { + ifdesc = >config.if_desc[ifnum]; + err = xhci_init_ep_contexts_if(udev, ctrl, virt_dev, ifdesc); + if (err < 0) + return err; + } return xhci_configure_endpoints(udev, false); } diff --git a/include/usb.h b/include/usb.h index 09e3f0cb30..3aafdc8bfd 100644 --- a/include/usb.h +++ b/include/usb.h @@ -49,6 +49,12 @@ extern bool usb_started; /* flag for the started/stopped USB status */ */ #define USB_TIMEOUT_MS(pipe) (usb_pipebulk(pipe) ? 5000 : 1000) +/* + * The xhcd hcd driver prepares only a limited number interfaces / endpoints. + * Define this limit so that drivers do not exceed it. + */ +#define USB_MAX_ACTIVE_INTERFACES 2 + /* device request (setup) */ struct devrequest { __u8requesttype; -- 2.44.0
[PATCH v2 4/6] usb: Add environment based device blocklist
From: Janne Grunau Add the environment variable "usb_blocklist" to prevent USB devices listed in it from being used. This allows to ignore devices which trigger bugs in u-boot's USB stack or are undesirable for other reasons. Devices emulating keyboards are one example. U-boot currently supports only one USB keyboard device. Most commonly, people run into this with Yubikeys, so let's ignore those in the default environment. Based on previous USB keyboard specific patches for the same purpose. Link: https://lore.kernel.org/u-boot/7ab604fb-0fec-4f5e-8708-7a3a7e2cb...@denx.de/ Signed-off-by: Janne Grunau --- common/usb.c | 56 +++ doc/usage/environment.rst | 12 ++ include/env_default.h | 11 ++ 3 files changed, 79 insertions(+) diff --git a/common/usb.c b/common/usb.c index 836506dcd9..73af5be066 100644 --- a/common/usb.c +++ b/common/usb.c @@ -1084,6 +1084,57 @@ static int usb_prepare_device(struct usb_device *dev, int addr, bool do_read, return 0; } +static int usb_blocklist_parse_error(const char *blocklist, size_t pos) +{ + printf("usb_blocklist parse error at char %zu in \"%s\"\n", pos, + blocklist); + return 0; +} + +static int usb_device_is_blocked(u16 id_vendor, u16 id_product) +{ + ulong vid, pid; + char *end; + const char *block_str = env_get("usb_blocklist"); + const char *cur = block_str; + + /* parse "usb_blocklist" strictly */ + while (cur && cur[0] != '\0') { + vid = simple_strtoul(cur, , 0); + if (cur == end || end[0] != ':') + return usb_blocklist_parse_error(block_str, +cur - block_str); + + cur = end + 1; + pid = simple_strtoul(cur, , 0); + if (cur == end && end[0] != '*') + return usb_blocklist_parse_error(block_str, +cur - block_str); + + if (end[0] == '*') { + /* use out of range idProduct as wildcard indication */ + pid = U16_MAX + 1; + end++; + } + if (end[0] != ',' && end[0] != '\0') + return usb_blocklist_parse_error(block_str, +cur - block_str); + + if (id_vendor == vid && (pid > U16_MAX || id_product == pid)) { + printf("Ignoring USB device 0x%x:0x%x\n",id_vendor, + id_product); + debug("Ignoring USB device 0x%x:0x%x\n",id_vendor, + id_product); + return 1; + } + if (end[0] == '\0') + break; + cur = end + 1; + } + + return 0; +} + int usb_select_config(struct usb_device *dev) { unsigned char *tmpbuf = NULL; @@ -1099,6 +1150,11 @@ int usb_select_config(struct usb_device *dev) le16_to_cpus(>descriptor.idProduct); le16_to_cpus(>descriptor.bcdDevice); + /* ignore devices from usb_blocklist */ + if (usb_device_is_blocked(dev->descriptor.idVendor, + dev->descriptor.idProduct)) + return -ENODEV; + /* * Kingston DT Ultimate 32GB USB 3.0 seems to be extremely sensitive * about this first Get Descriptor request. If there are any other diff --git a/doc/usage/environment.rst b/doc/usage/environment.rst index ebf75fa948..e42702adb2 100644 --- a/doc/usage/environment.rst +++ b/doc/usage/environment.rst @@ -366,6 +366,18 @@ tftpwindowsize This means the count of blocks we can receive before sending ack to server. +usb_blocklist +Block USB devices from being bound to an USB device driver. This can be used +to ignore devices which causes crashes in u-boot's USB stack or are +undesirable for other reasons. +The default environment blocks Yubico devices since they emulate USB +keyboards. U-boot currently supports only a single USB keyboard device and +it is undesirable that a Yubikey is used as keyboard. +Devices are matched by idVendor and idProduct. The variable contains a comma +separated list of idVendor:idProduct pairs as hexadecimal numbers joined +by a colon. '*' functions as a wildcard for idProduct to block all devices +with the specified idVendor. + vlan When set to a value < 4095 the traffic over Ethernet is encapsulated/received over 802.1q diff --git a/include/env_default.h b/include/env_default.h index 2ca4a087d3..ba4c7516b4 100644 --- a/include/env_default.h +++ b/include/env_default.h @@ -99,6 +99,17 @@ const char default_environment[] = { #ifdef CONFIG_SYS_SOC "soc=" CONFIG_SYS_SOC "\0" #endif +#ifdef
[PATCH v2 3/6] usb: xhci: Abort transfers with unallocated rings
From: Janne Grunau Discovered while trying to use the second interface in the USB keyboard driver necessary on Apple USB keyboards. Signed-off-by: Janne Grunau --- drivers/usb/host/xhci-ring.c | 5 + 1 file changed, 5 insertions(+) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index b60661fe05..910c5f3352 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -685,6 +685,9 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe, reset_ep(udev, ep_index); ring = virt_dev->eps[ep_index].ring; + if (!ring) + return -EINVAL; + /* * How much data is (potentially) left before the 64KB boundary? * XHCI Spec puts restriction( TABLE 49 and 6.4.1 section of XHCI Spec) @@ -871,6 +874,8 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe, ep_index = usb_pipe_ep_index(pipe); ep_ring = virt_dev->eps[ep_index].ring; + if (!ep_ring) + return -EINVAL; /* * Check to see if the max packet size for the default control -- 2.44.0
[PATCH v3 7/7] efi_selftest: Update StrToFat() unit test after CP473 map extension
From: Janne Grunau Test that Unicode code points which map to CP437 code points 1-31 are converted to '_'. This ensures no FAT file names do not contain chars which are control characters in other code pages (CP 1250 for example). Signed-off-by: Janne Grunau --- lib/efi_selftest/efi_selftest_unicode_collation.c | 12 1 file changed, 12 insertions(+) diff --git a/lib/efi_selftest/efi_selftest_unicode_collation.c b/lib/efi_selftest/efi_selftest_unicode_collation.c index 32c99caf35..ad7dfa9fb9 100644 --- a/lib/efi_selftest/efi_selftest_unicode_collation.c +++ b/lib/efi_selftest/efi_selftest_unicode_collation.c @@ -220,6 +220,18 @@ static int test_str_to_fat(void) return EFI_ST_FAILURE; } + /* +* Test unicode code points which map to CP 437 0x01 - 0x1f are +* converted to '_'. +*/ + boottime->set_mem(fat, 16, 0); + ret = unicode_collation_protocol->str_to_fat(unicode_collation_protocol, + u"\u263a\u2666\u2022\u25d8\u2642\u2194\u00b6\u203c", 8, fat); + if (!ret || efi_st_strcmp_16_8(u"", fat)) { + efi_st_error("str_to_fat returned %u, \"%s\"\n", ret, fat); + return EFI_ST_FAILURE; + } + return EFI_ST_SUCCESS; } -- 2.44.0
[PATCH v3 2/7] video: console: Parse UTF-8 character sequences
From: Janne Grunau efi_console / UEFI applications (grub2, sd-boot, ...) pass UTF-8 character sequences to vidconsole which results in wrong glyphs for code points outside of ASCII. The truetype console expects Unicode code points and bitmap font based consoles expect code page 437 code points. To support both convert UTF-8 to UTF-32 and pass Unicode code points in vidconsole_ops.putc_xy(). These can be used directly in console_truetype and after conversion to code page 437 in console_{normal,rotate}. This fixes rendering of international, symbol and box drawing characters used by UEFI applications. Signed-off-by: Janne Grunau --- drivers/video/console_normal.c | 6 -- drivers/video/console_rotate.c | 16 ++-- drivers/video/console_truetype.c| 8 drivers/video/vidconsole-uclass.c | 18 +- drivers/video/vidconsole_internal.h | 19 +++ include/video_console.h | 10 ++ 6 files changed, 56 insertions(+), 21 deletions(-) diff --git a/drivers/video/console_normal.c b/drivers/video/console_normal.c index a0231293f3..34ef5a5229 100644 --- a/drivers/video/console_normal.c +++ b/drivers/video/console_normal.c @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -63,7 +64,7 @@ static int console_move_rows(struct udevice *dev, uint rowdst, return 0; } -static int console_putc_xy(struct udevice *dev, uint x_frac, uint y, char ch) +static int console_putc_xy(struct udevice *dev, uint x_frac, uint y, int cp) { struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev); struct udevice *vid = dev->parent; @@ -73,8 +74,9 @@ static int console_putc_xy(struct udevice *dev, uint x_frac, uint y, char ch) int pbytes = VNBYTES(vid_priv->bpix); int x, linenum, ret; void *start, *line; + u8 ch = console_utf_to_cp437(cp); uchar *pfont = fontdata->video_fontdata + - (u8)ch * fontdata->char_pixel_bytes; + ch * fontdata->char_pixel_bytes; if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac) return -EAGAIN; diff --git a/drivers/video/console_rotate.c b/drivers/video/console_rotate.c index 65358a1c6e..e4303dfb36 100644 --- a/drivers/video/console_rotate.c +++ b/drivers/video/console_rotate.c @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -67,7 +68,7 @@ static int console_move_rows_1(struct udevice *dev, uint rowdst, uint rowsrc, return 0; } -static int console_putc_xy_1(struct udevice *dev, uint x_frac, uint y, char ch) +static int console_putc_xy_1(struct udevice *dev, uint x_frac, uint y, int cp) { struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev); struct udevice *vid = dev->parent; @@ -77,8 +78,9 @@ static int console_putc_xy_1(struct udevice *dev, uint x_frac, uint y, char ch) int pbytes = VNBYTES(vid_priv->bpix); int x, linenum, ret; void *start, *line; + u8 ch = console_utf_to_cp437(cp); uchar *pfont = fontdata->video_fontdata + - (u8)ch * fontdata->char_pixel_bytes; + ch * fontdata->char_pixel_bytes; if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac) return -EAGAIN; @@ -145,7 +147,7 @@ static int console_move_rows_2(struct udevice *dev, uint rowdst, uint rowsrc, return 0; } -static int console_putc_xy_2(struct udevice *dev, uint x_frac, uint y, char ch) +static int console_putc_xy_2(struct udevice *dev, uint x_frac, uint y, int cp) { struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev); struct udevice *vid = dev->parent; @@ -155,8 +157,9 @@ static int console_putc_xy_2(struct udevice *dev, uint x_frac, uint y, char ch) int pbytes = VNBYTES(vid_priv->bpix); int linenum, x, ret; void *start, *line; + u8 ch = console_utf_to_cp437(cp); uchar *pfont = fontdata->video_fontdata + - (u8)ch * fontdata->char_pixel_bytes; + ch * fontdata->char_pixel_bytes; if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac) return -EAGAIN; @@ -227,7 +230,7 @@ static int console_move_rows_3(struct udevice *dev, uint rowdst, uint rowsrc, return 0; } -static int console_putc_xy_3(struct udevice *dev, uint x_frac, uint y, char ch) +static int console_putc_xy_3(struct udevice *dev, uint x_frac, uint y, int cp) { struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev); struct udevice *vid = dev->parent; @@ -237,8 +240,9 @@ static int console_putc_xy_3(struct udevice *dev, uint x_frac, uint y, char ch) int pbytes = VNBYTES(vid_priv->bpix); int linenum, x, ret; void *start, *line; + u8 ch = console_utf_to_cp437(cp); uchar *pfont = fontdata->video_fontdata + -
[PATCH v3 1/7] lib: charset: Fix and extend utf8_to_utf32_stream() documentation
From: Janne Grunau Suggested-by: Heinrich Schuchardt Reviewed-by: Heinrich Schuchardt Signed-off-by: Janne Grunau --- include/charset.h | 14 -- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/include/charset.h b/include/charset.h index 44034c71d3..f1050c903d 100644 --- a/include/charset.h +++ b/include/charset.h @@ -324,11 +324,21 @@ int utf_to_cp(s32 *c, const u16 *codepage); int utf8_to_cp437_stream(u8 c, char *buffer); /** - * utf8_to_utf32_stream() - convert UTF-8 stream to UTF-32 + * utf8_to_utf32_stream() - convert UTF-8 byte stream to Unicode code points + * + * The function is called for each byte @c in a UTF-8 stream. The byte is + * appended to the temporary storage @buffer until the UTF-8 stream in + * @buffer describes a Unicode code point. + * + * When a new code point has been decoded it is returned and buffer[0] is + * set to '\0', otherwise the return value is 0. + * + * The buffer must be at least 5 characters long. Before the first function + * invocation buffer[0] must be set to '\0'." * * @c: next UTF-8 character to convert * @buffer:buffer, at least 5 characters - * Return: next codepage 437 character or 0 + * Return: Unicode code point or 0 */ int utf8_to_utf32_stream(u8 c, char *buffer); -- 2.44.0
[PATCH v3 6/7] efi_selftest: Add geometric shapes character selftest
From: Janne Grunau Draw symbols from Unicode's "Geometric shapes" page which translate to code page 437 code points 1-31. These are used by UEFI applications to draw user interfaces using EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL. The output has to be checked manually on the screen for correctness. Signed-off-by: Janne Grunau --- lib/efi_selftest/efi_selftest_textoutput.c | 13 + 1 file changed, 13 insertions(+) diff --git a/lib/efi_selftest/efi_selftest_textoutput.c b/lib/efi_selftest/efi_selftest_textoutput.c index b56fd2ab76..2208a9877a 100644 --- a/lib/efi_selftest/efi_selftest_textoutput.c +++ b/lib/efi_selftest/efi_selftest_textoutput.c @@ -60,6 +60,13 @@ u"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534" u"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" u"\u2500\u2500\u2500\u2500\u2518\n"; + const u16 shapes[] = +u"Geometric shapes as described\n" +u"U+25B2 \u25B2 - Black up-pointing triangle\n" +u"U+25BA \u25BA - Black right-pointing pointer\n" +u"U+25BC \u25BC - Black down-pointing triangle\n" +u"U+25C4 \u25C4 - Black left-pointing pointer\n"; + /* SetAttribute */ efi_st_printf("\nColor palette\n"); for (foreground = 0; foreground < 0x10; ++foreground) { @@ -160,6 +167,12 @@ u"\u2500\u2500\u2500\u2500\u2518\n"; return EFI_ST_FAILURE; } efi_st_printf("\n"); + ret = con_out->output_string(con_out, shapes); + if (ret != EFI_ST_SUCCESS) { + efi_st_error("OutputString failed for geometric shapes\n"); + return EFI_ST_FAILURE; + } + efi_st_printf("\n"); return EFI_ST_SUCCESS; } -- 2.44.0
[PATCH v3 5/7] efi_selftest: Add box drawing character selftest
From: Andre Przywara UEFI applications rely on Unicode output capability, and might use that for drawing pseudo-graphical interfaces using Unicode defined box drawing characters. Add a simple test to display the most basic box characters, which would need to be checked manually on the screen for correctness. Signed-off-by: Andre Przywara Suggested-by: Heinrich Schuchardt Signed-off-by: Janne Grunau --- lib/efi_selftest/efi_selftest_textoutput.c | 20 1 file changed, 20 insertions(+) diff --git a/lib/efi_selftest/efi_selftest_textoutput.c b/lib/efi_selftest/efi_selftest_textoutput.c index 917903473d..b56fd2ab76 100644 --- a/lib/efi_selftest/efi_selftest_textoutput.c +++ b/lib/efi_selftest/efi_selftest_textoutput.c @@ -46,6 +46,20 @@ u"U+03BB \u03BB - Greek small letter lambda\n" u"U+03C2 \u03C2 - Greek small letter final sigma\n" u"U+1F19 \u1F19 - Greek capital letter epsilon with dasia\n"; + const u16 boxes[] = +u"This should render as four boxes with text\n" +u"\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" +u"\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500" +u"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502" +u" left top\u2502 right top \u2502\n\u251c\u2500" +u"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" +u"\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" +u"\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 " +u"left bottom \u2502 right bottom \u2502\n\u2514\u2500\u2500\u2500" +u"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534" +u"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" +u"\u2500\u2500\u2500\u2500\u2518\n"; + /* SetAttribute */ efi_st_printf("\nColor palette\n"); for (foreground = 0; foreground < 0x10; ++foreground) { @@ -140,6 +154,12 @@ u"U+1F19 \u1F19 - Greek capital letter epsilon with dasia\n"; return EFI_ST_FAILURE; } efi_st_printf("\n"); + ret = con_out->output_string(con_out, boxes); + if (ret != EFI_ST_SUCCESS) { + efi_st_error("OutputString failed for box drawing chars\n"); + return EFI_ST_FAILURE; + } + efi_st_printf("\n"); return EFI_ST_SUCCESS; } -- 2.44.0
[PATCH v3 4/7] efi_selftest: Add international characters test
From: Andre Przywara UEFI relies entirely on unicode output, which actual fonts displayed on the screen might not be ready for. Add a test displaying some international characters, to reveal missing glyphs, especially in our builtin fonts. This would be needed to be manually checked on the screen for correctness. Signed-off-by: Andre Przywara Suggested-by: Heinrich Schuchardt Signed-off-by: Janne Grunau --- lib/efi_selftest/efi_selftest_textoutput.c | 21 + 1 file changed, 21 insertions(+) diff --git a/lib/efi_selftest/efi_selftest_textoutput.c b/lib/efi_selftest/efi_selftest_textoutput.c index cc44b38bc2..917903473d 100644 --- a/lib/efi_selftest/efi_selftest_textoutput.c +++ b/lib/efi_selftest/efi_selftest_textoutput.c @@ -31,6 +31,21 @@ static int execute(void) 0xD804, 0xDC22, 0}; + const u16 text[] = +u"This should render international characters as described\n" +u"U+00D6 \u00D6 - Latin capital letter O with diaresis\n" +u"U+00DF \u00DF - Latin small letter sharp s\n" +u"U+00E5 \u00E5 - Latin small letter a with ring above\n" +u"U+00E9 \u00E9 - Latin small letter e with acute\n" +u"U+00F1 \u00F1 - Latin small letter n with tilde\n" +u"U+00F6 \u00F6 - Latin small letter o with diaresis\n" +u"The following characters will render as '?' with bitmap fonts\n" +u"U+00F8 \u00F8 - Latin small letter o with stroke\n" +u"U+03AC \u03AC - Greek small letter alpha with tonus\n" +u"U+03BB \u03BB - Greek small letter lambda\n" +u"U+03C2 \u03C2 - Greek small letter final sigma\n" +u"U+1F19 \u1F19 - Greek capital letter epsilon with dasia\n"; + /* SetAttribute */ efi_st_printf("\nColor palette\n"); for (foreground = 0; foreground < 0x10; ++foreground) { @@ -119,6 +134,12 @@ static int execute(void) return EFI_ST_FAILURE; } efi_st_printf("\n"); + ret = con_out->output_string(con_out, text); + if (ret != EFI_ST_SUCCESS) { + efi_st_error("OutputString failed for international chars\n"); + return EFI_ST_FAILURE; + } + efi_st_printf("\n"); return EFI_ST_SUCCESS; } -- 2.44.0
[PATCH v3 0/7] video: Add UTF-8 support for UEFI applications
Andre submitted 2 years ago DM_VIDEO improvements for UEFI applications using UEFI's EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL but did not follow with suggested changes. This series takes care of the UTF-8 support which required to draw symbol and box drawing characters used by UEFI applications like grub2 and sd-boot correctly. Compared to Andre's version this version has the following changes: - use and extend existing conversion functions from lib/charset.c - convert to Unicode code points for truetype console support - conversion is conditional on CONFIG_CHARSET - use escape sequences in tests as proposed by Heinrich Link: https://lore.kernel.org/u-boot/20220110005638.21599-1-andre.przyw...@arm.com/ Signed-off-by: Janne Grunau --- Changes in v3: - added Reviewed-by tag - removed unnecessary u8 casts - limited utf-8 conversion buffer to 5 bytes as documented - added missing console_utf_to_cp437() documentation - adapted EFI text output self-tests according to review comments - dropped wait after EFI text output self tests - added StrToFat EFI self test to ensure Unicode code points which map to code page 437 code points 1-31 are converted to '_' - Link to v2: https://lore.kernel.org/r/20240210-vidconsole-utf8-uefi-v2-0-88c03db60...@jannau.net Changes in v2: - use "CONFIG_IS_ENABLED(CHARSET)" instead of EFI_LOADER - rewritten commit message for mapping CP437 cp 1-31 - extended utf8_to_utf32_stream() documentation as suggested by Heinrich - Link to RFC: https://lore.kernel.org/r/20240117-vidconsole-utf8-uefi-v1-0-539f7ce74...@jannau.net --- Andre Przywara (2): efi_selftest: Add international characters test efi_selftest: Add box drawing character selftest Janne Grunau (5): lib: charset: Fix and extend utf8_to_utf32_stream() documentation video: console: Parse UTF-8 character sequences lib/charset: Map Unicode code points to CP437 code points 1-31 efi_selftest: Add geometric shapes character selftest efi_selftest: Update StrToFat() unit test after CP473 map extension drivers/video/console_normal.c| 6 ++- drivers/video/console_rotate.c| 16 --- drivers/video/console_truetype.c | 8 ++-- drivers/video/vidconsole-uclass.c | 18 +--- drivers/video/vidconsole_internal.h | 19 include/charset.h | 16 +-- include/cp1250.h | 12 - include/cp437.h | 12 - include/video_console.h | 10 +++-- lib/charset.c | 9 ++-- lib/efi_loader/efi_unicode_collation.c| 2 +- lib/efi_selftest/efi_selftest_textoutput.c| 54 +++ lib/efi_selftest/efi_selftest_unicode_collation.c | 12 + 13 files changed, 162 insertions(+), 32 deletions(-) --- base-commit: 866ca972d6c3cabeaf6dbac431e8e08bb30b3c8e change-id: 20240117-vidconsole-utf8-uefi-fa23b4ac65d6 Best regards, -- Janne Grunau
[PATCH v3 3/7] lib/charset: Map Unicode code points to CP437 code points 1-31
From: Janne Grunau Code page 437 uses code points 1-31 for glyphs instead of control characters. Map the appropriate Unicode code points to this code points. Fixes rendering of grub2's menu as EFI application using the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL on a console with bitmap fonts. Signed-off-by: Janne Grunau --- include/charset.h | 2 +- include/cp1250.h | 12 ++-- include/cp437.h| 12 ++-- lib/charset.c | 9 ++--- lib/efi_loader/efi_unicode_collation.c | 2 +- 5 files changed, 28 insertions(+), 9 deletions(-) diff --git a/include/charset.h b/include/charset.h index f1050c903d..348bad5883 100644 --- a/include/charset.h +++ b/include/charset.h @@ -16,7 +16,7 @@ /* * codepage_437 - Unicode to codepage 437 translation table */ -extern const u16 codepage_437[128]; +extern const u16 codepage_437[160]; /** * console_read_unicode() - read Unicode code point from console diff --git a/include/cp1250.h b/include/cp1250.h index adacf8a958..b762c78d9f 100644 --- a/include/cp1250.h +++ b/include/cp1250.h @@ -1,10 +1,18 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* - * Constant CP1250 contains the Unicode code points for characters 0x80 - 0xff - * of the code page 1250. + * Constant CP1250 contains the Unicode code points for characters 0x00 - 0x1f + * and 0x80 - 0xff of the code page 1250. */ #define CP1250 { \ + 0x, 0x, 0x, 0x, \ + 0x, 0x, 0x, 0x, \ + 0x, 0x, 0x, 0x, \ + 0x, 0x, 0x, 0x, \ + 0x, 0x, 0x, 0x, \ + 0x, 0x, 0x, 0x, \ + 0x, 0x, 0x, 0x, \ + 0x, 0x, 0x, 0x, \ 0x20ac, 0x, 0x201a, 0x, \ 0x201e, 0x2026, 0x2020, 0x2021, \ 0x, 0x2030, 0x0160, 0x2039, \ diff --git a/include/cp437.h b/include/cp437.h index 0b2b97132e..5093130f5e 100644 --- a/include/cp437.h +++ b/include/cp437.h @@ -1,10 +1,18 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* - * Constant CP437 contains the Unicode code points for characters 0x80 - 0xff - * of the code page 437. + * Constant CP437 contains the Unicode code points for characters 0x00 - 0x1f + * and 0x80 - 0xff of the code page 437. */ #define CP437 { \ + 0x, 0x263a, 0x263b, 0x2665, \ + 0x2666, 0x2663, 0x2660, 0x2022, \ + 0x25d8, 0x25cb, 0x25d9, 0x2642, \ + 0x2640, 0x266a, 0x266b, 0x263c, \ + 0x25ba, 0x25c4, 0x2195, 0x203c, \ + 0x00b6, 0x00a7, 0x25ac, 0x21a8, \ + 0x2191, 0x2193, 0x2192, 0x2190, \ + 0x221f, 0x2194, 0x25b2, 0x25bc, \ 0x00c7, 0x00fc, 0x00e9, 0x00e2, \ 0x00e4, 0x00e0, 0x00e5, 0x00e7, \ 0x00ea, 0x00eb, 0x00e8, 0x00ef, \ diff --git a/lib/charset.c b/lib/charset.c index 5e4c4f948a..1f8480150a 100644 --- a/lib/charset.c +++ b/lib/charset.c @@ -16,7 +16,7 @@ /** * codepage_437 - Unicode to codepage 437 translation table */ -const u16 codepage_437[128] = CP437; +const u16 codepage_437[160] = CP437; static struct capitalization_table capitalization_table[] = #ifdef CONFIG_EFI_UNICODE_CAPITALIZATION @@ -517,9 +517,12 @@ int utf_to_cp(s32 *c, const u16 *codepage) int j; /* Look up codepage translation */ - for (j = 0; j < 0x80; ++j) { + for (j = 0; j < 0xA0; ++j) { if (*c == codepage[j]) { - *c = j + 0x80; + if (j < 0x20) + *c = j; + else + *c = j + 0x60; return 0; } } diff --git a/lib/efi_loader/efi_unicode_collation.c b/lib/efi_loader/efi_unicode_collation.c index c4c7572063..4b2c52918a 100644 --- a/lib/efi_loader/efi_unicode_collation.c +++ b/lib/efi_loader/efi_unicode_collation.c @@ -257,7 +257,7 @@ static void EFIAPI efi_fat_to_str(struct efi_unicode_collation_protocol *this, for (i = 0; i < fat_size; ++i) { c = (unsigned char)fat[i]; if (c > 0x80) - c = codepage[c - 0x80]; + c = codepage[c - 0x60]; string[i] = c; if (!c) break; -- 2.44.0
[PATCH 2/6] usb: xhci: Set up endpoints for the first 2 interfaces
From: Janne Grunau Apple USB keyboards carry the HID keyboard boot protocol on the second interface. Using the second interface in the USB keyboard driver does not work since the xhci has not allocated a transfer ring. --- drivers/usb/host/xhci.c | 31 +++ include/usb.h | 6 ++ 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 534c4b973f..741e186ee0 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -606,24 +606,28 @@ static int xhci_set_configuration(struct usb_device *udev) int slot_id = udev->slot_id; struct xhci_virt_device *virt_dev = ctrl->devs[slot_id]; struct usb_interface *ifdesc; + unsigned int ifnum; + unsigned int max_ifnum = min((unsigned int)USB_MAX_ACTIVE_INTERFACES, +(unsigned int)udev->config.no_of_if); out_ctx = virt_dev->out_ctx; in_ctx = virt_dev->in_ctx; - num_of_ep = udev->config.if_desc[0].no_of_ep; - ifdesc = >config.if_desc[0]; - ctrl_ctx = xhci_get_input_control_ctx(in_ctx); /* Initialize the input context control */ ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG); ctrl_ctx->drop_flags = 0; - /* EP_FLAG gives values 1 & 4 for EP1OUT and EP2IN */ - for (cur_ep = 0; cur_ep < num_of_ep; cur_ep++) { - ep_flag = xhci_get_ep_index(>ep_desc[cur_ep]); - ctrl_ctx->add_flags |= cpu_to_le32(1 << (ep_flag + 1)); - if (max_ep_flag < ep_flag) - max_ep_flag = ep_flag; + for (ifnum = 0; ifnum < max_ifnum; ifnum++) { + ifdesc = >config.if_desc[ifnum]; + num_of_ep = ifdesc->no_of_ep; + /* EP_FLAG gives values 1 & 4 for EP1OUT and EP2IN */ + for (cur_ep = 0; cur_ep < num_of_ep; cur_ep++) { + ep_flag = xhci_get_ep_index(>ep_desc[cur_ep]); + ctrl_ctx->add_flags |= cpu_to_le32(1 << (ep_flag + 1)); + if (max_ep_flag < ep_flag) + max_ep_flag = ep_flag; + } } xhci_inval_cache((uintptr_t)out_ctx->bytes, out_ctx->size); @@ -637,9 +641,12 @@ static int xhci_set_configuration(struct usb_device *udev) xhci_endpoint_copy(ctrl, in_ctx, out_ctx, 0); /* filling up ep contexts */ - err = xhci_init_ep_contexts_if(udev, ctrl, virt_dev, ifdesc); - if (err < 0) - return err; + for (ifnum = 0; ifnum < max_ifnum; ifnum++) { + ifdesc = >config.if_desc[ifnum]; + err = xhci_init_ep_contexts_if(udev, ctrl, virt_dev, ifdesc); + if (err < 0) + return err; + } return xhci_configure_endpoints(udev, false); } diff --git a/include/usb.h b/include/usb.h index 09e3f0cb30..3aafdc8bfd 100644 --- a/include/usb.h +++ b/include/usb.h @@ -49,6 +49,12 @@ extern bool usb_started; /* flag for the started/stopped USB status */ */ #define USB_TIMEOUT_MS(pipe) (usb_pipebulk(pipe) ? 5000 : 1000) +/* + * The xhcd hcd driver prepares only a limited number interfaces / endpoints. + * Define this limit so that drivers do not exceed it. + */ +#define USB_MAX_ACTIVE_INTERFACES 2 + /* device request (setup) */ struct devrequest { __u8requesttype; -- 2.43.2
[PATCH 6/6] usb: kbd: Add probe quirk for Apple and Keychron keyboards
From: Janne Grunau Those keyboards do not return the current device state. Polling will timeout unless there are key presses. This is not a problem during operation but the inital device state query during probing will fail. Skip this step in usb_kbd_probe_dev() to make these devices useable. Not all Apple keyboards behave like this. A keyboard with USB vendor/product ID 05ac:0221 is reported to work with the current code. Unfortunately some Keychron keyboards "re-use" Apple's vendor ID and show the same behavior (Keychron C2, 05ac:024f for example). Signed-off-by: Janne Grunau --- common/usb_kbd.c | 22 ++ 1 file changed, 22 insertions(+) diff --git a/common/usb_kbd.c b/common/usb_kbd.c index 7aa803eb4e..b0012ce7ad 100644 --- a/common/usb_kbd.c +++ b/common/usb_kbd.c @@ -31,6 +31,10 @@ #define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_20210x029a #define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021 0x029f +#define USB_VENDOR_ID_KEYCHRON 0x3434 + +#define USB_HID_QUIRK_POLL_NO_REPORT_IDLE (1 << 0) + /* * If overwrite_console returns 1, the stdin, stderr and stdout * are switched to the serial port, else the settings in the @@ -483,6 +487,7 @@ static int usb_kbd_probe_dev(struct usb_device *dev, unsigned int ifnum) struct usb_interface *iface; struct usb_endpoint_descriptor *ep; struct usb_kbd_pdata *data; + unsigned int quirks = 0; int epNum; int i; @@ -525,6 +530,15 @@ static int usb_kbd_probe_dev(struct usb_device *dev, unsigned int ifnum) debug("USB KBD: found interrupt EP: 0x%x\n", ep->bEndpointAddress); + switch (dev->descriptor.idVendor) { + case USB_VENDOR_ID_APPLE: + case USB_VENDOR_ID_KEYCHRON: + quirks |= USB_HID_QUIRK_POLL_NO_REPORT_IDLE; + break; + default: + break; + } + data = malloc(sizeof(struct usb_kbd_pdata)); if (!data) { printf("USB KBD: Error allocating private data\n"); @@ -565,6 +579,14 @@ static int usb_kbd_probe_dev(struct usb_device *dev, unsigned int ifnum) usb_set_idle(dev, iface->desc.bInterfaceNumber, 0, 0); #endif + /* +* Apple and Keychron keyboards do not report the device state. Reports +* are only returned during key presses. +*/ + if (quirks & USB_HID_QUIRK_POLL_NO_REPORT_IDLE) { + debug("USB KBD: quirk: skip testing device state\n"); + return 1; + } debug("USB KBD: enable interrupt pipe...\n"); #ifdef CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE data->intq = create_int_queue(dev, data->intpipe, 1, -- 2.43.2
[PATCH 3/6] usb: xhci: Abort transfers with unallocated rings
From: Janne Grunau Discovered while trying to use the second interface in the USB keyboard driver necessary on Apple USB keyboards. Signed-off-by: Janne Grunau --- drivers/usb/host/xhci-ring.c | 5 + 1 file changed, 5 insertions(+) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index b60661fe05..4446f5f098 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -685,6 +685,9 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe, reset_ep(udev, ep_index); ring = virt_dev->eps[ep_index].ring; + if (!ring) + return -1; + /* * How much data is (potentially) left before the 64KB boundary? * XHCI Spec puts restriction( TABLE 49 and 6.4.1 section of XHCI Spec) @@ -871,6 +874,8 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe, ep_index = usb_pipe_ep_index(pipe); ep_ring = virt_dev->eps[ep_index].ring; + if (!ep_ring) + return -1; /* * Check to see if the max packet size for the default control -- 2.43.2
[PATCH 4/6] usb: kbd: Ignore Yubikeys
From: Hector Martin We currently only support one USB keyboard device, but some devices emulate keyboards for other purposes. Most commonly, people run into this with Yubikeys, so let's ignore those. Even if we end up supporting multiple keyboards in the future, it's safer to ignore known non-keyboard devices. Signed-off-by: Hector Martin --- common/usb_kbd.c | 19 +++ 1 file changed, 19 insertions(+) diff --git a/common/usb_kbd.c b/common/usb_kbd.c index 4cbc9acb73..774d3555d9 100644 --- a/common/usb_kbd.c +++ b/common/usb_kbd.c @@ -120,6 +120,15 @@ struct usb_kbd_pdata { extern int __maybe_unused net_busy_flag; +/* + * Since we only support one usbkbd device in the iomux, + * ignore common keyboard-emulating devices that aren't + * real keyboards. + */ +const uint16_t vid_blocklist[] = { + 0x1050, /* Yubico */ +}; + /* The period of time between two calls of usb_kbd_testc(). */ static unsigned long kbd_testc_tms; @@ -465,6 +474,7 @@ static int usb_kbd_probe_dev(struct usb_device *dev, unsigned int ifnum) struct usb_endpoint_descriptor *ep; struct usb_kbd_pdata *data; int epNum; + int i; if (dev->descriptor.bNumConfigurations != 1) return 0; @@ -480,6 +490,15 @@ static int usb_kbd_probe_dev(struct usb_device *dev, unsigned int ifnum) if (iface->desc.bInterfaceProtocol != USB_PROT_HID_KEYBOARD) return 0; + for (i = 0; i < ARRAY_SIZE(vid_blocklist); i++) { + if (dev->descriptor.idVendor == vid_blocklist[i]) { + printf("Ignoring keyboard device 0x%x:0x%x\n", + dev->descriptor.idVendor, + dev->descriptor.idProduct); + return 0; + } + } + for (epNum = 0; epNum < iface->desc.bNumEndpoints; epNum++) { ep = >ep_desc[epNum]; -- 2.43.2
[PATCH 1/6] usb: xhci: refactor xhci_set_configuration
From: Janne Grunau In the next step endpoints for multiple interfaces are set up. Move most of the per endpoint initialization to separate function to avoid another identation level. Signed-off-by: Janne Grunau --- drivers/usb/host/xhci.c | 119 +--- 1 file changed, 73 insertions(+), 46 deletions(-) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index d13cbff9b3..534c4b973f 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -475,67 +475,34 @@ static int xhci_configure_endpoints(struct usb_device *udev, bool ctx_change) } /** - * Configure the endpoint, programming the device contexts. + * Fill endpoint contexts for interface descriptor ifdesc. * - * @param udev pointer to the USB device structure - * Return: returns the status of the xhci_configure_endpoints + * @param udev pointer to the USB device structure + * @param ctrl pointer to the xhci pravte device structure + * @param virt_dev pointer to the xhci virtual device structure + * @param ifdesc pointer to the USB interface config descriptor + * Return: returns the status of xhci_init_ep_contexts_if */ -static int xhci_set_configuration(struct usb_device *udev) +static int xhci_init_ep_contexts_if(struct usb_device *udev, + struct xhci_ctrl *ctrl, + struct xhci_virt_device *virt_dev, + struct usb_interface *ifdesc + ) { - struct xhci_container_ctx *in_ctx; - struct xhci_container_ctx *out_ctx; - struct xhci_input_control_ctx *ctrl_ctx; - struct xhci_slot_ctx *slot_ctx; struct xhci_ep_ctx *ep_ctx[MAX_EP_CTX_NUM]; int cur_ep; - int max_ep_flag = 0; int ep_index; unsigned int dir; unsigned int ep_type; - struct xhci_ctrl *ctrl = xhci_get_ctrl(udev); - int num_of_ep; - int ep_flag = 0; u64 trb_64 = 0; - int slot_id = udev->slot_id; - struct xhci_virt_device *virt_dev = ctrl->devs[slot_id]; - struct usb_interface *ifdesc; u32 max_esit_payload; unsigned int interval; unsigned int mult; unsigned int max_burst; unsigned int avg_trb_len; unsigned int err_count = 0; + int num_of_ep = ifdesc->no_of_ep; - out_ctx = virt_dev->out_ctx; - in_ctx = virt_dev->in_ctx; - - num_of_ep = udev->config.if_desc[0].no_of_ep; - ifdesc = >config.if_desc[0]; - - ctrl_ctx = xhci_get_input_control_ctx(in_ctx); - /* Initialize the input context control */ - ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG); - ctrl_ctx->drop_flags = 0; - - /* EP_FLAG gives values 1 & 4 for EP1OUT and EP2IN */ - for (cur_ep = 0; cur_ep < num_of_ep; cur_ep++) { - ep_flag = xhci_get_ep_index(>ep_desc[cur_ep]); - ctrl_ctx->add_flags |= cpu_to_le32(1 << (ep_flag + 1)); - if (max_ep_flag < ep_flag) - max_ep_flag = ep_flag; - } - - xhci_inval_cache((uintptr_t)out_ctx->bytes, out_ctx->size); - - /* slot context */ - xhci_slot_copy(ctrl, in_ctx, out_ctx); - slot_ctx = xhci_get_slot_ctx(ctrl, in_ctx); - slot_ctx->dev_info &= ~(cpu_to_le32(LAST_CTX_MASK)); - slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(max_ep_flag + 1) | 0); - - xhci_endpoint_copy(ctrl, in_ctx, out_ctx, 0); - - /* filling up ep contexts */ for (cur_ep = 0; cur_ep < num_of_ep; cur_ep++) { struct usb_endpoint_descriptor *endpt_desc = NULL; struct usb_ss_ep_comp_descriptor *ss_ep_comp_desc = NULL; @@ -561,7 +528,8 @@ static int xhci_set_configuration(struct usb_device *udev) avg_trb_len = max_esit_payload; ep_index = xhci_get_ep_index(endpt_desc); - ep_ctx[ep_index] = xhci_get_ep_ctx(ctrl, in_ctx, ep_index); + ep_ctx[ep_index] = xhci_get_ep_ctx(ctrl, virt_dev->in_ctx, + ep_index); /* Allocate the ep rings */ virt_dev->eps[ep_index].ring = xhci_ring_alloc(ctrl, 1, true); @@ -614,6 +582,65 @@ static int xhci_set_configuration(struct usb_device *udev) } } + return 0; +} + +/** + * Configure the endpoint, programming the device contexts. + * + * @param udev pointer to the USB device structure + * Return: returns the status of the xhci_configure_endpoints + */ +static int xhci_set_configuration(struct usb_device *udev) +{ + struct xhci_container_ctx *out_ctx; + struct xhci_container_ctx *in_ctx; + struct xhci_input_control_ctx *ctrl_ctx; + struct xhci_slot_ctx *slot_ctx; + int err; + int cur_ep; + int max_ep_flag = 0; + struct xhci_ctrl *ctrl = xhci_get_ctrl(udev); + int num_of_ep; + int ep_flag = 0; + int slot_id =
[PATCH 5/6] usb: kbd: support Apple Magic Keyboards (2021)
From: Janne Grunau Apple USB keyboards (Magic Keyboard from 2021 (product id 0x029c)) carry the HID keyboard boot protocol on the second interface descriptor. Probe via vendor and product IDs since the class/subclass/protocol match uses the first interface descriptor. Probe the two first interface descriptors for the HID keyboard boot protocol. USB configuration descriptor for reference: | Bus 003 Device 002: ID 05ac:029c Apple, Inc. Magic Keyboard | Device Descriptor: | bLength18 | bDescriptorType 1 | bcdUSB 2.00 | bDeviceClass0 [unknown] | bDeviceSubClass 0 [unknown] | bDeviceProtocol 0 | bMaxPacketSize064 | idVendor 0x05ac Apple, Inc. | idProduct 0x029c Magic Keyboard | bcdDevice3.90 | iManufacturer 1 Apple Inc. | iProduct2 Magic Keyboard | iSerial 3 ... | bNumConfigurations 1 | Configuration Descriptor: | bLength 9 | bDescriptorType 2 | wTotalLength 0x003b | bNumInterfaces 2 | bConfigurationValue 1 | iConfiguration 4 Keyboard | bmAttributes 0xa0 | (Bus Powered) | Remote Wakeup | MaxPower 500mA | Interface Descriptor: | bLength 9 | bDescriptorType 4 | bInterfaceNumber0 | bAlternateSetting 0 | bNumEndpoints 1 | bInterfaceClass 3 Human Interface Device | bInterfaceSubClass 0 [unknown] | bInterfaceProtocol 0 | iInterface 5 Device Management | HID Device Descriptor: | bLength 9 | bDescriptorType33 | bcdHID 1.10 | bCountryCode0 Not supported | bNumDescriptors 1 | bDescriptorType34 Report | wDescriptorLength 83 | Report Descriptors: | ** UNAVAILABLE ** | Endpoint Descriptor: | bLength 7 | bDescriptorType 5 | bEndpointAddress 0x81 EP 1 IN | bmAttributes3 | Transfer TypeInterrupt | Synch Type None | Usage Type Data | wMaxPacketSize 0x0010 1x 16 bytes | bInterval 8 | Interface Descriptor: | bLength 9 | bDescriptorType 4 | bInterfaceNumber1 | bAlternateSetting 0 | bNumEndpoints 1 | bInterfaceClass 3 Human Interface Device | bInterfaceSubClass 1 Boot Interface Subclass | bInterfaceProtocol 1 Keyboard | iInterface 6 Keyboard / Boot | HID Device Descriptor: | bLength 9 | bDescriptorType33 | bcdHID 1.10 | bCountryCode 13 International (ISO) | bNumDescriptors 1 | bDescriptorType34 Report | wDescriptorLength 207 | Report Descriptors: | ** UNAVAILABLE ** | Endpoint Descriptor: | bLength 7 | bDescriptorType 5 | bEndpointAddress 0x82 EP 2 IN | bmAttributes3 | Transfer TypeInterrupt | Synch Type None | Usage Type Data | wMaxPacketSize 0x0010 1x 16 bytes | bInterval 8 Signed-off-by: Janne Grunau --- common/usb_kbd.c | 39 +++ 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/common/usb_kbd.c b/common/usb_kbd.c index 774d3555d9..7aa803eb4e 100644 --- a/common/usb_kbd.c +++ b/common/usb_kbd.c @@ -23,6 +23,14 @@ #include +/* + * USB vendor and product IDs used for quirks. + */ +#define USB_VENDOR_ID_APPLE0x05ac +#define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_20210x029c +#define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_20210x029a +#define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021 0x029f + /* * If overwrite_console returns 1, the stdin, stderr and stdout * are switched to the serial port, else the settings in the @@ -106,6 +114,8 @@ struct usb_kbd_pdata { unsigned long last_report; struct int_queue *intq; + uint32_tifnum; + uint32_trepeat_delay; uint32_tusb_in_pointer; @@ -159,8 +169,8 @@ static void usb_kbd_put_queue(struct usb_kbd_pdata *data, u8 c) */ static void usb_kbd_setled(struct usb_device *dev) { - struct usb_interface *iface = >config.if_desc[0]; struct usb_kbd_pdata *data = dev->privptr; + struct usb_interface *iface = >config.if_desc[data->ifnum];
[PATCH 0/6] USB keyboard improvements for asahi / desktop systems
Apple USB Keyboards from 2021 need quirks to be useable. The boot HID keyboard protocol is unfortunately not described in the first interface descriptor but the second. This needs several changes. The USB keyboard driver has to look at all (2) interface descriptors during probing. Since I didn't want to rebuild the USB driver probe code the Apple keyboards are bound to the keyboard driver via USB vendor and product IDs. To make the keyboards useable on Apple silicon devices the xhci driver needs to initializes rings for the endpoints of the first two interface descriptors. If this is causes concerns regarding regressions or memory use the USB_MAX_ACTIVE_INTERFACES define could be turned into a CONFIG option. Even after this changes the keyboards still do not probe successfully since they apparently do not behave HID standard compliant. They only generate reports on key events. This leads the final check whether the keyboard is operational to fail unless the user presses keys during the probe. Skip this check for known keyboards. Keychron seems to emulate Apple keyboards (some models even "re-use" Apple's USB vendor ID) so apply this quirk as well. Some devices like Yubikeys emulate a keyboard. since u-boot only binds a single keyboard block this kind of devices from the USB keyboard driver. Signed-off-by: Janne Grunau --- Hector Martin (1): usb: kbd: Ignore Yubikeys Janne Grunau (5): usb: xhci: refactor xhci_set_configuration usb: xhci: Set up endpoints for the first 2 interfaces usb: xhci: Abort transfers with unallocated rings usb: kbd: support Apple Magic Keyboards (2021) usb: kbd: Add probe quirk for Apple and Keychron keyboards common/usb_kbd.c | 80 +-- drivers/usb/host/xhci-ring.c | 5 ++ drivers/usb/host/xhci.c | 126 +++ include/usb.h| 6 +++ 4 files changed, 167 insertions(+), 50 deletions(-) --- base-commit: 37345abb97ef0dd9c50a03b2a72617612dcae585 change-id: 20240218-asahi-keyboards-f2ddaf0022b2 Best regards, -- Janne Grunau
[PATCH v2 6/6] efi_selftest: Add symbol character selftest
From: Janne Grunau Draw symbols from code page 437 code points 0x01 - 01f used by UEFI applications to draw user interfaces using EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL. Add a simple test to displaying the Konami code using symbols used by grub2. The output has to be checked manually on the screen for correctness. Signed-off-by: Janne Grunau --- lib/efi_selftest/efi_selftest_textoutput.c | 7 +++ 1 file changed, 7 insertions(+) diff --git a/lib/efi_selftest/efi_selftest_textoutput.c b/lib/efi_selftest/efi_selftest_textoutput.c index cc11a22eee..9e5d944fa0 100644 --- a/lib/efi_selftest/efi_selftest_textoutput.c +++ b/lib/efi_selftest/efi_selftest_textoutput.c @@ -46,6 +46,8 @@ u"left bottom \u2502 right bottom \u2502\n\u2514\u2500\u2500\u2500" u"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534" u"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" u"\u2500\u2500\u2500\u2500\u2518\n"; + const u16 konami[] = +u"Konami code: \u25b2 \u25b2 \u25bc \u25bc \u25c4 \u25ba \u25c4 \u25ba B A\n"; /* SetAttribute */ efi_st_printf("\nColor palette\n"); @@ -144,6 +146,11 @@ u"\u2500\u2500\u2500\u2500\u2518\n"; efi_st_error("OutputString failed for box drawing chars\n"); return EFI_ST_FAILURE; } + ret = con_out->output_string(con_out, konami); + if (ret != EFI_ST_SUCCESS) { + efi_st_error("OutputString failed for symbol chars\n"); + return EFI_ST_FAILURE; + } con_out->output_string(con_out, u"waiting for admiration...\n"); EFI_CALL(systab.boottime->stall(300)); efi_st_printf("\n"); -- 2.43.0
[PATCH v2 5/6] efi_selftest: Add box drawing character selftest
From: Andre Przywara UEFI applications rely on Unicode output capability, and might use that for drawing pseudo-graphical interfaces using Unicode defined box drawing characters. Add a simple test to display the most basic box characters, which would need to be checked manually on the screen for correctness. To facilitate this, add a three second delay after the output at this point. Signed-off-by: Andre Przywara Suggested-by: Heinrich Schuchardt Signed-off-by: Janne Grunau --- lib/efi_selftest/efi_selftest_textoutput.c | 20 1 file changed, 20 insertions(+) diff --git a/lib/efi_selftest/efi_selftest_textoutput.c b/lib/efi_selftest/efi_selftest_textoutput.c index 2aa81b0a80..cc11a22eee 100644 --- a/lib/efi_selftest/efi_selftest_textoutput.c +++ b/lib/efi_selftest/efi_selftest_textoutput.c @@ -33,6 +33,19 @@ static int execute(void) const u16 text[] = u"\u00d6sterreich Edelwei\u00df Sm\u00f8rrebr\u00f8d Sm\u00f6rg" u"\u00e5s Ni\u00f1o Ren\u00e9 >\u1f19\u03bb\u03bb\u03ac\u03c2<\n"; + const u16 boxes[] = +u"This should render as four boxes with text\n" +u"\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" +u"\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500" +u"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502" +u" left top\u2502 right top \u2502\n\u251c\u2500" +u"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" +u"\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" +u"\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 " +u"left bottom \u2502 right bottom \u2502\n\u2514\u2500\u2500\u2500" +u"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534" +u"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" +u"\u2500\u2500\u2500\u2500\u2518\n"; /* SetAttribute */ efi_st_printf("\nColor palette\n"); @@ -126,6 +139,13 @@ u"\u00e5s Ni\u00f1o Ren\u00e9 >\u1f19\u03bb\u03bb\u03ac\u03c2<\n"; efi_st_error("OutputString failed for international chars\n"); return EFI_ST_FAILURE; } + ret = con_out->output_string(con_out, boxes); + if (ret != EFI_ST_SUCCESS) { + efi_st_error("OutputString failed for box drawing chars\n"); + return EFI_ST_FAILURE; + } + con_out->output_string(con_out, u"waiting for admiration...\n"); + EFI_CALL(systab.boottime->stall(300)); efi_st_printf("\n"); return EFI_ST_SUCCESS; -- 2.43.0
[PATCH v2 1/6] lib: charset: Fix and extend utf8_to_utf32_stream() documentation
From: Janne Grunau Suggested-by: Heinrich Schuchardt Signed-off-by: Janne Grunau --- include/charset.h | 14 -- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/include/charset.h b/include/charset.h index 44034c71d3..f1050c903d 100644 --- a/include/charset.h +++ b/include/charset.h @@ -324,11 +324,21 @@ int utf_to_cp(s32 *c, const u16 *codepage); int utf8_to_cp437_stream(u8 c, char *buffer); /** - * utf8_to_utf32_stream() - convert UTF-8 stream to UTF-32 + * utf8_to_utf32_stream() - convert UTF-8 byte stream to Unicode code points + * + * The function is called for each byte @c in a UTF-8 stream. The byte is + * appended to the temporary storage @buffer until the UTF-8 stream in + * @buffer describes a Unicode code point. + * + * When a new code point has been decoded it is returned and buffer[0] is + * set to '\0', otherwise the return value is 0. + * + * The buffer must be at least 5 characters long. Before the first function + * invocation buffer[0] must be set to '\0'." * * @c: next UTF-8 character to convert * @buffer:buffer, at least 5 characters - * Return: next codepage 437 character or 0 + * Return: Unicode code point or 0 */ int utf8_to_utf32_stream(u8 c, char *buffer); -- 2.43.0
[PATCH v2 4/6] efi_selftest: Add international characters test
From: Andre Przywara UEFI relies entirely on unicode output, which actual fonts displayed on the screen might not be ready for. Add a test displaying some international characters, to reveal missing glyphs, especially in our builtin fonts. This would be needed to be manually checked on the screen for correctness. Signed-off-by: Andre Przywara Suggested-by: Heinrich Schuchardt Signed-off-by: Janne Grunau --- lib/efi_selftest/efi_selftest_textoutput.c | 8 1 file changed, 8 insertions(+) diff --git a/lib/efi_selftest/efi_selftest_textoutput.c b/lib/efi_selftest/efi_selftest_textoutput.c index cc44b38bc2..2aa81b0a80 100644 --- a/lib/efi_selftest/efi_selftest_textoutput.c +++ b/lib/efi_selftest/efi_selftest_textoutput.c @@ -30,6 +30,9 @@ static int execute(void) 0xD804, 0xDC05, 0xD804, 0xDC22, 0}; + const u16 text[] = +u"\u00d6sterreich Edelwei\u00df Sm\u00f8rrebr\u00f8d Sm\u00f6rg" +u"\u00e5s Ni\u00f1o Ren\u00e9 >\u1f19\u03bb\u03bb\u03ac\u03c2<\n"; /* SetAttribute */ efi_st_printf("\nColor palette\n"); @@ -118,6 +121,11 @@ static int execute(void) efi_st_printf("Unicode not handled properly\n"); return EFI_ST_FAILURE; } + ret = con_out->output_string(con_out, text); + if (ret != EFI_ST_SUCCESS) { + efi_st_error("OutputString failed for international chars\n"); + return EFI_ST_FAILURE; + } efi_st_printf("\n"); return EFI_ST_SUCCESS; -- 2.43.0
[PATCH v2 2/6] video: console: Parse UTF-8 character sequences
From: Janne Grunau efi_console / UEFI applications (grub2, sd-boot, ...) pass UTF-8 character sequences to vidconsole which results in wrong glyphs for code points outside of ASCII. The truetype console expects Unicode code points and bitmap font based consoles expect code page 437 code points. To support both convert UTF-8 to UTF-32 and pass Unicode code points in vidconsole_ops.putc_xy(). These can be used directly in console_truetype and after conversion to code page 437 in console_{normal,rotate}. This fixes rendering of international, symbol and box drawing characters used by UEFI applications. Signed-off-by: Janne Grunau --- drivers/video/console_normal.c | 6 -- drivers/video/console_rotate.c | 16 ++-- drivers/video/console_truetype.c| 8 drivers/video/vidconsole-uclass.c | 18 +- drivers/video/vidconsole_internal.h | 15 +++ include/video_console.h | 10 ++ 6 files changed, 52 insertions(+), 21 deletions(-) diff --git a/drivers/video/console_normal.c b/drivers/video/console_normal.c index a0231293f3..34ef5a5229 100644 --- a/drivers/video/console_normal.c +++ b/drivers/video/console_normal.c @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -63,7 +64,7 @@ static int console_move_rows(struct udevice *dev, uint rowdst, return 0; } -static int console_putc_xy(struct udevice *dev, uint x_frac, uint y, char ch) +static int console_putc_xy(struct udevice *dev, uint x_frac, uint y, int cp) { struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev); struct udevice *vid = dev->parent; @@ -73,8 +74,9 @@ static int console_putc_xy(struct udevice *dev, uint x_frac, uint y, char ch) int pbytes = VNBYTES(vid_priv->bpix); int x, linenum, ret; void *start, *line; + u8 ch = console_utf_to_cp437(cp); uchar *pfont = fontdata->video_fontdata + - (u8)ch * fontdata->char_pixel_bytes; + ch * fontdata->char_pixel_bytes; if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac) return -EAGAIN; diff --git a/drivers/video/console_rotate.c b/drivers/video/console_rotate.c index 65358a1c6e..e4303dfb36 100644 --- a/drivers/video/console_rotate.c +++ b/drivers/video/console_rotate.c @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -67,7 +68,7 @@ static int console_move_rows_1(struct udevice *dev, uint rowdst, uint rowsrc, return 0; } -static int console_putc_xy_1(struct udevice *dev, uint x_frac, uint y, char ch) +static int console_putc_xy_1(struct udevice *dev, uint x_frac, uint y, int cp) { struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev); struct udevice *vid = dev->parent; @@ -77,8 +78,9 @@ static int console_putc_xy_1(struct udevice *dev, uint x_frac, uint y, char ch) int pbytes = VNBYTES(vid_priv->bpix); int x, linenum, ret; void *start, *line; + u8 ch = console_utf_to_cp437(cp); uchar *pfont = fontdata->video_fontdata + - (u8)ch * fontdata->char_pixel_bytes; + ch * fontdata->char_pixel_bytes; if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac) return -EAGAIN; @@ -145,7 +147,7 @@ static int console_move_rows_2(struct udevice *dev, uint rowdst, uint rowsrc, return 0; } -static int console_putc_xy_2(struct udevice *dev, uint x_frac, uint y, char ch) +static int console_putc_xy_2(struct udevice *dev, uint x_frac, uint y, int cp) { struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev); struct udevice *vid = dev->parent; @@ -155,8 +157,9 @@ static int console_putc_xy_2(struct udevice *dev, uint x_frac, uint y, char ch) int pbytes = VNBYTES(vid_priv->bpix); int linenum, x, ret; void *start, *line; + u8 ch = console_utf_to_cp437(cp); uchar *pfont = fontdata->video_fontdata + - (u8)ch * fontdata->char_pixel_bytes; + ch * fontdata->char_pixel_bytes; if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac) return -EAGAIN; @@ -227,7 +230,7 @@ static int console_move_rows_3(struct udevice *dev, uint rowdst, uint rowsrc, return 0; } -static int console_putc_xy_3(struct udevice *dev, uint x_frac, uint y, char ch) +static int console_putc_xy_3(struct udevice *dev, uint x_frac, uint y, int cp) { struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev); struct udevice *vid = dev->parent; @@ -237,8 +240,9 @@ static int console_putc_xy_3(struct udevice *dev, uint x_frac, uint y, char ch) int pbytes = VNBYTES(vid_priv->bpix); int linenum, x, ret; void *start, *line; + u8 ch = console_utf_to_cp437(cp); uchar *pfont = fontdata->video_fontdata + -
[PATCH v2 0/6] video: Add UTF-8 support for UEFI applications
Andre submitted 2 years ago DM_VIDEO improvements for UEFI applications using UEFI's EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL but did not follow with suggested changes. This series takes care of the UTF-8 support which required to draw symbol and box drawing characters used by UEFI applications like grub2 and sd-boot correctly. Compared to Andre's version this version has the following changes: - use and extend existing conversion functions from lib/charset.c - convert to Unicode code points for truetype console support - conversion is conditional on CONFIG_CHARSET - use escape sequences in tests as proposed by Heinrich Link: https://lore.kernel.org/u-boot/20220110005638.21599-1-andre.przyw...@arm.com/ Signed-off-by: Janne Grunau --- Changes in v2: - use "CONFIG_IS_ENABLED(CHARSET)" instead of EFI_LOADER - rewritten commit message for mapping CP437 cp 1-31 - extended utf8_to_utf32_stream() documentation as suggested by Heinrich - Link to RFC: https://lore.kernel.org/r/20240117-vidconsole-utf8-uefi-v1-0-539f7ce74...@jannau.net --- Andre Przywara (2): efi_selftest: Add international characters test efi_selftest: Add box drawing character selftest Janne Grunau (4): lib: charset: Fix and extend utf8_to_utf32_stream() documentation video: console: Parse UTF-8 character sequences lib/charset: Map Unicode code points to CP437 code points 0-31 efi_selftest: Add symbol character selftest drivers/video/console_normal.c | 6 +++-- drivers/video/console_rotate.c | 16 +- drivers/video/console_truetype.c | 8 +++ drivers/video/vidconsole-uclass.c | 18 ++- drivers/video/vidconsole_internal.h| 15 + include/charset.h | 16 +++--- include/cp1250.h | 12 -- include/cp437.h| 12 -- include/video_console.h| 10 + lib/charset.c | 9 +--- lib/efi_loader/efi_unicode_collation.c | 2 +- lib/efi_selftest/efi_selftest_textoutput.c | 35 ++ 12 files changed, 127 insertions(+), 32 deletions(-) --- base-commit: 866ca972d6c3cabeaf6dbac431e8e08bb30b3c8e change-id: 20240117-vidconsole-utf8-uefi-fa23b4ac65d6 Best regards, -- Janne Grunau
[PATCH v2 3/6] lib/charset: Map Unicode code points to CP437 code points 0-31
From: Janne Grunau Code page 437 uses code points 1-31 for glyphs instead of control characters. Map the appropriate Unicode code points to this code points. Fixes rendering of grub2's menu as EFI application using the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL on a console with bitmap fonts. Signed-off-by: Janne Grunau --- include/charset.h | 2 +- include/cp1250.h | 12 ++-- include/cp437.h| 12 ++-- lib/charset.c | 9 ++--- lib/efi_loader/efi_unicode_collation.c | 2 +- 5 files changed, 28 insertions(+), 9 deletions(-) diff --git a/include/charset.h b/include/charset.h index f1050c903d..348bad5883 100644 --- a/include/charset.h +++ b/include/charset.h @@ -16,7 +16,7 @@ /* * codepage_437 - Unicode to codepage 437 translation table */ -extern const u16 codepage_437[128]; +extern const u16 codepage_437[160]; /** * console_read_unicode() - read Unicode code point from console diff --git a/include/cp1250.h b/include/cp1250.h index adacf8a958..b762c78d9f 100644 --- a/include/cp1250.h +++ b/include/cp1250.h @@ -1,10 +1,18 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* - * Constant CP1250 contains the Unicode code points for characters 0x80 - 0xff - * of the code page 1250. + * Constant CP1250 contains the Unicode code points for characters 0x00 - 0x1f + * and 0x80 - 0xff of the code page 1250. */ #define CP1250 { \ + 0x, 0x, 0x, 0x, \ + 0x, 0x, 0x, 0x, \ + 0x, 0x, 0x, 0x, \ + 0x, 0x, 0x, 0x, \ + 0x, 0x, 0x, 0x, \ + 0x, 0x, 0x, 0x, \ + 0x, 0x, 0x, 0x, \ + 0x, 0x, 0x, 0x, \ 0x20ac, 0x, 0x201a, 0x, \ 0x201e, 0x2026, 0x2020, 0x2021, \ 0x, 0x2030, 0x0160, 0x2039, \ diff --git a/include/cp437.h b/include/cp437.h index 0b2b97132e..5093130f5e 100644 --- a/include/cp437.h +++ b/include/cp437.h @@ -1,10 +1,18 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* - * Constant CP437 contains the Unicode code points for characters 0x80 - 0xff - * of the code page 437. + * Constant CP437 contains the Unicode code points for characters 0x00 - 0x1f + * and 0x80 - 0xff of the code page 437. */ #define CP437 { \ + 0x, 0x263a, 0x263b, 0x2665, \ + 0x2666, 0x2663, 0x2660, 0x2022, \ + 0x25d8, 0x25cb, 0x25d9, 0x2642, \ + 0x2640, 0x266a, 0x266b, 0x263c, \ + 0x25ba, 0x25c4, 0x2195, 0x203c, \ + 0x00b6, 0x00a7, 0x25ac, 0x21a8, \ + 0x2191, 0x2193, 0x2192, 0x2190, \ + 0x221f, 0x2194, 0x25b2, 0x25bc, \ 0x00c7, 0x00fc, 0x00e9, 0x00e2, \ 0x00e4, 0x00e0, 0x00e5, 0x00e7, \ 0x00ea, 0x00eb, 0x00e8, 0x00ef, \ diff --git a/lib/charset.c b/lib/charset.c index 5e4c4f948a..1f8480150a 100644 --- a/lib/charset.c +++ b/lib/charset.c @@ -16,7 +16,7 @@ /** * codepage_437 - Unicode to codepage 437 translation table */ -const u16 codepage_437[128] = CP437; +const u16 codepage_437[160] = CP437; static struct capitalization_table capitalization_table[] = #ifdef CONFIG_EFI_UNICODE_CAPITALIZATION @@ -517,9 +517,12 @@ int utf_to_cp(s32 *c, const u16 *codepage) int j; /* Look up codepage translation */ - for (j = 0; j < 0x80; ++j) { + for (j = 0; j < 0xA0; ++j) { if (*c == codepage[j]) { - *c = j + 0x80; + if (j < 0x20) + *c = j; + else + *c = j + 0x60; return 0; } } diff --git a/lib/efi_loader/efi_unicode_collation.c b/lib/efi_loader/efi_unicode_collation.c index c4c7572063..4b2c52918a 100644 --- a/lib/efi_loader/efi_unicode_collation.c +++ b/lib/efi_loader/efi_unicode_collation.c @@ -257,7 +257,7 @@ static void EFIAPI efi_fat_to_str(struct efi_unicode_collation_protocol *this, for (i = 0; i < fat_size; ++i) { c = (unsigned char)fat[i]; if (c > 0x80) - c = codepage[c - 0x80]; + c = codepage[c - 0x60]; string[i] = c; if (!c) break; -- 2.43.0
[PATCH] video: console: Fix buffer overflow in cmd 'font list'
From: Janne Grunau vidconsole_ops.get_font is documented to return -ENOENT after the last video_fontdata entry. Signed-off-by: Janne Grunau --- drivers/video/console_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/console_core.c b/drivers/video/console_core.c index d17764d0b0..939363653f 100644 --- a/drivers/video/console_core.c +++ b/drivers/video/console_core.c @@ -225,7 +225,7 @@ int console_simple_get_font(struct udevice *dev, int seq, struct vidfont_info *i { info->name = fonts[seq].name; - return 0; + return info->name ? 0 : -ENOENT; } int console_simple_select_font(struct udevice *dev, const char *name, uint size) --- base-commit: 866ca972d6c3cabeaf6dbac431e8e08bb30b3c8e change-id: 20240117-cmd_font_bitmap_segfault-cf291e2621c1 Best regards, -- Janne Grunau
[PATCH] video: Support VIDEO_X2R10G10B10 in truetype console
From: Janne Grunau Without explicit support for VIDEO_X2R10G10B10 VIDEO_X8R8G8B8 white will be rendered as cyan-ish. The conversion leaves to lowest 2 bits unset for more compact code. Signed-off-by: Janne Grunau --- drivers/video/console_truetype.c | 10 -- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/video/console_truetype.c b/drivers/video/console_truetype.c index 14fb81e956..547e5a8d9c 100644 --- a/drivers/video/console_truetype.c +++ b/drivers/video/console_truetype.c @@ -397,7 +397,10 @@ static int console_truetype_putc_xy(struct udevice *dev, uint x, uint y, if (vid_priv->colour_bg) val = 255 - val; - out = val | val << 8 | val << 16; + if (vid_priv->format == VIDEO_X2R10G10B10) + out = val << 2 | val << 12 | val << 22; + else + out = val | val << 8 | val << 16; if (vid_priv->colour_fg) *dst++ |= out; else @@ -911,7 +914,10 @@ static int truetype_set_cursor_visible(struct udevice *dev, bool visible, for (i = 0; i < width; i++) { int out; - out = val | val << 8 | val << 16; + if (vid_priv->format == VIDEO_X2R10G10B10) + out = val << 2 | val << 12 | val << 22; + else + out = val | val << 8 | val << 16; if (vid_priv->colour_fg) *dst++ |= out; else --- base-commit: 866ca972d6c3cabeaf6dbac431e8e08bb30b3c8e change-id: 20240117-console_truetype_x2r10g10b10-fe88e5864640 Best regards, -- Janne Grunau
[PATCH RFC 2/6] video: console: Parse UTF-8 character sequences
From: Janne Grunau efi_console / UEFI applications (grub2, sd-boot, ...) pass UTF-8 character sequences to vidconsole which results in wrong glyphs for code points outside of ASCII. The truetype console expects Unicode code points and bitmap font based consoles expect code page 437 code points. To support both convert UTF-8 to UTF-32 and pass Unicode code points in vidconsole_ops.putc_xy(). These can be used directly in console_truetype and after conversion to code page 437 in console_{normal,rotate}. This fixes rendering of international, symbol and box drawing characters used by UEFI applications. Signed-off-by: Janne Grunau --- drivers/video/console_normal.c | 6 -- drivers/video/console_rotate.c | 16 ++-- drivers/video/console_truetype.c| 8 drivers/video/vidconsole-uclass.c | 18 +- drivers/video/vidconsole_internal.h | 15 +++ include/video_console.h | 10 ++ 6 files changed, 52 insertions(+), 21 deletions(-) diff --git a/drivers/video/console_normal.c b/drivers/video/console_normal.c index a0231293f3..34ef5a5229 100644 --- a/drivers/video/console_normal.c +++ b/drivers/video/console_normal.c @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -63,7 +64,7 @@ static int console_move_rows(struct udevice *dev, uint rowdst, return 0; } -static int console_putc_xy(struct udevice *dev, uint x_frac, uint y, char ch) +static int console_putc_xy(struct udevice *dev, uint x_frac, uint y, int cp) { struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev); struct udevice *vid = dev->parent; @@ -73,8 +74,9 @@ static int console_putc_xy(struct udevice *dev, uint x_frac, uint y, char ch) int pbytes = VNBYTES(vid_priv->bpix); int x, linenum, ret; void *start, *line; + u8 ch = console_utf_to_cp437(cp); uchar *pfont = fontdata->video_fontdata + - (u8)ch * fontdata->char_pixel_bytes; + ch * fontdata->char_pixel_bytes; if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac) return -EAGAIN; diff --git a/drivers/video/console_rotate.c b/drivers/video/console_rotate.c index 65358a1c6e..e4303dfb36 100644 --- a/drivers/video/console_rotate.c +++ b/drivers/video/console_rotate.c @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -67,7 +68,7 @@ static int console_move_rows_1(struct udevice *dev, uint rowdst, uint rowsrc, return 0; } -static int console_putc_xy_1(struct udevice *dev, uint x_frac, uint y, char ch) +static int console_putc_xy_1(struct udevice *dev, uint x_frac, uint y, int cp) { struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev); struct udevice *vid = dev->parent; @@ -77,8 +78,9 @@ static int console_putc_xy_1(struct udevice *dev, uint x_frac, uint y, char ch) int pbytes = VNBYTES(vid_priv->bpix); int x, linenum, ret; void *start, *line; + u8 ch = console_utf_to_cp437(cp); uchar *pfont = fontdata->video_fontdata + - (u8)ch * fontdata->char_pixel_bytes; + ch * fontdata->char_pixel_bytes; if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac) return -EAGAIN; @@ -145,7 +147,7 @@ static int console_move_rows_2(struct udevice *dev, uint rowdst, uint rowsrc, return 0; } -static int console_putc_xy_2(struct udevice *dev, uint x_frac, uint y, char ch) +static int console_putc_xy_2(struct udevice *dev, uint x_frac, uint y, int cp) { struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev); struct udevice *vid = dev->parent; @@ -155,8 +157,9 @@ static int console_putc_xy_2(struct udevice *dev, uint x_frac, uint y, char ch) int pbytes = VNBYTES(vid_priv->bpix); int linenum, x, ret; void *start, *line; + u8 ch = console_utf_to_cp437(cp); uchar *pfont = fontdata->video_fontdata + - (u8)ch * fontdata->char_pixel_bytes; + ch * fontdata->char_pixel_bytes; if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac) return -EAGAIN; @@ -227,7 +230,7 @@ static int console_move_rows_3(struct udevice *dev, uint rowdst, uint rowsrc, return 0; } -static int console_putc_xy_3(struct udevice *dev, uint x_frac, uint y, char ch) +static int console_putc_xy_3(struct udevice *dev, uint x_frac, uint y, int cp) { struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev); struct udevice *vid = dev->parent; @@ -237,8 +240,9 @@ static int console_putc_xy_3(struct udevice *dev, uint x_frac, uint y, char ch) int pbytes = VNBYTES(vid_priv->bpix); int linenum, x, ret; void *start, *line; + u8 ch = console_utf_to_cp437(cp); uchar *pfont = fontdata->video_fontdata + -
[PATCH RFC 3/6] lib/charset: Map cp437 low chars (0x01 - 0x1f) from unicode
From: Janne Grunau Add mappings for code points 1 - 31 as those code points in code page 437 are graphics. Thios fixes rendering issues of various EFI boot loaders (grub2, sd-boot, ...) using EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL. Signed-off-by: Janne Grunau --- include/charset.h | 2 +- include/cp1250.h | 12 ++-- include/cp437.h| 12 ++-- lib/charset.c | 9 ++--- lib/efi_loader/efi_unicode_collation.c | 2 +- 5 files changed, 28 insertions(+), 9 deletions(-) diff --git a/include/charset.h b/include/charset.h index 714382e1c1..c51c29235f 100644 --- a/include/charset.h +++ b/include/charset.h @@ -16,7 +16,7 @@ /* * codepage_437 - Unicode to codepage 437 translation table */ -extern const u16 codepage_437[128]; +extern const u16 codepage_437[160]; /** * console_read_unicode() - read Unicode code point from console diff --git a/include/cp1250.h b/include/cp1250.h index adacf8a958..b762c78d9f 100644 --- a/include/cp1250.h +++ b/include/cp1250.h @@ -1,10 +1,18 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* - * Constant CP1250 contains the Unicode code points for characters 0x80 - 0xff - * of the code page 1250. + * Constant CP1250 contains the Unicode code points for characters 0x00 - 0x1f + * and 0x80 - 0xff of the code page 1250. */ #define CP1250 { \ + 0x, 0x, 0x, 0x, \ + 0x, 0x, 0x, 0x, \ + 0x, 0x, 0x, 0x, \ + 0x, 0x, 0x, 0x, \ + 0x, 0x, 0x, 0x, \ + 0x, 0x, 0x, 0x, \ + 0x, 0x, 0x, 0x, \ + 0x, 0x, 0x, 0x, \ 0x20ac, 0x, 0x201a, 0x, \ 0x201e, 0x2026, 0x2020, 0x2021, \ 0x, 0x2030, 0x0160, 0x2039, \ diff --git a/include/cp437.h b/include/cp437.h index 0b2b97132e..5093130f5e 100644 --- a/include/cp437.h +++ b/include/cp437.h @@ -1,10 +1,18 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* - * Constant CP437 contains the Unicode code points for characters 0x80 - 0xff - * of the code page 437. + * Constant CP437 contains the Unicode code points for characters 0x00 - 0x1f + * and 0x80 - 0xff of the code page 437. */ #define CP437 { \ + 0x, 0x263a, 0x263b, 0x2665, \ + 0x2666, 0x2663, 0x2660, 0x2022, \ + 0x25d8, 0x25cb, 0x25d9, 0x2642, \ + 0x2640, 0x266a, 0x266b, 0x263c, \ + 0x25ba, 0x25c4, 0x2195, 0x203c, \ + 0x00b6, 0x00a7, 0x25ac, 0x21a8, \ + 0x2191, 0x2193, 0x2192, 0x2190, \ + 0x221f, 0x2194, 0x25b2, 0x25bc, \ 0x00c7, 0x00fc, 0x00e9, 0x00e2, \ 0x00e4, 0x00e0, 0x00e5, 0x00e7, \ 0x00ea, 0x00eb, 0x00e8, 0x00ef, \ diff --git a/lib/charset.c b/lib/charset.c index 5e4c4f948a..1f8480150a 100644 --- a/lib/charset.c +++ b/lib/charset.c @@ -16,7 +16,7 @@ /** * codepage_437 - Unicode to codepage 437 translation table */ -const u16 codepage_437[128] = CP437; +const u16 codepage_437[160] = CP437; static struct capitalization_table capitalization_table[] = #ifdef CONFIG_EFI_UNICODE_CAPITALIZATION @@ -517,9 +517,12 @@ int utf_to_cp(s32 *c, const u16 *codepage) int j; /* Look up codepage translation */ - for (j = 0; j < 0x80; ++j) { + for (j = 0; j < 0xA0; ++j) { if (*c == codepage[j]) { - *c = j + 0x80; + if (j < 0x20) + *c = j; + else + *c = j + 0x60; return 0; } } diff --git a/lib/efi_loader/efi_unicode_collation.c b/lib/efi_loader/efi_unicode_collation.c index c4c7572063..4b2c52918a 100644 --- a/lib/efi_loader/efi_unicode_collation.c +++ b/lib/efi_loader/efi_unicode_collation.c @@ -257,7 +257,7 @@ static void EFIAPI efi_fat_to_str(struct efi_unicode_collation_protocol *this, for (i = 0; i < fat_size; ++i) { c = (unsigned char)fat[i]; if (c > 0x80) - c = codepage[c - 0x80]; + c = codepage[c - 0x60]; string[i] = c; if (!c) break; -- 2.43.0
[PATCH RFC 0/6] video: Add UTF-8 support for UEFI applications
Andre submitted 2 years ago DM_VIDEO improvements for UEFI applications using UEFI's EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL but did not follow with suggested changes. This series takes care of the UTF-8 support which required to draw symbol and box drawing characters used by UEFI applications like grub2 and sd-boot correctly. Compared to Andre's version this version has the following changes: - use and extend existing conversion functions from lib/charset.c - convert first to UTF-32 to support the truetype console as well - conversion is conditional on CONFIG_EFI_LOADER - use escape sequences in tests as proposed by Heinrich Link: https://lore.kernel.org/u-boot/20220110005638.21599-1-andre.przyw...@arm.com/ Signed-off-by: Janne Grunau --- Andre Przywara (2): efi_selftest: Add international characters test efi_selftest: Add box drawing character selftest Janne Grunau (4): lib: charset: Fix utf8_to_utf32_stream() return value doc string video: console: Parse UTF-8 character sequences lib/charset: Map cp437 low chars (0x01 - 0x1f) from unicode efi_selftest: Add symbol character selftest drivers/video/console_normal.c | 6 +++-- drivers/video/console_rotate.c | 16 +- drivers/video/console_truetype.c | 8 +++ drivers/video/vidconsole-uclass.c | 18 ++- drivers/video/vidconsole_internal.h| 15 + include/charset.h | 4 ++-- include/cp1250.h | 12 -- include/cp437.h| 12 -- include/video_console.h| 10 + lib/charset.c | 9 +--- lib/efi_loader/efi_unicode_collation.c | 2 +- lib/efi_selftest/efi_selftest_textoutput.c | 35 ++ 12 files changed, 116 insertions(+), 31 deletions(-) --- base-commit: 866ca972d6c3cabeaf6dbac431e8e08bb30b3c8e change-id: 20240117-vidconsole-utf8-uefi-fa23b4ac65d6 Best regards, -- Janne Grunau
[PATCH RFC 6/6] efi_selftest: Add symbol character selftest
From: Janne Grunau Draw symbols from code page 437 code points 0x01 - 01f used by UEFI applications to draw user interfaces using EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL. Add a simple test to displaying the Konami code using symbols used by grub2. The output has to be checked manually on the screen for correctness. Signed-off-by: Janne Grunau --- lib/efi_selftest/efi_selftest_textoutput.c | 7 +++ 1 file changed, 7 insertions(+) diff --git a/lib/efi_selftest/efi_selftest_textoutput.c b/lib/efi_selftest/efi_selftest_textoutput.c index cc11a22eee..9e5d944fa0 100644 --- a/lib/efi_selftest/efi_selftest_textoutput.c +++ b/lib/efi_selftest/efi_selftest_textoutput.c @@ -46,6 +46,8 @@ u"left bottom \u2502 right bottom \u2502\n\u2514\u2500\u2500\u2500" u"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534" u"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" u"\u2500\u2500\u2500\u2500\u2518\n"; + const u16 konami[] = +u"Konami code: \u25b2 \u25b2 \u25bc \u25bc \u25c4 \u25ba \u25c4 \u25ba B A\n"; /* SetAttribute */ efi_st_printf("\nColor palette\n"); @@ -144,6 +146,11 @@ u"\u2500\u2500\u2500\u2500\u2518\n"; efi_st_error("OutputString failed for box drawing chars\n"); return EFI_ST_FAILURE; } + ret = con_out->output_string(con_out, konami); + if (ret != EFI_ST_SUCCESS) { + efi_st_error("OutputString failed for symbol chars\n"); + return EFI_ST_FAILURE; + } con_out->output_string(con_out, u"waiting for admiration...\n"); EFI_CALL(systab.boottime->stall(300)); efi_st_printf("\n"); -- 2.43.0
[PATCH RFC 5/6] efi_selftest: Add box drawing character selftest
From: Andre Przywara UEFI applications rely on Unicode output capability, and might use that for drawing pseudo-graphical interfaces using Unicode defined box drawing characters. Add a simple test to display the most basic box characters, which would need to be checked manually on the screen for correctness. To facilitate this, add a three second delay after the output at this point. Signed-off-by: Andre Przywara Suggested-by: Heinrich Schuchardt Signed-off-by: Janne Grunau --- lib/efi_selftest/efi_selftest_textoutput.c | 20 1 file changed, 20 insertions(+) diff --git a/lib/efi_selftest/efi_selftest_textoutput.c b/lib/efi_selftest/efi_selftest_textoutput.c index 2aa81b0a80..cc11a22eee 100644 --- a/lib/efi_selftest/efi_selftest_textoutput.c +++ b/lib/efi_selftest/efi_selftest_textoutput.c @@ -33,6 +33,19 @@ static int execute(void) const u16 text[] = u"\u00d6sterreich Edelwei\u00df Sm\u00f8rrebr\u00f8d Sm\u00f6rg" u"\u00e5s Ni\u00f1o Ren\u00e9 >\u1f19\u03bb\u03bb\u03ac\u03c2<\n"; + const u16 boxes[] = +u"This should render as four boxes with text\n" +u"\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" +u"\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500" +u"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502" +u" left top\u2502 right top \u2502\n\u251c\u2500" +u"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" +u"\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" +u"\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 " +u"left bottom \u2502 right bottom \u2502\n\u2514\u2500\u2500\u2500" +u"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534" +u"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" +u"\u2500\u2500\u2500\u2500\u2518\n"; /* SetAttribute */ efi_st_printf("\nColor palette\n"); @@ -126,6 +139,13 @@ u"\u00e5s Ni\u00f1o Ren\u00e9 >\u1f19\u03bb\u03bb\u03ac\u03c2<\n"; efi_st_error("OutputString failed for international chars\n"); return EFI_ST_FAILURE; } + ret = con_out->output_string(con_out, boxes); + if (ret != EFI_ST_SUCCESS) { + efi_st_error("OutputString failed for box drawing chars\n"); + return EFI_ST_FAILURE; + } + con_out->output_string(con_out, u"waiting for admiration...\n"); + EFI_CALL(systab.boottime->stall(300)); efi_st_printf("\n"); return EFI_ST_SUCCESS; -- 2.43.0
[PATCH RFC 1/6] lib: charset: Fix utf8_to_utf32_stream() return value doc string
From: Janne Grunau The comment appears to be copied from utf8_to_cp437_stream() but was not updated. Signed-off-by: Janne Grunau --- include/charset.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/charset.h b/include/charset.h index 44034c71d3..714382e1c1 100644 --- a/include/charset.h +++ b/include/charset.h @@ -328,7 +328,7 @@ int utf8_to_cp437_stream(u8 c, char *buffer); * * @c: next UTF-8 character to convert * @buffer:buffer, at least 5 characters - * Return: next codepage 437 character or 0 + * Return: next Unicode code point or 0 */ int utf8_to_utf32_stream(u8 c, char *buffer); -- 2.43.0
[PATCH RFC 4/6] efi_selftest: Add international characters test
From: Andre Przywara UEFI relies entirely on unicode output, which actual fonts displayed on the screen might not be ready for. Add a test displaying some international characters, to reveal missing glyphs, especially in our builtin fonts. This would be needed to be manually checked on the screen for correctness. Signed-off-by: Andre Przywara Suggested-by: Heinrich Schuchardt Signed-off-by: Janne Grunau --- lib/efi_selftest/efi_selftest_textoutput.c | 8 1 file changed, 8 insertions(+) diff --git a/lib/efi_selftest/efi_selftest_textoutput.c b/lib/efi_selftest/efi_selftest_textoutput.c index cc44b38bc2..2aa81b0a80 100644 --- a/lib/efi_selftest/efi_selftest_textoutput.c +++ b/lib/efi_selftest/efi_selftest_textoutput.c @@ -30,6 +30,9 @@ static int execute(void) 0xD804, 0xDC05, 0xD804, 0xDC22, 0}; + const u16 text[] = +u"\u00d6sterreich Edelwei\u00df Sm\u00f8rrebr\u00f8d Sm\u00f6rg" +u"\u00e5s Ni\u00f1o Ren\u00e9 >\u1f19\u03bb\u03bb\u03ac\u03c2<\n"; /* SetAttribute */ efi_st_printf("\nColor palette\n"); @@ -118,6 +121,11 @@ static int execute(void) efi_st_printf("Unicode not handled properly\n"); return EFI_ST_FAILURE; } + ret = con_out->output_string(con_out, text); + if (ret != EFI_ST_SUCCESS) { + efi_st_error("OutputString failed for international chars\n"); + return EFI_ST_FAILURE; + } efi_st_printf("\n"); return EFI_ST_SUCCESS; -- 2.43.0
[PATCH v2] arm: apple: t602x: Add missing MMIO regions to memmap
From: Janne Grunau The memory maps for Apple's M2 Pro/Max/Ultra left MMIO space out which was not used by any driver at the time. The display out exposed as simple-framebuffer use a power-domain controlled by a device in an unmapped region. Add a map covering this region as well as another MMIO region in the range 0x4'' - 0x5''. The added regions cover all MMIO annotated in Apple's device tree in this range. Signed-off-by: Janne Grunau --- Changes in v2: - use SZ_1G as block size - Link to v1: https://lore.kernel.org/r/20231130-apple_t602x_extend_memmap-v1-1-cd96b251d...@jannau.net --- arch/arm/mach-apple/board.c | 48 + 1 file changed, 48 insertions(+) diff --git a/arch/arm/mach-apple/board.c b/arch/arm/mach-apple/board.c index 47393babbc..7a6151a972 100644 --- a/arch/arm/mach-apple/board.c +++ b/arch/arm/mach-apple/board.c @@ -370,6 +370,22 @@ static struct mm_region t6020_mem_map[] = { .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* I/O */ + .virt = 0x4, + .phys = 0x4, + .size = SZ_1G, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* I/O */ + .virt = 0x48000, + .phys = 0x48000, + .size = SZ_1G, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN }, { /* I/O */ .virt = 0x58000, @@ -471,6 +487,22 @@ static struct mm_region t6022_mem_map[] = { .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* I/O */ + .virt = 0x4, + .phys = 0x4, + .size = SZ_1G, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* I/O */ + .virt = 0x48000, + .phys = 0x48000, + .size = SZ_1G, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN }, { /* I/O */ .virt = 0x58000, @@ -551,6 +583,22 @@ static struct mm_region t6022_mem_map[] = { .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* I/O */ + .virt = 0x24, + .phys = 0x24, + .size = SZ_1G, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* I/O */ + .virt = 0x248000, + .phys = 0x248000, + .size = SZ_1G, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN }, { /* I/O */ .virt = 0x258000, --- base-commit: 43f2873fa98b1da6eb56d756315c7bd7db63db27 change-id: 20231130-apple_t602x_extend_memmap-c82c522ca8c0 Best regards, -- Janne Grunau
[PATCH] arm: apple: t602x: Add missing MMIO regions to memmap
From: Janne Grunau The memory maps for Apple's M2 Pro/Max/Ultra left MMIO space out which was not used by any driver at the time. The display out exposed as simple-framebuffer use a power-domain controlled by a device in an unmapped region. Add a map covering this region as well as another MMIO region in the range 0x4'' - 0x5''. The added regions cover all MMIO annotated in Apple's device tree in this range. Signed-off-by: Janne Grunau --- arch/arm/mach-apple/board.c | 48 + 1 file changed, 48 insertions(+) diff --git a/arch/arm/mach-apple/board.c b/arch/arm/mach-apple/board.c index 47393babbc..e05ec431bc 100644 --- a/arch/arm/mach-apple/board.c +++ b/arch/arm/mach-apple/board.c @@ -370,6 +370,22 @@ static struct mm_region t6020_mem_map[] = { .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* I/O */ + .virt = 0x4, + .phys = 0x4, + .size = SZ_512M, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* I/O */ + .virt = 0x48000, + .phys = 0x48000, + .size = SZ_1G, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN }, { /* I/O */ .virt = 0x58000, @@ -471,6 +487,22 @@ static struct mm_region t6022_mem_map[] = { .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* I/O */ + .virt = 0x4, + .phys = 0x4, + .size = SZ_512M, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* I/O */ + .virt = 0x48000, + .phys = 0x48000, + .size = SZ_1G, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN }, { /* I/O */ .virt = 0x58000, @@ -551,6 +583,22 @@ static struct mm_region t6022_mem_map[] = { .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* I/O */ + .virt = 0x24, + .phys = 0x24, + .size = SZ_512M, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* I/O */ + .virt = 0x248000, + .phys = 0x248000, + .size = SZ_1G, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN }, { /* I/O */ .virt = 0x258000, --- base-commit: 43f2873fa98b1da6eb56d756315c7bd7db63db27 change-id: 20231130-apple_t602x_extend_memmap-c82c522ca8c0 Best regards, -- Janne Grunau