From patchwork Fri Aug 4 19:31:48 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Clark X-Patchwork-Id: 797968 X-Patchwork-Delegate: agraf@suse.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="ZBDrFBvI"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3xPHKg74qgz9s8P for ; Sat, 5 Aug 2017 05:38:47 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id A09D9C21E6C; Fri, 4 Aug 2017 19:38:15 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=FREEMAIL_FROM, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 2E8E0C21E27; Fri, 4 Aug 2017 19:33:19 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 0CA53C21EE7; Fri, 4 Aug 2017 19:32:50 +0000 (UTC) Received: from mail-qt0-f195.google.com (mail-qt0-f195.google.com [209.85.216.195]) by lists.denx.de (Postfix) with ESMTPS id A78BBC21E4A for ; Fri, 4 Aug 2017 19:32:46 +0000 (UTC) Received: by mail-qt0-f195.google.com with SMTP id t37so2462389qtg.2 for ; Fri, 04 Aug 2017 12:32:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=EUZEXRpj7zzjPId8y4Kz6wJ/LKMPpqykSEvcSYHcYUA=; b=ZBDrFBvIshzOOLsveNzfMnBKQdNwJe2hBNHlusHw9dsSzV+2+Scx+QBVC9hmkLhjfQ hO8OKF+YUvccbrHzasDwWGJ0Znr6ex6im8OYKY+F6lwrxnbUtCDmcWvEOL3fGGBWINSe 0eoKipB1OUoSwQkHeioH9+QpKQpzZHZwLUJNczXN2ASeiqxfrHrrHbZ0b8s03AA9GOMo y+JJSa93dDR3dqR0XXn18nPqxW/Xlf7Su0P9WiHuhjq/LIurVw5Gdxu4c1EVH/VkmpAg w2uSVpOAns84497HohRO+gpgbON8xG4RvvB3cCEcZqCuU5r1DC/ON5aMytgIovTzspN2 fyBg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=EUZEXRpj7zzjPId8y4Kz6wJ/LKMPpqykSEvcSYHcYUA=; b=CnfBuDwI4UHlt0Wk+m8MP5kniAXOpGpz5Kkw95iJrNrx68WoPvY9OewZv8nDI+BFwL c0d8+YJaGEFhyJHQNFCZX3XYlcpgYPfIK34qPalCUw0yycS+5bryHyQialEM7PSz7iy+ MWdDmdML9eK2YX5Jj5aEPCl6gnNYtU2GIqunAUL2r3NeeTyOKp/8x5XkiiI/Zpv4t4p8 LVfYVuuowjx/7Y/23MCcN+u++zJznnsm5meCPFo39TU0M5PlcrVkHesx3H0EeW8icdo/ LdhdrYjWrDS8+bKqWK/FciwYAFqzten/Luwleye717Xy47PW1MgoMnK1AcYCuCR3FzOj kWWg== X-Gm-Message-State: AHYfb5hU9zt0vcD8FZ/VY8bAmr7G3oxOaUNrcARQJMmgUFkao/HFMnRl A0blqU3zduMSBs+zZGw= X-Received: by 10.237.33.206 with SMTP id m14mr4944329qtc.9.1501875165348; Fri, 04 Aug 2017 12:32:45 -0700 (PDT) Received: from localhost ([2601:184:4780:aac0:25f8:dd96:a084:785a]) by smtp.gmail.com with ESMTPSA id d13sm1545714qti.72.2017.08.04.12.32.44 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Fri, 04 Aug 2017 12:32:44 -0700 (PDT) From: Rob Clark To: U-Boot Mailing List Date: Fri, 4 Aug 2017 15:31:48 -0400 Message-Id: <20170804193205.24669-7-robdclark@gmail.com> X-Mailer: git-send-email 2.13.0 In-Reply-To: <20170804193205.24669-1-robdclark@gmail.com> References: <20170804193205.24669-1-robdclark@gmail.com> Cc: Heinrich Schuchardt , Peter Jones , Andy Yan , "Cooper Jr., Franklin" Subject: [U-Boot] [PATCH v0 06/20] common: add some utf16 handling helpers X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" We'll eventually want these in a few places in efi_loader, and also vsprintf. Signed-off-by: Rob Clark --- common/Makefile | 1 + common/charset.c | 81 ++++++++++++++++++++++++++++++++++++++++++++ include/charset.h | 18 ++++++++++ lib/efi_loader/efi_console.c | 17 ++-------- 4 files changed, 103 insertions(+), 14 deletions(-) create mode 100644 common/charset.c create mode 100644 include/charset.h diff --git a/common/Makefile b/common/Makefile index 60681c845c..44c8e1ba52 100644 --- a/common/Makefile +++ b/common/Makefile @@ -175,5 +175,6 @@ obj-$(CONFIG_CMD_DFU) += dfu.o obj-y += command.o obj-y += s_record.o obj-y += xyzModem.o +obj-y += charset.o CFLAGS_env_embedded.o := -Wa,--no-warn -DENV_CRC=$(shell tools/envcrc 2>/dev/null) diff --git a/common/charset.c b/common/charset.c new file mode 100644 index 0000000000..eaff2e542e --- /dev/null +++ b/common/charset.c @@ -0,0 +1,81 @@ +/* + * charset conversion utils + * + * Copyright (c) 2017 Rob Clark + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include + +/* + * utf8/utf16 conversion mostly lifted from grub + */ + +size_t utf16_strlen(uint16_t *in) +{ + size_t i; + for (i = 0; in[i]; i++); + return i; +} + +size_t utf16_strnlen(const uint16_t *in, size_t count) +{ + size_t i; + for (i = 0; count-- && in[i]; i++); + return i; +} + +/* Convert UTF-16 to UTF-8. */ +uint8_t *utf16_to_utf8(uint8_t *dest, const uint16_t *src, size_t size) +{ + uint32_t code_high = 0; + + while (size--) { + uint32_t code = *src++; + + if (code_high) { + if (code >= 0xDC00 && code <= 0xDFFF) { + /* Surrogate pair. */ + code = ((code_high - 0xD800) << 10) + (code - 0xDC00) + 0x10000; + + *dest++ = (code >> 18) | 0xF0; + *dest++ = ((code >> 12) & 0x3F) | 0x80; + *dest++ = ((code >> 6) & 0x3F) | 0x80; + *dest++ = (code & 0x3F) | 0x80; + } else { + /* Error... */ + *dest++ = '?'; + /* *src may be valid. Don't eat it. */ + src--; + } + + code_high = 0; + } else { + if (code <= 0x007F) { + *dest++ = code; + } else if (code <= 0x07FF) { + *dest++ = (code >> 6) | 0xC0; + *dest++ = (code & 0x3F) | 0x80; + } else if (code >= 0xD800 && code <= 0xDBFF) { + code_high = code; + continue; + } else if (code >= 0xDC00 && code <= 0xDFFF) { + /* Error... */ + *dest++ = '?'; + } else if (code < 0x10000) { + *dest++ = (code >> 12) | 0xE0; + *dest++ = ((code >> 6) & 0x3F) | 0x80; + *dest++ = (code & 0x3F) | 0x80; + } else { + *dest++ = (code >> 18) | 0xF0; + *dest++ = ((code >> 12) & 0x3F) | 0x80; + *dest++ = ((code >> 6) & 0x3F) | 0x80; + *dest++ = (code & 0x3F) | 0x80; + } + } + } + + return dest; +} diff --git a/include/charset.h b/include/charset.h new file mode 100644 index 0000000000..2ee1172182 --- /dev/null +++ b/include/charset.h @@ -0,0 +1,18 @@ +/* + * charset conversion utils + * + * Copyright (c) 2017 Rob Clark + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __CHARSET_H_ +#define __CHARSET_H_ + +#define MAX_UTF8_PER_UTF16 4 + +size_t utf16_strlen(uint16_t *in); +size_t utf16_strnlen(const uint16_t *in, size_t count); +uint8_t *utf16_to_utf8(uint8_t *dest, const uint16_t *src, size_t size); + +#endif /* __CHARSET_H_ */ diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c index 5ebce4b544..3fc82b8726 100644 --- a/lib/efi_loader/efi_console.c +++ b/lib/efi_loader/efi_console.c @@ -7,6 +7,7 @@ */ #include +#include #include static bool console_size_queried; @@ -138,20 +139,8 @@ static efi_status_t EFIAPI efi_cout_reset( static void print_unicode_in_utf8(u16 c) { - char utf8[4] = { 0 }; - char *b = utf8; - - if (c < 0x80) { - *(b++) = c; - } else if (c < 0x800) { - *(b++) = 192 + c / 64; - *(b++) = 128 + c % 64; - } else { - *(b++) = 224 + c / 4096; - *(b++) = 128 + c / 64 % 64; - *(b++) = 128 + c % 64; - } - + char utf8[MAX_UTF8_PER_UTF16] = { 0 }; + utf16_to_utf8((u8 *)utf8, &c, 1); puts(utf8); }