From patchwork Sun Sep 10 11:21:19 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Clark X-Patchwork-Id: 812096 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="OxtH22QM"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3xqpZm5sDFz9sDB for ; Sun, 10 Sep 2017 21:23:11 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 4FE3AC21E55; Sun, 10 Sep 2017 11:22:22 +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 4C9A9C21E97; Sun, 10 Sep 2017 11:22:20 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id D42F1C21DBD; Sun, 10 Sep 2017 11:22:12 +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 C7CF3C21C39 for ; Sun, 10 Sep 2017 11:22:08 +0000 (UTC) Received: by mail-qt0-f195.google.com with SMTP id k2so4079721qte.5 for ; Sun, 10 Sep 2017 04:22:08 -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=C8brqXExN7NxaVnn/oz5yvzer5LRFsZ1dCKpKCuxfPE=; b=OxtH22QMXFmmnsCUMjTO1s3UFqnde641ZYCx+TEKbCbNNHuNofzZvuVWIss/JGf2MZ Hj5cN3Rqn6WYQ9uvXx7PooF+GBsablV5sWCy1vJg94jBUU5JMqJhtQqOrabDwHZug/w3 MCOYSiPxchs1gz5/SfsTpoDdiXsuGgJOlp38n3HNYJ8tQGx7W3IXX2ed0lfcujtG7h8G Wb5jJPYvhQ7iSdQ093MppHKBdUUl8/1iAWO5VEMp6+xfWydX7hmqHFLYXl88tFZQBnxn z/O+fBRETEwnsO3aKHPbzT5HevPQh7hpfaxAy/0oki9Op9T2Bb1q832iQQYgg7r1PV/a sYPw== 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=C8brqXExN7NxaVnn/oz5yvzer5LRFsZ1dCKpKCuxfPE=; b=Dem4YyrKzCA6ABV1t2R2ZXcC9wnfCpKJ1G3WEXkmZfQtl2jJUUjC3818MQRJENn2F6 ABtjgFaNq8eVmh/AdyJ9TfCu0jjA8RML1Dk3FFXzN9y793znzmWZ+ykcHftiU9UU+/AM 87oUX2rAU2pRQ+yjngIGExDsDbCckeJTruZnI3mFsyEWfDU+/52oTPQa2B8s1qsImTtn ThFaZ7KcEhHnzdX2bUR8VgpRQICAjIAvvBZXJFebf5LzRAnZxBMuVx531x8IM2hT8+8B ksY4rZEM63nB2ZD2BVTj1uicVL6vXcayyUk0oOSsc6uDSg7R2AzC/w8sgjqXMRbtSQ+B wQEA== X-Gm-Message-State: AHPjjUi4ZyFRMIL2m8B3xq4+r9sYwydOjHJ0A8IQXkUXLbTuhMY0bgjT kGwRLboUtAdxYc3eT+o= X-Google-Smtp-Source: AOwi7QAMofl65zLW7N1QwwA82gBkLgH+L420pzjDodxjErsr/WWq59kaAwTOapJSyF9AoiikwNTwHg== X-Received: by 10.200.8.225 with SMTP id y30mr11565952qth.239.1505042527390; Sun, 10 Sep 2017 04:22:07 -0700 (PDT) Received: from localhost ([2601:184:4780:aac0:25f8:dd96:a084:785a]) by smtp.gmail.com with ESMTPSA id c7sm471997qtg.30.2017.09.10.04.22.06 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sun, 10 Sep 2017 04:22:06 -0700 (PDT) From: Rob Clark To: U-Boot Mailing List Date: Sun, 10 Sep 2017 07:21:19 -0400 Message-Id: <20170910112149.21358-3-robdclark@gmail.com> X-Mailer: git-send-email 2.13.5 In-Reply-To: <20170910112149.21358-1-robdclark@gmail.com> References: <20170910112149.21358-1-robdclark@gmail.com> Cc: Petr Kulhavy , Heinrich Schuchardt , Alison Chaiken , Steve Rae , Maxime Ripard Subject: [U-Boot] [PATCH v2 01/21] part: move efi_guid_t 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" Prep work for next patch. Signed-off-by: Rob Clark Acked-by: Heinrich Schuchardt Reviewed-by: Simon Glass --- include/efi.h | 4 ++++ include/part.h | 3 ++- include/part_efi.h | 4 ---- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/include/efi.h b/include/efi.h index 02b78b31b1..87b0b43f20 100644 --- a/include/efi.h +++ b/include/efi.h @@ -28,6 +28,10 @@ struct efi_device_path; +typedef struct { + u8 b[16]; +} efi_guid_t; + #define EFI_BITS_PER_LONG BITS_PER_LONG /* diff --git a/include/part.h b/include/part.h index 86117a7ce5..b2e820ef8a 100644 --- a/include/part.h +++ b/include/part.h @@ -280,8 +280,9 @@ struct part_driver { #define U_BOOT_PART_TYPE(__name) \ ll_entry_declare(struct part_driver, __name, part_driver) -#if CONFIG_IS_ENABLED(EFI_PARTITION) #include + +#if CONFIG_IS_ENABLED(EFI_PARTITION) /* disk/part_efi.c */ /** * write_gpt_table() - Write the GUID Partition Table to disk diff --git a/include/part_efi.h b/include/part_efi.h index 317c044795..31e6bc6e14 100644 --- a/include/part_efi.h +++ b/include/part_efi.h @@ -58,10 +58,6 @@ /* linux/include/efi.h */ typedef u16 efi_char16_t; -typedef struct { - u8 b[16]; -} efi_guid_t; - /* based on linux/include/genhd.h */ struct partition { u8 boot_ind; /* 0x80 - active */ From patchwork Sun Sep 10 11:21:20 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Rob Clark X-Patchwork-Id: 812098 X-Patchwork-Delegate: trini@ti.com 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="FikrHPxc"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3xqpcT5NPWz9sNV for ; Sun, 10 Sep 2017 21:24:41 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 6E106C21C39; Sun, 10 Sep 2017 11:23:00 +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 F3308C21DDD; Sun, 10 Sep 2017 11:22:27 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 22CE2C21EA9; Sun, 10 Sep 2017 11:22:14 +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 937FCC21DDF for ; Sun, 10 Sep 2017 11:22:12 +0000 (UTC) Received: by mail-qt0-f195.google.com with SMTP id u48so1198195qtc.4 for ; Sun, 10 Sep 2017 04:22:12 -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 :mime-version:content-transfer-encoding; bh=olLHt/LWSXBdsV2nZv8WrqeymB/JReM33i5ffkISCXc=; b=FikrHPxcgwdyOM9LSRQiNT1grDCs+sOvKhOnCdZTGj7fYBgzS1aocoWdC8bh5+3QIm 6SjON6d7WkHbnf9VumKi9hBpRnHDwRIQBynAiG1MoaZUmzNwNdsp3NhPYTsNMVOVSM/s 9SIRpiEj2fcHXnwykBImkCa5x+Dv4rcmsZ4avg1Y0BMpDjAxup+d6ZJUUp6S4JB1UPEU 5dGtFHeObKSON1ZZX24RlTS6Md4OpoCh5yzzzuSED6Eqpqu2IJk2P8ZwkCPqql0A9TYS eqSWfvTNSeQ+HYA8ORVpE1ZGvRxIR+eskaFmkIuu6wU8u4d3IF15qdrNPJqClTnGOfEm 0+PQ== 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:mime-version:content-transfer-encoding; bh=olLHt/LWSXBdsV2nZv8WrqeymB/JReM33i5ffkISCXc=; b=nX4P+UgG4kL3QR3pZ8tONfmWeYtpXCJOO//f5+1mk+D6ll8MVHkbDAqt+OXS+bJi2P QiqcL66GYG8VBIRRBo18G1DQ4DVwdhDaUAj5CO9Kjv+7hZHGf/aSNpqaAz+Q0V6Uz915 JENrOe5MTPcXDAIGHppLL5zZncAm0ICFgGn3kBQbXE6KXSxsMz/2q28Y/AvHvaqYJp1g RfPBF8q8FmFiMRpWqZ73FnUQymvoM3JJxT2qyIz/Ztv5IszeM+Lxq7dfV3bl5KJhmqKH WOgDkDzxbrRNKRzM04NZYwqbszZ1VxhAS+uAZh1Mm7xamwFrFxmw2O133ZIPr2afKicW 9Q+A== X-Gm-Message-State: AHPjjUjOWC962Druew61Mm7vVaEA0p06SPL6wrYQowalbj0t4qpOqOju DQDtlWlWzAT9bqj+9Rw= X-Google-Smtp-Source: AOwi7QDhCi8wJz+P/Wf63lkFW5WmaPEM0SSuQvxVG6VecTMw3DGIy8jX9KPX4nltFD8p4OWUfV7Aig== X-Received: by 10.200.53.67 with SMTP id z3mr12458856qtb.145.1505042531142; Sun, 10 Sep 2017 04:22:11 -0700 (PDT) Received: from localhost ([2601:184:4780:aac0:25f8:dd96:a084:785a]) by smtp.gmail.com with ESMTPSA id q204sm4218283qke.37.2017.09.10.04.22.09 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sun, 10 Sep 2017 04:22:09 -0700 (PDT) From: Rob Clark To: U-Boot Mailing List Date: Sun, 10 Sep 2017 07:21:20 -0400 Message-Id: <20170910112149.21358-4-robdclark@gmail.com> X-Mailer: git-send-email 2.13.5 In-Reply-To: <20170910112149.21358-1-robdclark@gmail.com> References: <20170910112149.21358-1-robdclark@gmail.com> MIME-Version: 1.0 Cc: Heinrich Schuchardt , Genevieve Chan , Tien Fong Chee Subject: [U-Boot] [PATCH v3 2/9] fs/fat: introduce new director iterators 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: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" Untangle directory traversal into a simple iterator, to replace the existing multi-purpose do_fat_read_at() + get_dentfromdir(). Signed-off-by: Rob Clark Reviewed-by: Łukasz Majewski Reviewed-by: Simon Glass --- fs/fat/fat.c | 356 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- include/fat.h | 7 ++ 2 files changed, 360 insertions(+), 3 deletions(-) diff --git a/fs/fat/fat.c b/fs/fat/fat.c index e1c0a15dc7..ee2bbe38f1 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -812,7 +812,6 @@ static int get_fs_info(fsdata *mydata) { boot_sector bs; volume_info volinfo; - __u32 root_cluster = 0; int ret; ret = read_bootsectandvi(&bs, &volinfo, &mydata->fatsize); @@ -822,7 +821,6 @@ static int get_fs_info(fsdata *mydata) } if (mydata->fatsize == 32) { - root_cluster = bs.root_cluster; mydata->fatlength = bs.fat32_length; } else { mydata->fatlength = bs.fat_length; @@ -843,6 +841,7 @@ static int get_fs_info(fsdata *mydata) if (mydata->fatsize == 32) { mydata->data_begin = mydata->rootdir_sect - (mydata->clust_size * 2); + mydata->root_cluster = bs.root_cluster; } else { mydata->rootdir_size = ((bs.dir_entries[1] * (int)256 + bs.dir_entries[0]) * @@ -851,6 +850,9 @@ static int get_fs_info(fsdata *mydata) mydata->data_begin = mydata->rootdir_sect + mydata->rootdir_size - (mydata->clust_size * 2); + mydata->root_cluster = (mydata->rootdir_sect - + mydata->data_begin) / + mydata->clust_size; } mydata->fatbufnum = -1; @@ -868,7 +870,7 @@ static int get_fs_info(fsdata *mydata) mydata->fatsize, mydata->fat_sect, mydata->fatlength); debug("Rootdir begins at cluster: %d, sector: %d, offset: %x\n" "Data begins at: %d\n", - root_cluster, + mydata->root_cluster, mydata->rootdir_sect, mydata->rootdir_sect * mydata->sect_size, mydata->data_begin); debug("Sector size: %d, cluster size: %d\n", mydata->sect_size, @@ -1245,6 +1247,354 @@ exit: return ret; } + +/* + * Directory iterator, to simplify filesystem traversal + * + * Implements an iterator pattern to traverse directory tables, + * transparently handling directory tables split across multiple + * clusters, and the difference between FAT12/FAT16 root directory + * (contiguous) and subdirectories + FAT32 root (chained). + * + * Rough usage: + * + * for (fat_itr_root(&itr, fsdata); fat_itr_next(&itr); ) { + * // to traverse down to a subdirectory pointed to by + * // current iterator position: + * fat_itr_child(&itr, &itr); + * } + * + * For more complete example, see fat_itr_resolve() + */ + +typedef struct { + fsdata *fsdata; /* filesystem parameters */ + unsigned clust; /* current cluster */ + int last_cluster; /* set once we've read last cluster */ + int is_root; /* is iterator at root directory */ + int remaining; /* remaining dent's in current cluster */ + + /* current iterator position values: */ + dir_entry *dent; /* current directory entry */ + char l_name[VFAT_MAXLEN_BYTES]; /* long (vfat) name */ + char s_name[14]; /* short 8.3 name */ + char *name; /* l_name if there is one, else s_name */ + + /* storage for current cluster in memory: */ + u8 block[MAX_CLUSTSIZE] __aligned(ARCH_DMA_MINALIGN); +} fat_itr; + +static int fat_itr_isdir(fat_itr *itr); + +/** + * fat_itr_root() - initialize an iterator to start at the root + * directory + * + * @itr: iterator to initialize + * @fsdata: filesystem data for the partition + * @return 0 on success, else -errno + */ +static int fat_itr_root(fat_itr *itr, fsdata *fsdata) +{ + if (get_fs_info(fsdata)) + return -ENXIO; + + itr->fsdata = fsdata; + itr->clust = fsdata->root_cluster; + itr->dent = NULL; + itr->remaining = 0; + itr->last_cluster = 0; + itr->is_root = 1; + + return 0; +} + +/** + * fat_itr_child() - initialize an iterator to descend into a sub- + * directory + * + * Initializes 'itr' to iterate the contents of the directory at + * the current cursor position of 'parent'. It is an error to + * call this if the current cursor of 'parent' is pointing at a + * regular file. + * + * Note that 'itr' and 'parent' can be the same pointer if you do + * not need to preserve 'parent' after this call, which is useful + * for traversing directory structure to resolve a file/directory. + * + * @itr: iterator to initialize + * @parent: the iterator pointing at a directory entry in the + * parent directory of the directory to iterate + */ +static void fat_itr_child(fat_itr *itr, fat_itr *parent) +{ + fsdata *mydata = parent->fsdata; /* for silly macros */ + unsigned clustnum = START(parent->dent); + + assert(fat_itr_isdir(parent)); + + itr->fsdata = parent->fsdata; + if (clustnum > 0) { + itr->clust = clustnum; + } else { + itr->clust = parent->fsdata->root_cluster; + } + itr->dent = NULL; + itr->remaining = 0; + itr->last_cluster = 0; + itr->is_root = 0; +} + +static void *next_cluster(fat_itr *itr) +{ + fsdata *mydata = itr->fsdata; /* for silly macros */ + int ret; + u32 sect; + + /* have we reached the end? */ + if (itr->last_cluster) + return NULL; + + sect = clust_to_sect(itr->fsdata, itr->clust); + + debug("FAT read(sect=%d), clust_size=%d, DIRENTSPERBLOCK=%zd\n", + sect, itr->fsdata->clust_size, DIRENTSPERBLOCK); + + /* + * NOTE: do_fat_read_at() had complicated logic to deal w/ + * vfat names that span multiple clusters in the fat16 case, + * which get_dentfromdir() probably also needed (and was + * missing). And not entirely sure what fat32 didn't have + * the same issue.. We solve that by only caring about one + * dent at a time and iteratively constructing the vfat long + * name. + */ + ret = disk_read(sect, itr->fsdata->clust_size, + itr->block); + if (ret < 0) { + debug("Error: reading block\n"); + return NULL; + } + + if (itr->is_root && itr->fsdata->fatsize != 32) { + itr->clust++; + sect = clust_to_sect(itr->fsdata, itr->clust); + if (sect - itr->fsdata->rootdir_sect >= + itr->fsdata->rootdir_size) { + debug("cursect: 0x%x\n", itr->clust); + itr->last_cluster = 1; + } + } else { + itr->clust = get_fatent(itr->fsdata, itr->clust); + if (CHECK_CLUST(itr->clust, itr->fsdata->fatsize)) { + debug("cursect: 0x%x\n", itr->clust); + itr->last_cluster = 1; + } + } + + return itr->block; +} + +static dir_entry *next_dent(fat_itr *itr) +{ + if (itr->remaining == 0) { + struct dir_entry *dent = next_cluster(itr); + unsigned nbytes = itr->fsdata->sect_size * + itr->fsdata->clust_size; + + /* have we reached the last cluster? */ + if (!dent) + return NULL; + + itr->remaining = nbytes / sizeof(dir_entry) - 1; + itr->dent = dent; + } else { + itr->remaining--; + itr->dent++; + } + + /* have we reached the last valid entry? */ + if (itr->dent->name[0] == 0) + return NULL; + + return itr->dent; +} + +static dir_entry *extract_vfat_name(fat_itr *itr) +{ + struct dir_entry *dent = itr->dent; + int seqn = itr->dent->name[0] & ~LAST_LONG_ENTRY_MASK; + u8 chksum, alias_checksum = ((dir_slot *)dent)->alias_checksum; + int n = 0; + + while (seqn--) { + char buf[13]; + int idx = 0; + + slot2str((dir_slot *)dent, buf, &idx); + + /* shift accumulated long-name up and copy new part in: */ + memmove(itr->l_name + idx, itr->l_name, n); + memcpy(itr->l_name, buf, idx); + n += idx; + + dent = next_dent(itr); + if (!dent) + return NULL; + } + + itr->l_name[n] = '\0'; + + chksum = mkcksum(dent->name, dent->ext); + + /* checksum mismatch could mean deleted file, etc.. skip it: */ + if (chksum != alias_checksum) { + debug("** chksum=%x, alias_checksum=%x, l_name=%s, s_name=%8s.%3s\n", + chksum, alias_checksum, itr->l_name, dent->name, dent->ext); + return NULL; + } + + return dent; +} + +/** + * fat_itr_next() - step to the next entry in a directory + * + * Must be called once on a new iterator before the cursor is valid. + * + * @itr: the iterator to iterate + * @return boolean, 1 if success or 0 if no more entries in the + * current directory + */ +static int fat_itr_next(fat_itr *itr) +{ + dir_entry *dent; + + itr->name = NULL; + + while (1) { + dent = next_dent(itr); + if (!dent) + return 0; + + if (dent->name[0] == DELETED_FLAG || + dent->name[0] == aRING) + continue; + + if (dent->attr & ATTR_VOLUME) { + if (vfat_enabled && + (dent->attr & ATTR_VFAT) == ATTR_VFAT && + (dent->name[0] & LAST_LONG_ENTRY_MASK)) { + dent = extract_vfat_name(itr); + if (!dent) + continue; + itr->name = itr->l_name; + break; + } else { + /* Volume label or VFAT entry, skip */ + continue; + } + } + + break; + } + + get_name(dent, itr->s_name); + if (!itr->name) + itr->name = itr->s_name; + + return 1; +} + +/** + * fat_itr_isdir() - is current cursor position pointing to a directory + * + * @itr: the iterator + * @return true if cursor is at a directory + */ +static int fat_itr_isdir(fat_itr *itr) +{ + return !!(itr->dent->attr & ATTR_DIR); +} + +/* + * Helpers: + */ + +#define TYPE_FILE 0x1 +#define TYPE_DIR 0x2 +#define TYPE_ANY (TYPE_FILE | TYPE_DIR) + +/** + * fat_itr_resolve() - traverse directory structure to resolve the + * requested path. + * + * Traverse directory structure to the requested path. If the specified + * path is to a directory, this will descend into the directory and + * leave it iterator at the start of the directory. If the path is to a + * file, it will leave the iterator in the parent directory with current + * cursor at file's entry in the directory. + * + * @itr: iterator initialized to root + * @path: the requested path + * @type: bitmask of allowable file types + * @return 0 on success or -errno + */ +static int fat_itr_resolve(fat_itr *itr, const char *path, unsigned type) +{ + const char *next; + + /* chomp any extra leading slashes: */ + while (path[0] && ISDIRDELIM(path[0])) + path++; + + /* are we at the end? */ + if (strlen(path) == 0) { + if (!(type & TYPE_DIR)) + return -ENOENT; + return 0; + } + + /* find length of next path entry: */ + next = path; + while (next[0] && !ISDIRDELIM(next[0])) + next++; + + while (fat_itr_next(itr)) { + int match = 0; + unsigned n = max(strlen(itr->name), (size_t)(next - path)); + + /* check both long and short name: */ + if (!strncasecmp(path, itr->name, n)) + match = 1; + else if (itr->name != itr->s_name && + !strncasecmp(path, itr->s_name, n)) + match = 1; + + if (!match) + continue; + + if (fat_itr_isdir(itr)) { + /* recurse into directory: */ + fat_itr_child(itr, itr); + return fat_itr_resolve(itr, next, type); + } else if (next[0]) { + /* + * If next is not empty then we have a case + * like: /path/to/realfile/nonsense + */ + debug("bad trailing path: %s\n", next); + return -ENOENT; + } else if (!(type & TYPE_FILE)) { + return -ENOTDIR; + } else { + return 0; + } + } + + return -ENOENT; +} + int do_fat_read(const char *filename, void *buffer, loff_t maxsize, int dols, loff_t *actread) { diff --git a/include/fat.h b/include/fat.h index b671ee8f81..21bb6666cf 100644 --- a/include/fat.h +++ b/include/fat.h @@ -175,8 +175,15 @@ typedef struct { int data_begin; /* The sector of the first cluster, can be negative */ int fatbufnum; /* Used by get_fatent, init to -1 */ int rootdir_size; /* Size of root dir for non-FAT32 */ + __u32 root_cluster; /* First cluster of root dir for FAT32 */ } fsdata; +/* TODO clean up places that are open-coding this: */ +static inline u32 clust_to_sect(fsdata *fsdata, u32 clust) +{ + return fsdata->data_begin + clust * fsdata->clust_size; +} + typedef int (file_detectfs_func)(void); typedef int (file_ls_func)(const char *dir); typedef int (file_read_func)(const char *filename, void *buffer, From patchwork Sun Sep 10 11:21:23 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Rob Clark X-Patchwork-Id: 812101 X-Patchwork-Delegate: trini@ti.com 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="cgAgwt20"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3xqpf242Jqz9s8J for ; Sun, 10 Sep 2017 21:26:02 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 5042DC21C4C; Sun, 10 Sep 2017 11:23:45 +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 C8A7AC21F1A; Sun, 10 Sep 2017 11:23:08 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 58FB0C21EDB; Sun, 10 Sep 2017 11:22:29 +0000 (UTC) Received: from mail-qt0-f194.google.com (mail-qt0-f194.google.com [209.85.216.194]) by lists.denx.de (Postfix) with ESMTPS id D7BC7C21DEF for ; Sun, 10 Sep 2017 11:22:24 +0000 (UTC) Received: by mail-qt0-f194.google.com with SMTP id l25so1177091qtf.2 for ; Sun, 10 Sep 2017 04:22:24 -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 :mime-version:content-transfer-encoding; bh=rBXu5viO0nx6ilNLUFtFtvPu5flOKRAP0NAR3BsKh8w=; b=cgAgwt20AY67gBPkwsGSvJ70itcuf5wQB67zgJgV6KeQ366twZtyi2yKo63Nr+Waxd TiuZ8SVJvYSMsvevGaJZwg/7tdWcqGRN3IuCeg8pXyfc7YWkox6Q7k7PYn183UDxsduv Im0FfdWfbHnDoh3iSbuLgClRKO6Ee5JT8HBsKgBA/j8oI6T/Jt3OIGIDppbrlBz3Sld4 dZcHHVUiCQmtGa7pKTTAIAaT2jUSslkPJNQnpdzYAJ8WDdUook5MRue/sWO1n1HwPLEK hjpu0Z3urn37+GEcCiCcaBeQiBeUIzd1R/copDYk58zKxMlFRgEL/FBgjEcOEmHleDvt BP0w== 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:mime-version:content-transfer-encoding; bh=rBXu5viO0nx6ilNLUFtFtvPu5flOKRAP0NAR3BsKh8w=; b=WXmbAiZLH/3i5RJN/or7Up7AignJ+6+PeffschqHS26efbAELU/KS+VYYPwuml4L1U bTZmRGcK7rh5EAcJXws/Poxh0IZ+AdmBrQkXovc55zqq5ZCAUlCmc0GzgnDZIK039fpQ 2gjZkaXOMKOQCKTJZrhIojOONahoYuz+/X4Fwi9t5VGDKCJtc8PUzRthyMAX5ZMU9mdN BwHJDmBs7UMjLfMc4F3RzVJQUwlKG2qkXFBso4NEdl7n/7SGypVn6HopChKx35KWm1yD cizkEOSAhS+CDSKuhOMrkLRyFiIEzB/kLdZAnZhl6TLFzLatrSuRK/tm63Io8GGwz7cZ d/YA== X-Gm-Message-State: AHPjjUiQsZjNEpYQq1JSamMjDjYp5rShrcZbOFcvliNA1oKJidMs7Wlf 5Okldjaa1t1J4KkeDf0= X-Google-Smtp-Source: AOwi7QASYkmVzixcAXFUqavTp2keWY582i6eOt9BGiQg1g5pvesh1iC6AmK13ZexC2BkfPz1h1sPTw== X-Received: by 10.200.14.4 with SMTP id a4mr11324162qti.1.1505042543433; Sun, 10 Sep 2017 04:22:23 -0700 (PDT) Received: from localhost ([2601:184:4780:aac0:25f8:dd96:a084:785a]) by smtp.gmail.com with ESMTPSA id s16sm4348897qks.63.2017.09.10.04.22.22 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sun, 10 Sep 2017 04:22:22 -0700 (PDT) From: Rob Clark To: U-Boot Mailing List Date: Sun, 10 Sep 2017 07:21:23 -0400 Message-Id: <20170910112149.21358-7-robdclark@gmail.com> X-Mailer: git-send-email 2.13.5 In-Reply-To: <20170910112149.21358-1-robdclark@gmail.com> References: <20170910112149.21358-1-robdclark@gmail.com> MIME-Version: 1.0 Cc: Heinrich Schuchardt , Genevieve Chan , Tien Fong Chee Subject: [U-Boot] [PATCH v3 3/9] fat/fs: convert to directory iterators 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: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" And drop a whole lot of ugly code! Signed-off-by: Rob Clark Reviewed-by: Łukasz Majewski --- fs/fat/fat.c | 722 +++++++--------------------------------------------------- include/fat.h | 6 - 2 files changed, 76 insertions(+), 652 deletions(-) diff --git a/fs/fat/fat.c b/fs/fat/fat.c index ee2bbe38f1..bbba7947ee 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -119,22 +119,6 @@ int fat_register_device(struct blk_desc *dev_desc, int part_no) } /* - * Get the first occurence of a directory delimiter ('/' or '\') in a string. - * Return index into string if found, -1 otherwise. - */ -static int dirdelim(char *str) -{ - char *start = str; - - while (*str != '\0') { - if (ISDIRDELIM(*str)) - return str - start; - str++; - } - return -1; -} - -/* * Extract zero terminated short name from a directory entry. */ static void get_name(dir_entry *dirent, char *s_name) @@ -468,95 +452,6 @@ static int slot2str(dir_slot *slotptr, char *l_name, int *idx) return 0; } -/* - * Extract the full long filename starting at 'retdent' (which is really - * a slot) into 'l_name'. If successful also copy the real directory entry - * into 'retdent' - * Return 0 on success, -1 otherwise. - */ -static int -get_vfatname(fsdata *mydata, int curclust, __u8 *cluster, - dir_entry *retdent, char *l_name) -{ - dir_entry *realdent; - dir_slot *slotptr = (dir_slot *)retdent; - __u8 *buflimit = cluster + mydata->sect_size * ((curclust == 0) ? - PREFETCH_BLOCKS : - mydata->clust_size); - __u8 counter = (slotptr->id & ~LAST_LONG_ENTRY_MASK) & 0xff; - int idx = 0; - - if (counter > VFAT_MAXSEQ) { - debug("Error: VFAT name is too long\n"); - return -1; - } - - while ((__u8 *)slotptr < buflimit) { - if (counter == 0) - break; - if (((slotptr->id & ~LAST_LONG_ENTRY_MASK) & 0xff) != counter) - return -1; - slotptr++; - counter--; - } - - if ((__u8 *)slotptr >= buflimit) { - dir_slot *slotptr2; - - if (curclust == 0) - return -1; - curclust = get_fatent(mydata, curclust); - if (CHECK_CLUST(curclust, mydata->fatsize)) { - debug("curclust: 0x%x\n", curclust); - printf("Invalid FAT entry\n"); - return -1; - } - - if (get_cluster(mydata, curclust, get_contents_vfatname_block, - mydata->clust_size * mydata->sect_size) != 0) { - debug("Error: reading directory block\n"); - return -1; - } - - slotptr2 = (dir_slot *)get_contents_vfatname_block; - while (counter > 0) { - if (((slotptr2->id & ~LAST_LONG_ENTRY_MASK) - & 0xff) != counter) - return -1; - slotptr2++; - counter--; - } - - /* Save the real directory entry */ - realdent = (dir_entry *)slotptr2; - while ((__u8 *)slotptr2 > get_contents_vfatname_block) { - slotptr2--; - slot2str(slotptr2, l_name, &idx); - } - } else { - /* Save the real directory entry */ - realdent = (dir_entry *)slotptr; - } - - do { - slotptr--; - if (slot2str(slotptr, l_name, &idx)) - break; - } while (!(slotptr->id & LAST_LONG_ENTRY_MASK)); - - l_name[idx] = '\0'; - if (*l_name == DELETED_FLAG) - *l_name = '\0'; - else if (*l_name == aRING) - *l_name = DELETED_FLAG; - downcase(l_name); - - /* Return the real directory entry */ - memcpy(retdent, realdent, sizeof(dir_entry)); - - return 0; -} - /* Calculate short name checksum */ static __u8 mkcksum(const char name[8], const char ext[3]) { @@ -573,169 +468,13 @@ static __u8 mkcksum(const char name[8], const char ext[3]) } /* - * Get the directory entry associated with 'filename' from the directory - * starting at 'startsect' + * TODO these should go away once fat_write is reworked to use the + * directory iterator */ __u8 get_dentfromdir_block[MAX_CLUSTSIZE] __aligned(ARCH_DMA_MINALIGN); - -static dir_entry *get_dentfromdir(fsdata *mydata, int startsect, - char *filename, dir_entry *retdent, - int dols) -{ - __u16 prevcksum = 0xffff; - __u32 curclust = START(retdent); - int files = 0, dirs = 0; - - debug("get_dentfromdir: %s\n", filename); - - while (1) { - dir_entry *dentptr; - - int i; - - if (get_cluster(mydata, curclust, get_dentfromdir_block, - mydata->clust_size * mydata->sect_size) != 0) { - debug("Error: reading directory block\n"); - return NULL; - } - - dentptr = (dir_entry *)get_dentfromdir_block; - - for (i = 0; i < DIRENTSPERCLUST; i++) { - char s_name[14], l_name[VFAT_MAXLEN_BYTES]; - - l_name[0] = '\0'; - if (dentptr->name[0] == DELETED_FLAG) { - dentptr++; - continue; - } - if ((dentptr->attr & ATTR_VOLUME)) { - if (vfat_enabled && - (dentptr->attr & ATTR_VFAT) == ATTR_VFAT && - (dentptr->name[0] & LAST_LONG_ENTRY_MASK)) { - prevcksum = ((dir_slot *)dentptr)->alias_checksum; - get_vfatname(mydata, curclust, - get_dentfromdir_block, - dentptr, l_name); - if (dols) { - int isdir; - char dirc; - int doit = 0; - - isdir = (dentptr->attr & ATTR_DIR); - - if (isdir) { - dirs++; - dirc = '/'; - doit = 1; - } else { - dirc = ' '; - if (l_name[0] != 0) { - files++; - doit = 1; - } - } - if (doit) { - if (dirc == ' ') { - printf(" %8u %s%c\n", - FAT2CPU32(dentptr->size), - l_name, - dirc); - } else { - printf(" %s%c\n", - l_name, - dirc); - } - } - dentptr++; - continue; - } - debug("vfatname: |%s|\n", l_name); - } else { - /* Volume label or VFAT entry */ - dentptr++; - continue; - } - } - if (dentptr->name[0] == 0) { - if (dols) { - printf("\n%d file(s), %d dir(s)\n\n", - files, dirs); - } - debug("Dentname == NULL - %d\n", i); - return NULL; - } - if (vfat_enabled) { - __u8 csum = mkcksum(dentptr->name, dentptr->ext); - if (dols && csum == prevcksum) { - prevcksum = 0xffff; - dentptr++; - continue; - } - } - - get_name(dentptr, s_name); - if (dols) { - int isdir = (dentptr->attr & ATTR_DIR); - char dirc; - int doit = 0; - - if (isdir) { - dirs++; - dirc = '/'; - doit = 1; - } else { - dirc = ' '; - if (s_name[0] != 0) { - files++; - doit = 1; - } - } - - if (doit) { - if (dirc == ' ') { - printf(" %8u %s%c\n", - FAT2CPU32(dentptr->size), - s_name, dirc); - } else { - printf(" %s%c\n", - s_name, dirc); - } - } - - dentptr++; - continue; - } - - if (strcmp(filename, s_name) - && strcmp(filename, l_name)) { - debug("Mismatch: |%s|%s|\n", s_name, l_name); - dentptr++; - continue; - } - - memcpy(retdent, dentptr, sizeof(dir_entry)); - - debug("DentName: %s", s_name); - debug(", start: 0x%x", START(dentptr)); - debug(", size: 0x%x %s\n", - FAT2CPU32(dentptr->size), - (dentptr->attr & ATTR_DIR) ? "(DIR)" : ""); - - return retdent; - } - - curclust = get_fatent(mydata, curclust); - if (CHECK_CLUST(curclust, mydata->fatsize)) { - debug("curclust: 0x%x\n", curclust); - printf("Invalid FAT entry\n"); - return NULL; - } - } - - return NULL; -} +__u8 do_fat_read_at_block[MAX_CLUSTSIZE] + __aligned(ARCH_DMA_MINALIGN); /* * Read boot sector and volume info from a FAT filesystem @@ -879,374 +618,6 @@ static int get_fs_info(fsdata *mydata) return 0; } -__u8 do_fat_read_at_block[MAX_CLUSTSIZE] - __aligned(ARCH_DMA_MINALIGN); - -int do_fat_read_at(const char *filename, loff_t pos, void *buffer, - loff_t maxsize, int dols, int dogetsize, loff_t *size) -{ - char fnamecopy[2048]; - fsdata datablock; - fsdata *mydata = &datablock; - dir_entry *dentptr = NULL; - __u16 prevcksum = 0xffff; - char *subname = ""; - __u32 cursect; - int idx, isdir = 0; - int files = 0, dirs = 0; - int ret = -1; - int firsttime; - __u32 root_cluster = 0; - __u32 read_blk; - int rootdir_size = 0; - int buffer_blk_cnt; - int do_read; - __u8 *dir_ptr; - - if (get_fs_info(mydata)) - return -1; - - cursect = mydata->rootdir_sect; - - /* "cwd" is always the root... */ - while (ISDIRDELIM(*filename)) - filename++; - - /* Make a copy of the filename and convert it to lowercase */ - strcpy(fnamecopy, filename); - downcase(fnamecopy); - -root_reparse: - if (*fnamecopy == '\0') { - if (!dols) - goto exit; - - dols = LS_ROOT; - } else if ((idx = dirdelim(fnamecopy)) >= 0) { - isdir = 1; - fnamecopy[idx] = '\0'; - subname = fnamecopy + idx + 1; - - /* Handle multiple delimiters */ - while (ISDIRDELIM(*subname)) - subname++; - } else if (dols) { - isdir = 1; - } - - buffer_blk_cnt = 0; - firsttime = 1; - while (1) { - int i; - - if (mydata->fatsize == 32 || firsttime) { - dir_ptr = do_fat_read_at_block; - firsttime = 0; - } else { - /** - * FAT16 sector buffer modification: - * Each loop, the second buffered block is moved to - * the buffer begin, and two next sectors are read - * next to the previously moved one. So the sector - * buffer keeps always 3 sectors for fat16. - * And the current sector is the buffer second sector - * beside the "firsttime" read, when it is the first one. - * - * PREFETCH_BLOCKS is 2 for FAT16 == loop[0:1] - * n = computed root dir sector - * loop | cursect-1 | cursect | cursect+1 | - * 0 | sector n+0 | sector n+1 | none | - * 1 | none | sector n+0 | sector n+1 | - * 0 | sector n+1 | sector n+2 | sector n+3 | - * 1 | sector n+3 | ... - */ - dir_ptr = (do_fat_read_at_block + mydata->sect_size); - memcpy(do_fat_read_at_block, dir_ptr, mydata->sect_size); - } - - do_read = 1; - - if (mydata->fatsize == 32 && buffer_blk_cnt) - do_read = 0; - - if (do_read) { - read_blk = (mydata->fatsize == 32) ? - mydata->clust_size : PREFETCH_BLOCKS; - - debug("FAT read(sect=%d, cnt:%d), clust_size=%d, DIRENTSPERBLOCK=%zd\n", - cursect, read_blk, mydata->clust_size, DIRENTSPERBLOCK); - - if (disk_read(cursect, read_blk, dir_ptr) < 0) { - debug("Error: reading rootdir block\n"); - goto exit; - } - - dentptr = (dir_entry *)dir_ptr; - } - - for (i = 0; i < DIRENTSPERBLOCK; i++) { - char s_name[14], l_name[VFAT_MAXLEN_BYTES]; - __u8 csum; - - l_name[0] = '\0'; - if (dentptr->name[0] == DELETED_FLAG) { - dentptr++; - continue; - } - - if (vfat_enabled) - csum = mkcksum(dentptr->name, dentptr->ext); - - if (dentptr->attr & ATTR_VOLUME) { - if (vfat_enabled && - (dentptr->attr & ATTR_VFAT) == ATTR_VFAT && - (dentptr->name[0] & LAST_LONG_ENTRY_MASK)) { - prevcksum = - ((dir_slot *)dentptr)->alias_checksum; - - get_vfatname(mydata, - root_cluster, - dir_ptr, - dentptr, l_name); - - if (dols == LS_ROOT) { - char dirc; - int doit = 0; - int isdir = - (dentptr->attr & ATTR_DIR); - - if (isdir) { - dirs++; - dirc = '/'; - doit = 1; - } else { - dirc = ' '; - if (l_name[0] != 0) { - files++; - doit = 1; - } - } - if (doit) { - if (dirc == ' ') { - printf(" %8u %s%c\n", - FAT2CPU32(dentptr->size), - l_name, - dirc); - } else { - printf(" %s%c\n", - l_name, - dirc); - } - } - dentptr++; - continue; - } - debug("Rootvfatname: |%s|\n", - l_name); - } else { - /* Volume label or VFAT entry */ - dentptr++; - continue; - } - } else if (dentptr->name[0] == 0) { - debug("RootDentname == NULL - %d\n", i); - if (dols == LS_ROOT) { - printf("\n%d file(s), %d dir(s)\n\n", - files, dirs); - ret = 0; - } - goto exit; - } - else if (vfat_enabled && - dols == LS_ROOT && csum == prevcksum) { - prevcksum = 0xffff; - dentptr++; - continue; - } - - get_name(dentptr, s_name); - - if (dols == LS_ROOT) { - int isdir = (dentptr->attr & ATTR_DIR); - char dirc; - int doit = 0; - - if (isdir) { - dirc = '/'; - if (s_name[0] != 0) { - dirs++; - doit = 1; - } - } else { - dirc = ' '; - if (s_name[0] != 0) { - files++; - doit = 1; - } - } - if (doit) { - if (dirc == ' ') { - printf(" %8u %s%c\n", - FAT2CPU32(dentptr->size), - s_name, dirc); - } else { - printf(" %s%c\n", - s_name, dirc); - } - } - dentptr++; - continue; - } - - if (strcmp(fnamecopy, s_name) - && strcmp(fnamecopy, l_name)) { - debug("RootMismatch: |%s|%s|\n", s_name, - l_name); - dentptr++; - continue; - } - - if (isdir && !(dentptr->attr & ATTR_DIR)) - goto exit; - - debug("RootName: %s", s_name); - debug(", start: 0x%x", START(dentptr)); - debug(", size: 0x%x %s\n", - FAT2CPU32(dentptr->size), - isdir ? "(DIR)" : ""); - - goto rootdir_done; /* We got a match */ - } - debug("END LOOP: buffer_blk_cnt=%d clust_size=%d\n", buffer_blk_cnt, - mydata->clust_size); - - /* - * On FAT32 we must fetch the FAT entries for the next - * root directory clusters when a cluster has been - * completely processed. - */ - ++buffer_blk_cnt; - int rootdir_end = 0; - if (mydata->fatsize == 32) { - if (buffer_blk_cnt == mydata->clust_size) { - int nxtsect = 0; - int nxt_clust = 0; - - nxt_clust = get_fatent(mydata, root_cluster); - rootdir_end = CHECK_CLUST(nxt_clust, 32); - - nxtsect = mydata->data_begin + - (nxt_clust * mydata->clust_size); - - root_cluster = nxt_clust; - - cursect = nxtsect; - buffer_blk_cnt = 0; - } - } else { - if (buffer_blk_cnt == PREFETCH_BLOCKS) - buffer_blk_cnt = 0; - - rootdir_end = (++cursect - mydata->rootdir_sect >= - rootdir_size); - } - - /* If end of rootdir reached */ - if (rootdir_end) { - if (dols == LS_ROOT) { - printf("\n%d file(s), %d dir(s)\n\n", - files, dirs); - *size = 0; - } - goto exit; - } - } -rootdir_done: - - firsttime = 1; - - while (isdir) { - int startsect = mydata->data_begin - + START(dentptr) * mydata->clust_size; - dir_entry dent; - char *nextname = NULL; - - dent = *dentptr; - dentptr = &dent; - - idx = dirdelim(subname); - - if (idx >= 0) { - subname[idx] = '\0'; - nextname = subname + idx + 1; - /* Handle multiple delimiters */ - while (ISDIRDELIM(*nextname)) - nextname++; - if (dols && *nextname == '\0') - firsttime = 0; - } else { - if (dols && firsttime) { - firsttime = 0; - } else { - isdir = 0; - } - } - - if (get_dentfromdir(mydata, startsect, subname, dentptr, - isdir ? 0 : dols) == NULL) { - if (dols && !isdir) - *size = 0; - goto exit; - } - - if (isdir && !(dentptr->attr & ATTR_DIR)) - goto exit; - - /* - * If we are looking for a directory, and found a directory - * type entry, and the entry is for the root directory (as - * denoted by a cluster number of 0), jump back to the start - * of the function, since at least on FAT12/16, the root dir - * lives in a hard-coded location and needs special handling - * to parse, rather than simply following the cluster linked - * list in the FAT, like other directories. - */ - if (isdir && (dentptr->attr & ATTR_DIR) && !START(dentptr)) { - /* - * Modify the filename to remove the prefix that gets - * back to the root directory, so the initial root dir - * parsing code can continue from where we are without - * confusion. - */ - strcpy(fnamecopy, nextname ?: ""); - /* - * Set up state the same way as the function does when - * first started. This is required for the root dir - * parsing code operates in its expected environment. - */ - subname = ""; - cursect = mydata->rootdir_sect; - isdir = 0; - goto root_reparse; - } - - if (idx >= 0) - subname = nextname; - } - - if (dogetsize) { - *size = FAT2CPU32(dentptr->size); - ret = 0; - } else { - ret = get_contents(mydata, dentptr, pos, buffer, maxsize, size); - } - debug("Size: %u, got: %llu\n", FAT2CPU32(dentptr->size), *size); - -exit: - free(mydata->fatbuf); - return ret; -} - /* * Directory iterator, to simplify filesystem traversal @@ -1595,12 +966,6 @@ static int fat_itr_resolve(fat_itr *itr, const char *path, unsigned type) return -ENOENT; } -int do_fat_read(const char *filename, void *buffer, loff_t maxsize, int dols, - loff_t *actread) -{ - return do_fat_read_at(filename, 0, buffer, maxsize, dols, 0, actread); -} - int file_fat_detectfs(void) { boot_sector bs; @@ -1665,31 +1030,96 @@ int file_fat_detectfs(void) int file_fat_ls(const char *dir) { - loff_t size; + fsdata fsdata; + fat_itr itrblock, *itr = &itrblock; + int files = 0, dirs = 0; + int ret; + + ret = fat_itr_root(itr, &fsdata); + if (ret) + return ret; + + ret = fat_itr_resolve(itr, dir, TYPE_DIR); + if (ret) + return ret; + + while (fat_itr_next(itr)) { + if (fat_itr_isdir(itr)) { + printf(" %s/\n", itr->name); + dirs++; + } else { + printf(" %8u %s\n", + FAT2CPU32(itr->dent->size), + itr->name); + files++; + } + } - return do_fat_read(dir, NULL, 0, LS_YES, &size); + printf("\n%d file(s), %d dir(s)\n\n", files, dirs); + + return 0; } int fat_exists(const char *filename) { + fsdata fsdata; + fat_itr itrblock, *itr = &itrblock; int ret; - loff_t size; - ret = do_fat_read_at(filename, 0, NULL, 0, LS_NO, 1, &size); + ret = fat_itr_root(itr, &fsdata); + if (ret) + return 0; + + ret = fat_itr_resolve(itr, filename, TYPE_ANY); return ret == 0; } int fat_size(const char *filename, loff_t *size) { - return do_fat_read_at(filename, 0, NULL, 0, LS_NO, 1, size); + fsdata fsdata; + fat_itr itrblock, *itr = &itrblock; + int ret; + + ret = fat_itr_root(itr, &fsdata); + if (ret) + return ret; + + ret = fat_itr_resolve(itr, filename, TYPE_FILE); + if (ret) { + /* + * Directories don't have size, but fs_size() is not + * expected to fail if passed a directory path: + */ + fat_itr_root(itr, &fsdata); + if (!fat_itr_resolve(itr, filename, TYPE_DIR)) { + *size = 0; + return 0; + } + return ret; + } + + *size = FAT2CPU32(itr->dent->size); + + return 0; } int file_fat_read_at(const char *filename, loff_t pos, void *buffer, loff_t maxsize, loff_t *actread) { + fsdata fsdata; + fat_itr itrblock, *itr = &itrblock; + int ret; + + ret = fat_itr_root(itr, &fsdata); + if (ret) + return ret; + + ret = fat_itr_resolve(itr, filename, TYPE_FILE); + if (ret) + return ret; + printf("reading %s\n", filename); - return do_fat_read_at(filename, pos, buffer, maxsize, LS_NO, 0, - actread); + return get_contents(&fsdata, itr->dent, pos, buffer, maxsize, actread); } int file_fat_read(const char *filename, void *buffer, int maxsize) diff --git a/include/fat.h b/include/fat.h index 21bb6666cf..18d8981c48 100644 --- a/include/fat.h +++ b/include/fat.h @@ -58,12 +58,6 @@ */ #define LAST_LONG_ENTRY_MASK 0x40 -/* Flags telling whether we should read a file or list a directory */ -#define LS_NO 0 -#define LS_YES 1 -#define LS_DIR 1 -#define LS_ROOT 2 - #define ISDIRDELIM(c) ((c) == '/' || (c) == '\\') #define FSTYPE_NONE (-1) From patchwork Sun Sep 10 11:21:24 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Clark X-Patchwork-Id: 812099 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="O+Vl5MN/"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3xqpcv0nZ5z9sDB for ; Sun, 10 Sep 2017 21:25:03 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id C3D02C21EA9; Sun, 10 Sep 2017 11:24:21 +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 AC8D5C21F1D; Sun, 10 Sep 2017 11:23:12 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 2C7E6C21E7C; Sun, 10 Sep 2017 11:22:31 +0000 (UTC) Received: from mail-qk0-f195.google.com (mail-qk0-f195.google.com [209.85.220.195]) by lists.denx.de (Postfix) with ESMTPS id E6037C21EBF for ; Sun, 10 Sep 2017 11:22:27 +0000 (UTC) Received: by mail-qk0-f195.google.com with SMTP id g128so3987492qke.0 for ; Sun, 10 Sep 2017 04:22:27 -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=0HLerYTmPnGMALX7+280qm7VekjKZjPCzmGTASJHnXA=; b=O+Vl5MN/jyb/kvZr4jxYQsw3FkG0LElVmXyoJe9IuoM+jqvHEWFMfr5dK2CxuBayXD +u0lMWBOstRKMRklp9vCIE4K6ojaXl31jwnIfrisKy8tPsYlARNa1qtziSvy12wyBWI1 q1bD1N5Yob7UYbPDEZzZgBbJQBd8ZvK9RKNOlhs6HcRu8N/qnYmnxfhUVFfECi1nZiP+ S2FaYzqWA/lqn6qzdTpzl3MgX09S148iaW2HHtrmPUwXbjgdLEET2+OcDQXkDj8/yNse OHvUzo8QHpS7uqsMgYg+RYsZx6gWkjOWAlqtuq2d3+p4Laa7q6H+9JrxOwR2QJM4KzLP /5RQ== 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=0HLerYTmPnGMALX7+280qm7VekjKZjPCzmGTASJHnXA=; b=VCSE5/JMAfyVrsKPVU7iQ6uVwYAHAbAdLbB4yfcMeDY2z56R0JHWZV3Ot7+E4Q9Ml7 vuj0p3PyUlHEQcSwz0qBXeVV49HmfuAz00czNdXqGnzddu7K5tFJf0Tt4JaJjN3udmsh mQ/EK3TrwK4GIU+Y0Ok7O5FTt8xaiQ12TuyKDi8iKHxh9Fs8mZMWkX4IZAvsePhV6Icv 4QT9NZdlahl4yBMb8412LP/Aw2O7oKEB4MhKdnyvXzNGRwgHr7vgvzZ6Gu3waH0nKwm2 IM81Kyb6u1/QLqCDEKuYaLQXhnkCn4GuiqzA9BsSgmGxmNoJKEeMnyPttOf8IlVK2iph 5sdA== X-Gm-Message-State: AHPjjUh8IOGjaRMBREAzETuvbEVsBhoM7mtEgFLrrnDmdXzMSB4H4j1K 8z/tGSUkOC58HMssYN0= X-Google-Smtp-Source: ADKCNb4xhOZ2FBK0J/kc7ay9aEaJtWxf7QEc8o4GrKdMWYjriWL++2zZ1jzpuw/mXtBOEMB8u+43aQ== X-Received: by 10.55.93.67 with SMTP id r64mr10633058qkb.358.1505042546674; Sun, 10 Sep 2017 04:22:26 -0700 (PDT) Received: from localhost ([2601:184:4780:aac0:25f8:dd96:a084:785a]) by smtp.gmail.com with ESMTPSA id o190sm4261175qke.59.2017.09.10.04.22.25 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sun, 10 Sep 2017 04:22:25 -0700 (PDT) From: Rob Clark To: U-Boot Mailing List Date: Sun, 10 Sep 2017 07:21:24 -0400 Message-Id: <20170910112149.21358-8-robdclark@gmail.com> X-Mailer: git-send-email 2.13.5 In-Reply-To: <20170910112149.21358-1-robdclark@gmail.com> References: <20170910112149.21358-1-robdclark@gmail.com> Cc: Heinrich Schuchardt , Peter Jones Subject: [U-Boot] [PATCH v2 04/21] efi: add some more device path structures 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" From: Peter Jones Signed-off-by: Peter Jones Signed-off-by: Rob Clark Reviewed-by: Simon Glass --- include/efi_api.h | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/include/efi_api.h b/include/efi_api.h index 175341348e..b761cf4822 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -290,8 +290,38 @@ struct efi_mac_addr { u8 addr[32]; } __packed; +#define DEVICE_PATH_TYPE_HARDWARE_DEVICE 0x01 +# define DEVICE_PATH_SUB_TYPE_VENDOR 0x04 + +struct efi_device_path_vendor { + struct efi_device_path dp; + efi_guid_t guid; + u8 vendor_data[]; +} __packed; + +#define DEVICE_PATH_TYPE_ACPI_DEVICE 0x02 +# define DEVICE_PATH_SUB_TYPE_ACPI_DEVICE 0x01 + +#define EFI_PNP_ID(ID) (u32)(((ID) << 16) | 0x41D0) +#define EISA_PNP_ID(ID) EFI_PNP_ID(ID) + +struct efi_device_path_acpi_path { + struct efi_device_path dp; + u32 hid; + u32 uid; +} __packed; + #define DEVICE_PATH_TYPE_MESSAGING_DEVICE 0x03 +# define DEVICE_PATH_SUB_TYPE_MSG_USB 0x05 # define DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR 0x0b +# define DEVICE_PATH_SUB_TYPE_MSG_SD 0x1a +# define DEVICE_PATH_SUB_TYPE_MSG_MMC 0x1d + +struct efi_device_path_usb { + struct efi_device_path dp; + u8 parent_port_number; + u8 usb_interface; +} __packed; struct efi_device_path_mac_addr { struct efi_device_path dp; @@ -299,9 +329,33 @@ struct efi_device_path_mac_addr { u8 if_type; } __packed; +struct efi_device_path_sd_mmc_path { + struct efi_device_path dp; + u8 slot_number; +} __packed; + #define DEVICE_PATH_TYPE_MEDIA_DEVICE 0x04 +# define DEVICE_PATH_SUB_TYPE_HARD_DRIVE_PATH 0x01 +# define DEVICE_PATH_SUB_TYPE_CDROM_PATH 0x02 # define DEVICE_PATH_SUB_TYPE_FILE_PATH 0x04 +struct efi_device_path_hard_drive_path { + struct efi_device_path dp; + u32 partition_number; + u64 partition_start; + u64 partition_end; + u8 partition_signature[16]; + u8 partmap_type; + u8 signature_type; +} __packed; + +struct efi_device_path_cdrom_path { + struct efi_device_path dp; + u32 boot_entry; + u64 partition_start; + u64 partition_end; +} __packed; + struct efi_device_path_file_path { struct efi_device_path dp; u16 str[32]; From patchwork Sun Sep 10 11:21:26 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Clark X-Patchwork-Id: 812106 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="ajSAVxHy"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3xqpkY4M4yz9sDB for ; Sun, 10 Sep 2017 21:29:57 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 3A6B6C21E8C; Sun, 10 Sep 2017 11:27:31 +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 CD5E1C21DDF; Sun, 10 Sep 2017 11:24:44 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 786A9C21EFC; Sun, 10 Sep 2017 11:22:41 +0000 (UTC) Received: from mail-qk0-f195.google.com (mail-qk0-f195.google.com [209.85.220.195]) by lists.denx.de (Postfix) with ESMTPS id 1E92FC21C4C for ; Sun, 10 Sep 2017 11:22:37 +0000 (UTC) Received: by mail-qk0-f195.google.com with SMTP id d70so3977602qkc.1 for ; Sun, 10 Sep 2017 04:22:37 -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=6tVjFEhkD+n/lPFRMHZEy/F0zK8ykCSr4pMVfxeeooI=; b=ajSAVxHy1IA+q48hQ9qM+e7hefrMZeJf6YXvsRPv5q3aeqVT3nqGldggOPKz8Ls/iG Y3hWLIlNiJmMZbL1IcJfxd+DVthUL6Wm2O8Yh1lSHca4hhYdtu9oSxFomkMw+cU94Rvm LuV7aUtEnC5xKM9o2iWym6B8asqCoMaVHf+8Zximu+2j/SEyKMiIh6GA9Ev/8pAlj56C wA4HsoxMKN0u3TtMNQjnHEqAsa73/H0iU1qFV8rFURHuiWBbjEkKiHvjJPaEr5rOVvSF WM34QT69RnDLMfqc58Wnx3b0xW+hvqPdZhZCHVNJpfzGEYgGpKik94Cmw6QUKCTlPMh6 7NNA== 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=6tVjFEhkD+n/lPFRMHZEy/F0zK8ykCSr4pMVfxeeooI=; b=nNNE6oR+yaDczpYUrX8qb4WAzHhG+pxR9e6aTbQcb381K4W3pWIukNyUDGZJWepJDd l37sMNYgK5RrWVfXYK7P1yUkS6JyOHGNRgywEPrPW0i449gSHC+tknGcuGQFZ2/trkE9 0d9mFBWiY6Nph+ONBSqGfAT9jrTmD0fpe9D+hw76uDkPsVltCBVu5RFXTmhLgIBdNAz9 VOkvG97vzhlBjR4QPGSS5uPEx8ejVGgAMipio0vs08jmNxt6jXfM0TCn8wolvHlRmvxm VMLUNX8Xb2ZcN6MKteNg7hcfN/mciNafjLkPbHqHi/F058sF7sM5oG+jL6viMF6KPH++ UgSw== X-Gm-Message-State: AHPjjUiRo98CHKZC3Wmh0foQ2KCmCwr442GAT//Zq5KK3FT7KivU/rgU u1rWUjI2QeEYDLMzNpk= X-Google-Smtp-Source: ADKCNb7W82GwH1uv+ce2LxJ0nt/5fRYGil8tSRLODzrrlRl8GsybXEz0A9+4WabbOxUeKJoCw/QLDA== X-Received: by 10.55.148.194 with SMTP id w185mr1550468qkd.354.1505042555497; Sun, 10 Sep 2017 04:22:35 -0700 (PDT) Received: from localhost ([2601:184:4780:aac0:25f8:dd96:a084:785a]) by smtp.gmail.com with ESMTPSA id q49sm4497320qta.80.2017.09.10.04.22.34 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sun, 10 Sep 2017 04:22:34 -0700 (PDT) From: Rob Clark To: U-Boot Mailing List Date: Sun, 10 Sep 2017 07:21:26 -0400 Message-Id: <20170910112149.21358-10-robdclark@gmail.com> X-Mailer: git-send-email 2.13.5 In-Reply-To: <20170910112149.21358-1-robdclark@gmail.com> References: <20170910112149.21358-1-robdclark@gmail.com> Cc: Heinrich Schuchardt , Peter Jones Subject: [U-Boot] [PATCH v2 05/21] efi_loader: add device-path utils 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" Helpers to construct device-paths from devices, partitions, files, and for parsing and manipulating device-paths. For non-legacy devices, this will use u-boot's device-model to construct device-paths which include bus hierarchy to construct device-paths. For legacy devices we still fake it, but slightly more convincingly. Signed-off-by: Rob Clark --- include/efi_api.h | 10 + include/efi_loader.h | 26 ++ lib/efi_loader/Makefile | 2 +- lib/efi_loader/efi_boottime.c | 13 +- lib/efi_loader/efi_device_path.c | 563 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 611 insertions(+), 3 deletions(-) create mode 100644 lib/efi_loader/efi_device_path.c diff --git a/include/efi_api.h b/include/efi_api.h index b761cf4822..4e27c82129 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -314,6 +314,7 @@ struct efi_device_path_acpi_path { #define DEVICE_PATH_TYPE_MESSAGING_DEVICE 0x03 # define DEVICE_PATH_SUB_TYPE_MSG_USB 0x05 # define DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR 0x0b +# define DEVICE_PATH_SUB_TYPE_MSG_USB_CLASS 0x0f # define DEVICE_PATH_SUB_TYPE_MSG_SD 0x1a # define DEVICE_PATH_SUB_TYPE_MSG_MMC 0x1d @@ -329,6 +330,15 @@ struct efi_device_path_mac_addr { u8 if_type; } __packed; +struct efi_device_path_usb_class { + struct efi_device_path dp; + u16 vendor_id; + u16 product_id; + u8 device_class; + u8 device_subclass; + u8 device_protocol; +} __packed; + struct efi_device_path_sd_mmc_path { struct efi_device_path dp; u8 slot_number; diff --git a/include/efi_loader.h b/include/efi_loader.h index 1179234f68..d052b03ab7 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -197,6 +197,32 @@ extern void *efi_bounce_buffer; #define EFI_LOADER_BOUNCE_BUFFER_SIZE (64 * 1024 * 1024) #endif + +struct efi_device_path *efi_dp_next(const struct efi_device_path *dp); +int efi_dp_match(struct efi_device_path *a, struct efi_device_path *b); +struct efi_object *efi_dp_find_obj(struct efi_device_path *dp, + struct efi_device_path **rem); +unsigned efi_dp_size(const struct efi_device_path *dp); +struct efi_device_path *efi_dp_dup(const struct efi_device_path *dp); +struct efi_device_path *efi_dp_append(const struct efi_device_path *dp1, + const struct efi_device_path *dp2); +struct efi_device_path *efi_dp_append_node(const struct efi_device_path *dp, + const struct efi_device_path *node); + + +struct efi_device_path *efi_dp_from_dev(struct udevice *dev); +struct efi_device_path *efi_dp_from_part(struct blk_desc *desc, int part); +struct efi_device_path *efi_dp_from_file(struct blk_desc *desc, int part, + const char *path); +struct efi_device_path *efi_dp_from_eth(void); +void efi_dp_split_file_path(struct efi_device_path *full_path, + struct efi_device_path **device_path, + struct efi_device_path **file_path); + +#define EFI_DP_TYPE(_dp, _type, _subtype) \ + (((_dp)->type == DEVICE_PATH_TYPE_##_type) && \ + ((_dp)->sub_type == DEVICE_PATH_SUB_TYPE_##_subtype)) + /* Convert strings from normal C strings to uEFI strings */ static inline void ascii2unicode(u16 *unicode, const char *ascii) { diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile index 30bf343a36..f35e5ce8a8 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -15,7 +15,7 @@ always := $(efiprogs-y) obj-$(CONFIG_CMD_BOOTEFI_HELLO) += helloworld_efi.o obj-y += efi_image_loader.o efi_boottime.o efi_runtime.o efi_console.o -obj-y += efi_memory.o efi_device_path_to_text.o +obj-y += efi_memory.o efi_device_path_to_text.o efi_device_path.o obj-$(CONFIG_LCD) += efi_gop.o obj-$(CONFIG_DM_VIDEO) += efi_gop.o obj-$(CONFIG_PARTITIONS) += efi_disk.o diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 43f32385fa..b962b62a97 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -665,8 +665,17 @@ static efi_status_t EFIAPI efi_locate_device_path(efi_guid_t *protocol, struct efi_device_path **device_path, efi_handle_t *device) { - EFI_ENTRY("%p, %p, %p", protocol, device_path, device); - return EFI_EXIT(EFI_NOT_FOUND); + struct efi_object *efiobj; + + EFI_ENTRY("%pUl, %p, %p", protocol, device_path, device); + + efiobj = efi_dp_find_obj(*device_path, device_path); + if (!efiobj) + return EFI_EXIT(EFI_NOT_FOUND); + + *device = efiobj->handle; + + return EFI_EXIT(EFI_SUCCESS); } /* Collapses configuration table entries, removing index i */ diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c new file mode 100644 index 0000000000..5d5c3b3464 --- /dev/null +++ b/lib/efi_loader/efi_device_path.c @@ -0,0 +1,563 @@ +/* + * EFI device path from u-boot device-model mapping + * + * (C) Copyright 2017 Rob Clark + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* template END node: */ +static const struct efi_device_path END = { + .type = DEVICE_PATH_TYPE_END, + .sub_type = DEVICE_PATH_SUB_TYPE_END, + .length = sizeof(END), +}; + +#define U_BOOT_GUID \ + EFI_GUID(0xe61d73b9, 0xa384, 0x4acc, \ + 0xae, 0xab, 0x82, 0xe8, 0x28, 0xf3, 0x62, 0x8b) + +/* template ROOT node: */ +static const struct efi_device_path_vendor ROOT = { + .dp = { + .type = DEVICE_PATH_TYPE_HARDWARE_DEVICE, + .sub_type = DEVICE_PATH_SUB_TYPE_VENDOR, + .length = sizeof(ROOT), + }, + .guid = U_BOOT_GUID, +}; + +static void *dp_alloc(size_t sz) +{ + void *buf; + + if (efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES, sz, &buf) != EFI_SUCCESS) + return NULL; + + return buf; +} + +/* + * Iterate to next block in device-path, terminating (returning NULL) + * at /End* node. + */ +struct efi_device_path *efi_dp_next(const struct efi_device_path *dp) +{ + if (dp == NULL) + return NULL; + if (dp->type == DEVICE_PATH_TYPE_END) + return NULL; + dp = ((void *)dp) + dp->length; + if (dp->type == DEVICE_PATH_TYPE_END) + return NULL; + return (struct efi_device_path *)dp; +} + +/* + * Compare two device-paths, stopping when the shorter of the two hits + * an End* node. This is useful to, for example, compare a device-path + * representing a device with one representing a file on the device, or + * a device with a parent device. + */ +int efi_dp_match(struct efi_device_path *a, struct efi_device_path *b) +{ + while (1) { + int ret; + + ret = memcmp(&a->length, &b->length, sizeof(a->length)); + if (ret) + return ret; + + ret = memcmp(a, b, a->length); + if (ret) + return ret; + + a = efi_dp_next(a); + b = efi_dp_next(b); + + if (!a || !b) + return 0; + } +} + + +/* + * See UEFI spec (section 3.1.2, about short-form device-paths.. + * tl;dr: we can have a device-path that starts with a USB WWID + * or USB Class node, and a few other cases which don't encode + * the full device path with bus hierarchy: + * + * - MESSAGING:USB_WWID + * - MESSAGING:USB_CLASS + * - MEDIA:FILE_PATH + * - MEDIA:HARD_DRIVE + * - MESSAGING:URI + */ +static struct efi_device_path *shorten_path(struct efi_device_path *dp) +{ + while (dp) { + /* + * TODO: Add MESSAGING:USB_WWID and MESSAGING:URI.. + * in practice fallback.efi just uses MEDIA:HARD_DRIVE + * so not sure when we would see these other cases. + */ + if (EFI_DP_TYPE(dp, MESSAGING_DEVICE, MSG_USB_CLASS) || + EFI_DP_TYPE(dp, MEDIA_DEVICE, HARD_DRIVE_PATH) || + EFI_DP_TYPE(dp, MEDIA_DEVICE, FILE_PATH)) + return dp; + + dp = efi_dp_next(dp); + } + + return dp; +} + +static struct efi_object *find_obj(struct efi_device_path *dp, bool short_path, + struct efi_device_path **rem) +{ + struct efi_object *efiobj; + + list_for_each_entry(efiobj, &efi_obj_list, link) { + int i; + + for (i = 0; i < ARRAY_SIZE(efiobj->protocols); i++) { + struct efi_handler *handler = &efiobj->protocols[i]; + struct efi_device_path *obj_dp; + + if (!handler->guid) + break; + + if (guidcmp(handler->guid, &efi_guid_device_path)) + continue; + + obj_dp = handler->protocol_interface; + + do { + if (efi_dp_match(dp, obj_dp) == 0) { + if (rem) { + *rem = ((void *)dp) + + efi_dp_size(obj_dp); + } + return efiobj; + } + + obj_dp = shorten_path(efi_dp_next(obj_dp)); + } while (short_path && obj_dp); + } + } + + return NULL; +} + + +/* + * Find an efiobj from device-path, if 'rem' is not NULL, returns the + * remaining part of the device path after the matched object. + */ +struct efi_object *efi_dp_find_obj(struct efi_device_path *dp, + struct efi_device_path **rem) +{ + struct efi_object *efiobj; + + efiobj = find_obj(dp, false, rem); + + if (!efiobj) + efiobj = find_obj(dp, true, rem); + + return efiobj; +} + +/* return size not including End node: */ +unsigned efi_dp_size(const struct efi_device_path *dp) +{ + unsigned sz = 0; + + while (dp) { + sz += dp->length; + dp = efi_dp_next(dp); + } + + return sz; +} + +struct efi_device_path *efi_dp_dup(const struct efi_device_path *dp) +{ + struct efi_device_path *ndp; + unsigned sz = efi_dp_size(dp) + sizeof(END); + + if (!dp) + return NULL; + + ndp = dp_alloc(sz); + memcpy(ndp, dp, sz); + + return ndp; +} + +struct efi_device_path *efi_dp_append(const struct efi_device_path *dp1, + const struct efi_device_path *dp2) +{ + struct efi_device_path *ret; + + if (!dp1) { + ret = efi_dp_dup(dp2); + } else if (!dp2) { + ret = efi_dp_dup(dp1); + } else { + /* both dp1 and dp2 are non-null */ + unsigned sz1 = efi_dp_size(dp1); + unsigned sz2 = efi_dp_size(dp2); + void *p = dp_alloc(sz1 + sz2 + sizeof(END)); + memcpy(p, dp1, sz1); + memcpy(p + sz1, dp2, sz2); + memcpy(p + sz1 + sz2, &END, sizeof(END)); + ret = p; + } + + return ret; +} + +struct efi_device_path *efi_dp_append_node(const struct efi_device_path *dp, + const struct efi_device_path *node) +{ + struct efi_device_path *ret; + + if (!node && !dp) { + ret = efi_dp_dup(&END); + } else if (!node) { + ret = efi_dp_dup(dp); + } else if (!dp) { + unsigned sz = node->length; + void *p = dp_alloc(sz + sizeof(END)); + memcpy(p, node, sz); + memcpy(p + sz, &END, sizeof(END)); + ret = p; + } else { + /* both dp and node are non-null */ + unsigned sz = efi_dp_size(dp); + void *p = dp_alloc(sz + node->length + sizeof(END)); + memcpy(p, dp, sz); + memcpy(p + sz, node, node->length); + memcpy(p + sz + node->length, &END, sizeof(END)); + ret = p; + } + + return ret; +} + +#ifdef CONFIG_DM +/* size of device-path not including END node for device and all parents + * up to the root device. + */ +static unsigned dp_size(struct udevice *dev) +{ + if (!dev || !dev->driver) + return sizeof(ROOT); + + switch (dev->driver->id) { + case UCLASS_ROOT: + case UCLASS_SIMPLE_BUS: + /* stop traversing parents at this point: */ + return sizeof(ROOT); + case UCLASS_MMC: + return dp_size(dev->parent) + + sizeof(struct efi_device_path_sd_mmc_path); + case UCLASS_MASS_STORAGE: + case UCLASS_USB_HUB: + return dp_size(dev->parent) + + sizeof(struct efi_device_path_usb_class); + default: + /* just skip over unknown classes: */ + return dp_size(dev->parent); + } +} + +static void *dp_fill(void *buf, struct udevice *dev) +{ + if (!dev || !dev->driver) + return buf; + + switch (dev->driver->id) { + case UCLASS_ROOT: + case UCLASS_SIMPLE_BUS: { + /* stop traversing parents at this point: */ + struct efi_device_path_vendor *vdp = buf; + *vdp = ROOT; + return &vdp[1]; + } +#if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC) + case UCLASS_MMC: { + struct efi_device_path_sd_mmc_path *sddp = + dp_fill(buf, dev->parent); + struct mmc *mmc = mmc_get_mmc_dev(dev); + struct blk_desc *desc = mmc_get_blk_desc(mmc); + + sddp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE; + sddp->dp.sub_type = (desc->if_type == IF_TYPE_MMC) ? + DEVICE_PATH_SUB_TYPE_MSG_MMC : + DEVICE_PATH_SUB_TYPE_MSG_SD; + sddp->dp.length = sizeof(*sddp); + sddp->slot_number = dev->seq; + + return &sddp[1]; + } +#endif + case UCLASS_MASS_STORAGE: + case UCLASS_USB_HUB: { + struct efi_device_path_usb_class *udp = + dp_fill(buf, dev->parent); + struct usb_device *udev = dev_get_parent_priv(dev); + struct usb_device_descriptor *desc = &udev->descriptor; + + udp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE; + udp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_USB_CLASS; + udp->dp.length = sizeof(*udp); + udp->vendor_id = desc->idVendor; + udp->product_id = desc->idProduct; + udp->device_class = desc->bDeviceClass; + udp->device_subclass = desc->bDeviceSubClass; + udp->device_protocol = desc->bDeviceProtocol; + + return &udp[1]; + } + default: + debug("unhandled device class: %s (%u)\n", + dev->name, dev->driver->id); + return dp_fill(buf, dev->parent); + } +} + +/* Construct a device-path from a device: */ +struct efi_device_path *efi_dp_from_dev(struct udevice *dev) +{ + void *buf, *start; + + start = buf = dp_alloc(dp_size(dev) + sizeof(END)); + buf = dp_fill(buf, dev); + *((struct efi_device_path *)buf) = END; + + return start; +} +#endif + +static unsigned dp_part_size(struct blk_desc *desc, int part) +{ + unsigned dpsize; + +#ifdef CONFIG_BLK + dpsize = dp_size(desc->bdev->parent); +#else + dpsize = sizeof(ROOT) + sizeof(struct efi_device_path_usb); +#endif + + if (part == 0) /* the actual disk, not a partition */ + return dpsize; + + if (desc->part_type == PART_TYPE_ISO) + dpsize += sizeof(struct efi_device_path_cdrom_path); + else + dpsize += sizeof(struct efi_device_path_hard_drive_path); + + return dpsize; +} + +static void *dp_part_fill(void *buf, struct blk_desc *desc, int part) +{ + disk_partition_t info; + +#ifdef CONFIG_BLK + buf = dp_fill(buf, desc->bdev->parent); +#else + /* + * We *could* make a more accurate path, by looking at if_type + * and handling all the different cases like we do for non- + * legacy (ie CONFIG_BLK=y) case. But most important thing + * is just to have a unique device-path for if_type+devnum. + * So map things to a fictional USB device: + */ + struct efi_device_path_usb *udp; + + memcpy(buf, &ROOT, sizeof(ROOT)); + buf += sizeof(ROOT); + + udp = buf; + udp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE; + udp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_USB; + udp->dp.length = sizeof(*udp); + udp->parent_port_number = desc->if_type; + udp->usb_interface = desc->devnum; + buf = &udp[1]; +#endif + + if (part == 0) /* the actual disk, not a partition */ + return buf; + + part_get_info(desc, part, &info); + + if (desc->part_type == PART_TYPE_ISO) { + struct efi_device_path_cdrom_path *cddp = buf; + + cddp->boot_entry = part - 1; + cddp->dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE; + cddp->dp.sub_type = DEVICE_PATH_SUB_TYPE_CDROM_PATH; + cddp->dp.length = sizeof(*cddp); + cddp->partition_start = info.start; + cddp->partition_end = info.size; + + buf = &cddp[1]; + } else { + struct efi_device_path_hard_drive_path *hddp = buf; + + hddp->dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE; + hddp->dp.sub_type = DEVICE_PATH_SUB_TYPE_HARD_DRIVE_PATH; + hddp->dp.length = sizeof(*hddp); + hddp->partition_number = part - 1; + hddp->partition_start = info.start; + hddp->partition_end = info.size; + if (desc->part_type == PART_TYPE_EFI) + hddp->partmap_type = 2; + else + hddp->partmap_type = 1; + hddp->signature_type = desc->sig_type; + if (hddp->signature_type != 0) + memcpy(hddp->partition_signature, &desc->guid_sig, + sizeof(hddp->partition_signature)); + + buf = &hddp[1]; + } + + return buf; +} + + +/* Construct a device-path from a partition on a blk device: */ +struct efi_device_path *efi_dp_from_part(struct blk_desc *desc, int part) +{ + void *buf, *start; + + start = buf = dp_alloc(dp_part_size(desc, part) + sizeof(END)); + + buf = dp_part_fill(buf, desc, part); + + *((struct efi_device_path *)buf) = END; + + return start; +} + +/* convert path to an UEFI style path (ie. DOS style backslashes and utf16) */ +static void path_to_uefi(u16 *uefi, const char *path) +{ + while (*path) { + char c = *(path++); + if (c == '/') + c = '\\'; + *(uefi++) = c; + } + *uefi = '\0'; +} + +/* + * If desc is NULL, this creates a path with only the file component, + * otherwise it creates a full path with both device and file components + */ +struct efi_device_path *efi_dp_from_file(struct blk_desc *desc, int part, + const char *path) +{ + struct efi_device_path_file_path *fp; + void *buf, *start; + unsigned dpsize = 0, fpsize; + + if (desc) + dpsize = dp_part_size(desc, part); + + fpsize = sizeof(struct efi_device_path) + 2 * (strlen(path) + 1); + dpsize += fpsize; + + start = buf = dp_alloc(dpsize + sizeof(END)); + + if (desc) + buf = dp_part_fill(buf, desc, part); + + /* add file-path: */ + fp = buf; + fp->dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE; + fp->dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH; + fp->dp.length = fpsize; + path_to_uefi(fp->str, path); + buf += fpsize; + + *((struct efi_device_path *)buf) = END; + + return start; +} + +#ifdef CONFIG_NET +struct efi_device_path *efi_dp_from_eth(void) +{ + struct efi_device_path_mac_addr *ndp; + void *buf, *start; + unsigned dpsize = 0; + + assert(eth_get_dev()); + +#ifdef CONFIG_DM_ETH + dpsize += dp_size(eth_get_dev()); +#else + dpsize += sizeof(ROOT); +#endif + dpsize += sizeof(*ndp); + + start = buf = dp_alloc(dpsize + sizeof(END)); + +#ifdef CONFIG_DM_ETH + buf = dp_fill(buf, eth_get_dev()); +#else + memcpy(buf, &ROOT, sizeof(ROOT)); + buf += sizeof(ROOT); +#endif + + ndp = buf; + ndp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE; + ndp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR; + ndp->dp.length = sizeof(*ndp); + memcpy(ndp->mac.addr, eth_get_ethaddr(), ARP_HLEN); + buf = &ndp[1]; + + *((struct efi_device_path *)buf) = END; + + return start; +} +#endif + +/* + * Helper to split a full device path (containing both device and file + * parts) into it's constituent parts. + */ +void efi_dp_split_file_path(struct efi_device_path *full_path, + struct efi_device_path **device_path, + struct efi_device_path **file_path) +{ + struct efi_device_path *p, *dp, *fp; + + dp = efi_dp_dup(full_path); + p = dp; + while (!EFI_DP_TYPE(p, MEDIA_DEVICE, FILE_PATH)) + p = efi_dp_next(p); + fp = efi_dp_dup(p); + + p->type = DEVICE_PATH_TYPE_END; + p->sub_type = DEVICE_PATH_SUB_TYPE_END; + p->length = sizeof(*p); + + *device_path = dp; + *file_path = fp; +} From patchwork Sun Sep 10 11:21:29 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Rob Clark X-Patchwork-Id: 812104 X-Patchwork-Delegate: trini@ti.com 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="atMhNXxm"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3xqphY5DjRz9sDB for ; Sun, 10 Sep 2017 21:28:13 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 51862C21E3C; Sun, 10 Sep 2017 11:26:25 +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 E8F9AC21DA1; Sun, 10 Sep 2017 11:24:16 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id ABDD1C21EFC; Sun, 10 Sep 2017 11:22:52 +0000 (UTC) Received: from mail-qk0-f196.google.com (mail-qk0-f196.google.com [209.85.220.196]) by lists.denx.de (Postfix) with ESMTPS id D8F24C21DBD for ; Sun, 10 Sep 2017 11:22:47 +0000 (UTC) Received: by mail-qk0-f196.google.com with SMTP id r66so3817627qke.4 for ; Sun, 10 Sep 2017 04:22:47 -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 :mime-version:content-transfer-encoding; bh=PymlcJay5TBoRrL4RcwklBXHDDJILXqutTw+bvDSHWU=; b=atMhNXxmUaNXpyF1t//xzWF4q2gZhsepjAXhoxiNqc7HNunsKhtiEsXeCa5llQDToA gQ0Xv36G4eOaqc/3XmFRPgrZib+MHRKEOa0HiPEcWTyZhURm+91vLY6FfxNs8Zt7nJzT 4U+ixZ3XS6IEQwR50c81cgCy+Ng1DAXJ4uJL+0+w7Nr/biDaJfzvTxBPGtlDFVNVPRL9 KGOdXXB1Wsltf7o4GfKbZdNkDqhlHegA0JcfyOiABblgQerz8RCoUnw7BNx0cStow7gW f6+hW+K5lcMROPiSA0SNjYzLVvnupvlJ8LfGFAEUAh39tV5R0w4P9+Rt2abUjTVZTi/C hnvQ== 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:mime-version:content-transfer-encoding; bh=PymlcJay5TBoRrL4RcwklBXHDDJILXqutTw+bvDSHWU=; b=S66RXQKsk8Zpb5TRjtZxC5r6vnGQigBJbu6bPIXDPZlS7liSV7Yl28KKiAtfRelvzy /HYaVWxmPXc6IR5aIRHEYXwM5gFpFHNen2B5nV5pk3TcULNdMj7hqo5qTcbdgGt7vk6N kbuRP+c9jfMFhccc5G6iai0htBxdav5tkDoVGq0DjjZpFn7lqiVamYcJfm8hx8jlgMFB bl5KEK42Ht2n/A3CJNjk53yXn1ER/9Z/RrQPAd0XPI1pSgyeAVy1h/SjwMngADjT6z5M lsCup5lAMRJCeitKfxeQTVPIfOB99diJ0lnLG22kSLrAsZ8tvcLQR1jkkwVLwM8PA6uJ QnxA== X-Gm-Message-State: AHPjjUjn7OXMG0hWhl1jd2vUAF/bFqujFFxbBs6kuu3XNVrbJCAUO3K6 p7Kb10S1h5ywhIPjoxc= X-Google-Smtp-Source: AOwi7QATIRNXN4tJW7ALG2A++FJ4/+Gr//seefm9VDRKsKrHLRPZq4wP6rUEMglV5uFccchBAyxbhg== X-Received: by 10.55.200.210 with SMTP id t79mr11550462qkl.140.1505042566564; Sun, 10 Sep 2017 04:22:46 -0700 (PDT) Received: from localhost ([2601:184:4780:aac0:25f8:dd96:a084:785a]) by smtp.gmail.com with ESMTPSA id g132sm4084306qke.11.2017.09.10.04.22.45 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sun, 10 Sep 2017 04:22:45 -0700 (PDT) From: Rob Clark To: U-Boot Mailing List Date: Sun, 10 Sep 2017 07:21:29 -0400 Message-Id: <20170910112149.21358-13-robdclark@gmail.com> X-Mailer: git-send-email 2.13.5 In-Reply-To: <20170910112149.21358-1-robdclark@gmail.com> References: <20170910112149.21358-1-robdclark@gmail.com> MIME-Version: 1.0 Cc: Heinrich Schuchardt , Genevieve Chan , Tien Fong Chee Subject: [U-Boot] [PATCH v3 6/9] fat/fs: remove a bunch of dead code 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: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" Spotted by chance, when trying to remove file_fat_ls(), I noticed there were some dead users of the API. Signed-off-by: Rob Clark Acked-by: Stefan Brüns Reviewed-by: Simon Glass --- fs/fat/Makefile | 4 -- fs/fat/file.c | 183 -------------------------------------------------------- include/fat.h | 20 ------- 3 files changed, 207 deletions(-) delete mode 100644 fs/fat/file.c diff --git a/fs/fat/Makefile b/fs/fat/Makefile index b60e8486c4..3e2a6b01a8 100644 --- a/fs/fat/Makefile +++ b/fs/fat/Makefile @@ -5,7 +5,3 @@ obj-$(CONFIG_FS_FAT) := fat.o obj-$(CONFIG_FAT_WRITE):= fat_write.o - -ifndef CONFIG_SPL_BUILD -obj-$(CONFIG_FS_FAT) += file.o -endif diff --git a/fs/fat/file.c b/fs/fat/file.c deleted file mode 100644 index 89706117b9..0000000000 --- a/fs/fat/file.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - * file.c - * - * Mini "VFS" by Marcus Sundberg - * - * 2002-07-28 - rjones@nexus-tech.net - ported to ppcboot v1.1.6 - * 2003-03-10 - kharris@nexus-tech.net - ported to uboot - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include -#include - -/* Supported filesystems */ -static const struct filesystem filesystems[] = { - { file_fat_detectfs, file_fat_ls, file_fat_read, "FAT" }, -}; -#define NUM_FILESYS (sizeof(filesystems)/sizeof(struct filesystem)) - -/* The filesystem which was last detected */ -static int current_filesystem = FSTYPE_NONE; - -/* The current working directory */ -#define CWD_LEN 511 -char file_cwd[CWD_LEN+1] = "/"; - -const char * -file_getfsname(int idx) -{ - if (idx < 0 || idx >= NUM_FILESYS) - return NULL; - - return filesystems[idx].name; -} - -static void -pathcpy(char *dest, const char *src) -{ - char *origdest = dest; - - do { - if (dest-file_cwd >= CWD_LEN) { - *dest = '\0'; - return; - } - *(dest) = *(src); - if (*src == '\0') { - if (dest-- != origdest && ISDIRDELIM(*dest)) { - *dest = '\0'; - } - return; - } - ++dest; - - if (ISDIRDELIM(*src)) - while (ISDIRDELIM(*src)) src++; - else - src++; - } while (1); -} - -int -file_cd(const char *path) -{ - if (ISDIRDELIM(*path)) { - while (ISDIRDELIM(*path)) path++; - strncpy(file_cwd+1, path, CWD_LEN-1); - } else { - const char *origpath = path; - char *tmpstr = file_cwd; - int back = 0; - - while (*tmpstr != '\0') tmpstr++; - do { - tmpstr--; - } while (ISDIRDELIM(*tmpstr)); - - while (*path == '.') { - path++; - while (*path == '.') { - path++; - back++; - } - if (*path != '\0' && !ISDIRDELIM(*path)) { - path = origpath; - back = 0; - break; - } - while (ISDIRDELIM(*path)) path++; - origpath = path; - } - - while (back--) { - /* Strip off path component */ - while (!ISDIRDELIM(*tmpstr)) { - tmpstr--; - } - if (tmpstr == file_cwd) { - /* Incremented again right after the loop. */ - tmpstr--; - break; - } - /* Skip delimiters */ - while (ISDIRDELIM(*tmpstr)) tmpstr--; - } - tmpstr++; - if (*path == '\0') { - if (tmpstr == file_cwd) { - *tmpstr = '/'; - tmpstr++; - } - *tmpstr = '\0'; - return 0; - } - *tmpstr = '/'; - pathcpy(tmpstr+1, path); - } - - return 0; -} - -int -file_detectfs(void) -{ - int i; - - current_filesystem = FSTYPE_NONE; - - for (i = 0; i < NUM_FILESYS; i++) { - if (filesystems[i].detect() == 0) { - strcpy(file_cwd, "/"); - current_filesystem = i; - break; - } - } - - return current_filesystem; -} - -int -file_ls(const char *dir) -{ - char fullpath[1024]; - const char *arg; - - if (current_filesystem == FSTYPE_NONE) { - printf("Can't list files without a filesystem!\n"); - return -1; - } - - if (ISDIRDELIM(*dir)) { - arg = dir; - } else { - sprintf(fullpath, "%s/%s", file_cwd, dir); - arg = fullpath; - } - return filesystems[current_filesystem].ls(arg); -} - -int file_read(const char *filename, void *buffer, int maxsize) -{ - char fullpath[1024]; - const char *arg; - - if (current_filesystem == FSTYPE_NONE) { - printf("Can't load file without a filesystem!\n"); - return -1; - } - - if (ISDIRDELIM(*filename)) { - arg = filename; - } else { - sprintf(fullpath, "%s/%s", file_cwd, filename); - arg = fullpath; - } - - return filesystems[current_filesystem].read(arg, buffer, maxsize); -} diff --git a/include/fat.h b/include/fat.h index 18d8981c48..b255ce5337 100644 --- a/include/fat.h +++ b/include/fat.h @@ -178,25 +178,6 @@ static inline u32 clust_to_sect(fsdata *fsdata, u32 clust) return fsdata->data_begin + clust * fsdata->clust_size; } -typedef int (file_detectfs_func)(void); -typedef int (file_ls_func)(const char *dir); -typedef int (file_read_func)(const char *filename, void *buffer, - int maxsize); - -struct filesystem { - file_detectfs_func *detect; - file_ls_func *ls; - file_read_func *read; - const char name[12]; -}; - -/* FAT tables */ -file_detectfs_func file_fat_detectfs; -file_ls_func file_fat_ls; -file_read_func file_fat_read; - -/* Currently this doesn't check if the dir exists or is valid... */ -int file_cd(const char *path); int file_fat_detectfs(void); int file_fat_ls(const char *dir); int fat_exists(const char *filename); @@ -204,7 +185,6 @@ int fat_size(const char *filename, loff_t *size); int file_fat_read_at(const char *filename, loff_t pos, void *buffer, loff_t maxsize, loff_t *actread); int file_fat_read(const char *filename, void *buffer, int maxsize); -const char *file_getfsname(int idx); int fat_set_blk_dev(struct blk_desc *rbdd, disk_partition_t *info); int fat_register_device(struct blk_desc *dev_desc, int part_no); From patchwork Sun Sep 10 11:21:30 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Clark X-Patchwork-Id: 812102 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="RrpgCC7M"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3xqpgx5FHsz9sDB for ; Sun, 10 Sep 2017 21:27:41 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 5D324C21DDF; Sun, 10 Sep 2017 11:25:48 +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 DC483C21E40; Sun, 10 Sep 2017 11:23:40 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id F2B3BC21C4C; Sun, 10 Sep 2017 11:22:56 +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 29384C21E3C for ; Sun, 10 Sep 2017 11:22:51 +0000 (UTC) Received: by mail-qt0-f195.google.com with SMTP id b1so1747208qtc.0 for ; Sun, 10 Sep 2017 04:22:51 -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=9wvjK6cnE3C9klIJHwS9ip4xCU9ANtGDr0esnZ4NAhQ=; b=RrpgCC7MoAnJJOtQbMYvqOj14VAsctkHMVFc4O2zFBYg4wGP2k7vLBExJAItC4AOor iQIFCJW93CAzvMKzyrL0O0x5v56/7fbNEbrjP5dyaLa3Qm9hf3u1HiO7F2EggAnBN0Wp atd+FCXm5rStqxuBvduplvdYXYhUUJ0cH3rMExuWy+DyakxcoYURv82r2STzzvg1B7eU vbV9Q13+rzg7pZVPMWEBaa43ZrlvfkD2ScZHjd7rQkcvgPlWDRE8UKHiBhJkVtMRjk7A hjIMj3ZMMUCJT4w32l10vpCLYSR8ErWbHE4becCpUfZn7XrbmT68rkPyMurysZSZIu62 fUcQ== 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=9wvjK6cnE3C9klIJHwS9ip4xCU9ANtGDr0esnZ4NAhQ=; b=h5zJ0A6OkHryAQa1eL8cmwfn/IxvS57T9NbFS+8qMN8A3RhzAjNgiLHoAFe8pnaqir wwkaH/3kjtiUeMquQ4sVqttvE7RUCnETFfIHwnZSjWuHzDkDTaDAMSGDXkQTrD6aFmyx +H61RNYYKx2HlZOy4xN0oWYP3+q8Ld2SOnP0t5t+a6r9xodxqvJGvwNlzxBTMWtw4u4E aRFmV4mzZcOO2lKXXr753kymDEoFxGkM/7sNNXfAwKyu5Dgc5nwgkX16ICdGbYGg+d/T XXfCfnQ6OOZMnxAQMYjwXfLH9bkIF5K8aN54ZMQgRr1UClp+u7rQBpqZuHhrhqQ5Kwp4 mIGg== X-Gm-Message-State: AHPjjUjFjMUmddxupfDSJM1JKW8nh8epRHy9xUlAvfA3ZLnKRZeeZNmF Kyp8i1IVkylF6ITseE8= X-Google-Smtp-Source: AOwi7QBFI+GLboXJ0tuxFqtk1bg5TfQc6umbO15TCIUOKpj/zYMVO/dWDVBvVKp4C1b1as5XWYTIYA== X-Received: by 10.200.27.226 with SMTP id m31mr12304437qtk.198.1505042569769; Sun, 10 Sep 2017 04:22:49 -0700 (PDT) Received: from localhost ([2601:184:4780:aac0:25f8:dd96:a084:785a]) by smtp.gmail.com with ESMTPSA id i39sm4510910qte.11.2017.09.10.04.22.48 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sun, 10 Sep 2017 04:22:48 -0700 (PDT) From: Rob Clark To: U-Boot Mailing List Date: Sun, 10 Sep 2017 07:21:30 -0400 Message-Id: <20170910112149.21358-14-robdclark@gmail.com> X-Mailer: git-send-email 2.13.5 In-Reply-To: <20170910112149.21358-1-robdclark@gmail.com> References: <20170910112149.21358-1-robdclark@gmail.com> Cc: Heinrich Schuchardt , Peter Jones Subject: [U-Boot] [PATCH v2 07/21] efi_loader: flesh out device-path to text 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" It needs to handle more device-path node types, and also multiple levels of path hierarchy. To simplify this, initially construct utf8 string to a temporary buffer, and then allocate the real utf16 buffer that is returned. This should be mostly for debugging or at least not critical- path so an extra copy won't hurt, and is saner than the alternative. Signed-off-by: Rob Clark --- include/efi_api.h | 1 + include/efi_loader.h | 2 + lib/efi_loader/efi_device_path_to_text.c | 241 +++++++++++++++++++++++-------- 3 files changed, 181 insertions(+), 63 deletions(-) diff --git a/include/efi_api.h b/include/efi_api.h index ac58fd58de..0c36122107 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -304,6 +304,7 @@ struct efi_device_path_vendor { #define EFI_PNP_ID(ID) (u32)(((ID) << 16) | 0x41D0) #define EISA_PNP_ID(ID) EFI_PNP_ID(ID) +#define EISA_PNP_NUM(ID) ((ID) >> 16) struct efi_device_path_acpi_path { struct efi_device_path dp; diff --git a/include/efi_loader.h b/include/efi_loader.h index d052b03ab7..f39c2ee6da 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -59,6 +59,8 @@ extern struct efi_simple_input_interface efi_con_in; extern const struct efi_console_control_protocol efi_console_control; extern const struct efi_device_path_to_text_protocol efi_device_path_to_text; +uint16_t *efi_dp_str(struct efi_device_path *dp); + extern const efi_guid_t efi_guid_console_control; extern const efi_guid_t efi_guid_device_path; extern const efi_guid_t efi_guid_loaded_image; diff --git a/lib/efi_loader/efi_device_path_to_text.c b/lib/efi_loader/efi_device_path_to_text.c index f9d071ac50..1a5ef3919b 100644 --- a/lib/efi_loader/efi_device_path_to_text.c +++ b/lib/efi_loader/efi_device_path_to_text.c @@ -15,82 +15,197 @@ const efi_guid_t efi_guid_device_path_to_text_protocol = EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID; -static uint16_t *efi_convert_device_node_to_text( - struct efi_device_path *device_node, - bool display_only, - bool allow_shortcuts) +static char *dp_unknown(char *s, struct efi_device_path *dp) { - unsigned long buffer_size; - efi_status_t r; - uint16_t *buffer = NULL; - int i; + s += sprintf(s, "/UNKNOWN(%04x,%04x)", dp->type, dp->sub_type); + return s; +} - switch (device_node->type) { - case DEVICE_PATH_TYPE_END: - return NULL; - case DEVICE_PATH_TYPE_MESSAGING_DEVICE: - switch (device_node->sub_type) { - case DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR: { - struct efi_device_path_mac_addr *dp = - (struct efi_device_path_mac_addr *)device_node; - - if (dp->if_type != 0 && dp->if_type != 1) - break; - r = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES, - 2 * MAC_OUTPUT_LEN, - (void **)&buffer); - if (r != EFI_SUCCESS) - return NULL; - sprintf((char *)buffer, - "MAC(%02x%02x%02x%02x%02x%02x,0x%1x)", - dp->mac.addr[0], dp->mac.addr[1], - dp->mac.addr[2], dp->mac.addr[3], - dp->mac.addr[4], dp->mac.addr[5], - dp->if_type); - for (i = MAC_OUTPUT_LEN - 1; i >= 0; --i) - buffer[i] = ((uint8_t *)buffer)[i]; +static char *dp_hardware(char *s, struct efi_device_path *dp) +{ + switch (dp->sub_type) { + case DEVICE_PATH_SUB_TYPE_VENDOR: { + struct efi_device_path_vendor *vdp = + (struct efi_device_path_vendor *)dp; + s += sprintf(s, "/VenHw(%pUl)", &vdp->guid); + break; + } + default: + s = dp_unknown(s, dp); + break; + } + return s; +} + +static char *dp_acpi(char *s, struct efi_device_path *dp) +{ + switch (dp->sub_type) { + case DEVICE_PATH_SUB_TYPE_ACPI_DEVICE: { + struct efi_device_path_acpi_path *adp = + (struct efi_device_path_acpi_path *)dp; + s += sprintf(s, "/Acpi(PNP%04x", EISA_PNP_NUM(adp->hid)); + if (adp->uid) + s += sprintf(s, ",%d", adp->uid); + s += sprintf(s, ")"); + break; + } + default: + s = dp_unknown(s, dp); + break; + } + return s; +} + +static char *dp_msging(char *s, struct efi_device_path *dp) +{ + switch (dp->sub_type) { + case DEVICE_PATH_SUB_TYPE_MSG_USB: { + struct efi_device_path_usb *udp = + (struct efi_device_path_usb *)dp; + s += sprintf(s, "/Usb(0x%x,0x%x)", udp->parent_port_number, + udp->usb_interface); + break; + } + case DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR: { + struct efi_device_path_mac_addr *mdp = + (struct efi_device_path_mac_addr *)dp; + + if (mdp->if_type != 0 && mdp->if_type != 1) break; - } - } + + s += sprintf(s, "/MAC(%02x%02x%02x%02x%02x%02x,0x%1x)", + mdp->mac.addr[0], mdp->mac.addr[1], + mdp->mac.addr[2], mdp->mac.addr[3], + mdp->mac.addr[4], mdp->mac.addr[5], + mdp->if_type); + + break; + } + case DEVICE_PATH_SUB_TYPE_MSG_USB_CLASS: { + struct efi_device_path_usb_class *ucdp = + (struct efi_device_path_usb_class *)dp; + + s += sprintf(s, "/USBClass(%x,%x,%x,%x,%x)", + ucdp->vendor_id, ucdp->product_id, + ucdp->device_class, ucdp->device_subclass, + ucdp->device_protocol); + + break; + } + case DEVICE_PATH_SUB_TYPE_MSG_SD: + case DEVICE_PATH_SUB_TYPE_MSG_MMC: { + const char *typename = + (dp->sub_type == DEVICE_PATH_SUB_TYPE_MSG_SD) ? + "SDCard" : "MMC"; + struct efi_device_path_sd_mmc_path *sddp = + (struct efi_device_path_sd_mmc_path *)dp; + s += sprintf(s, "/%s(Slot%u)", typename, sddp->slot_number); + break; + } + default: + s = dp_unknown(s, dp); break; - case DEVICE_PATH_TYPE_MEDIA_DEVICE: - switch (device_node->sub_type) { - case DEVICE_PATH_SUB_TYPE_FILE_PATH: { - struct efi_device_path_file_path *fp = - (struct efi_device_path_file_path *)device_node; - buffer_size = device_node->length - 4; - r = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES, - buffer_size, (void **) &buffer); - if (r != EFI_SUCCESS) - return NULL; - memcpy(buffer, fp->str, buffer_size); + } + return s; +} + +static char *dp_media(char *s, struct efi_device_path *dp) +{ + switch (dp->sub_type) { + case DEVICE_PATH_SUB_TYPE_HARD_DRIVE_PATH: { + struct efi_device_path_hard_drive_path *hddp = + (struct efi_device_path_hard_drive_path *)dp; + void *sig = hddp->partition_signature; + + switch (hddp->signature_type) { + case SIG_TYPE_MBR: + s += sprintf(s, "/HD(Part%d,Sig%08x)", + hddp->partition_number, + *(uint32_t *)sig); break; + case SIG_TYPE_GUID: + s += sprintf(s, "/HD(Part%d,Sig%pUl)", + hddp->partition_number, sig); + default: + s += sprintf(s, "/HD(Part%d,MBRType=%02x,SigType=%02x)", + hddp->partition_number, hddp->partmap_type, + hddp->signature_type); } - } + + break; + } + case DEVICE_PATH_SUB_TYPE_CDROM_PATH: { + struct efi_device_path_cdrom_path *cddp = + (struct efi_device_path_cdrom_path *)dp; + s += sprintf(s, "/CDROM(0x%x)", cddp->boot_entry); + break; + } + case DEVICE_PATH_SUB_TYPE_FILE_PATH: { + struct efi_device_path_file_path *fp = + (struct efi_device_path_file_path *)dp; + int slen = (dp->length - sizeof(*dp)) / 2; + s += sprintf(s, "/%-*ls", slen, fp->str); + break; + } + default: + s = dp_unknown(s, dp); break; } + return s; +} - /* - * For all node types that we do not yet support return - * 'UNKNOWN(type,subtype)'. - */ - if (!buffer) { - r = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES, - 2 * UNKNOWN_OUTPUT_LEN, - (void **)&buffer); - if (r != EFI_SUCCESS) - return NULL; - sprintf((char *)buffer, - "UNKNOWN(%04x,%04x)", - device_node->type, - device_node->sub_type); - for (i = UNKNOWN_OUTPUT_LEN - 1; i >= 0; --i) - buffer[i] = ((uint8_t *)buffer)[i]; +static uint16_t *efi_convert_device_node_to_text( + struct efi_device_path *dp, + bool display_only, + bool allow_shortcuts) +{ + unsigned long len; + efi_status_t r; + char buf[512]; /* this ought be be big enough for worst case */ + char *str = buf; + uint16_t *out; + + while (dp) { + switch (dp->type) { + case DEVICE_PATH_TYPE_HARDWARE_DEVICE: + str = dp_hardware(str, dp); + break; + case DEVICE_PATH_TYPE_ACPI_DEVICE: + str = dp_acpi(str, dp); + break; + case DEVICE_PATH_TYPE_MESSAGING_DEVICE: + str = dp_msging(str, dp); + break; + case DEVICE_PATH_TYPE_MEDIA_DEVICE: + str = dp_media(str, dp); + break; + default: + str = dp_unknown(str, dp); + } + + dp = efi_dp_next(dp); } - return buffer; + *str++ = '\0'; + + len = str - buf; + r = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES, 2 * len, (void **)&out); + if (r != EFI_SUCCESS) + return NULL; + + ascii2unicode(out, buf); + out[len - 1] = 0; + + return out; } +/* helper for debug prints.. efi_free_pool() the result. */ +uint16_t *efi_dp_str(struct efi_device_path *dp) +{ + return efi_convert_device_node_to_text(dp, true, true); +} + + static uint16_t EFIAPI *efi_convert_device_node_to_text_ext( struct efi_device_path *device_node, bool display_only, From patchwork Sun Sep 10 11:21:33 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Rob Clark X-Patchwork-Id: 812115 X-Patchwork-Delegate: trini@ti.com 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="g5IM3Dtv"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3xqpt84D2Pz9sDB for ; Sun, 10 Sep 2017 21:36:32 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 2A5A0C21E8C; Sun, 10 Sep 2017 11:27:12 +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 EF2FCC21F44; Sun, 10 Sep 2017 11:24:25 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id A5BE6C21F28; Sun, 10 Sep 2017 11:23:09 +0000 (UTC) Received: from mail-qk0-f193.google.com (mail-qk0-f193.google.com [209.85.220.193]) by lists.denx.de (Postfix) with ESMTPS id DF189C21EBF for ; Sun, 10 Sep 2017 11:23:02 +0000 (UTC) Received: by mail-qk0-f193.google.com with SMTP id c69so3970239qke.5 for ; Sun, 10 Sep 2017 04:23:02 -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 :mime-version:content-transfer-encoding; bh=Y9Zc0Nv79pXQfDgDO26uLmB5Oesm4aAENBswlPKEk6U=; b=g5IM3Dtv4U4AkacmpI01t7FWK/azE2ZgRMDHZD6YvG905QG7D2HIvFDMX+5jbJ70+x Ueu6KlkXNtPE8/RNlRyrE+kN/cj3G3aNEnKEyhg3SLpmJIjq1k+FBTOxWSrymsohdK+O G/8i2KANuhBObTmfX+TyJ2kIiLPUW3VjqzYIzDNr4HNdNxBLnKVyl+0YDSmNJ+QJzRyt mEb8eEGlgP88swb+P5RoZfUbX0ICVBU2+7HIiWrKzxyLM0isrwjR8Lsb7eGcRpJp6h+0 yN8HywmQuoiyhTCE+nLy7FtOu/1Z0ZQwTKywcf7uFYN4adT7LPs6E8vKN9QwARYbL6Q1 HzWw== 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:mime-version:content-transfer-encoding; bh=Y9Zc0Nv79pXQfDgDO26uLmB5Oesm4aAENBswlPKEk6U=; b=CsLdd9KWtIvXPstaIXUc30NlnreeDms57W3QgfE2JRaA7xwYPmbVfhHKsvfNdcX0Kg C4XvHpXf0HHkOh7DoZtmESCEQYMQ3Qnwn2W4KSNEImjfvW2EVH4n1Cljxv63olvj9CcO rxfxFOJubdASzfBR8jSvybupCO2hMldELeB85Lm1Q4auVitdfJYvt9/53+YLX5nJFZWg r7K9rvJe1LMdjsIKTaZ0Onn6rvN19FkMLOLozh2L5o9N67GPciVajhZICPSlX8I1TbUx whNOkTryeXoj4MKThIs34AgfBy/1sd71YYhIoYtuJaJHD84hHXkK6fXTlxv90IXQwr4C pByw== X-Gm-Message-State: AHPjjUhjKC9/21q+qI6qYNu8o3aPt/n8bqv0nl2RqIsdTDE463Cd5GSI 4texuY2YYcrb0hK//4o= X-Google-Smtp-Source: AOwi7QDsmbSfHv448a/Gw6Jb5hMCdkTJGZMmOg4uFRTNjtvavTOgxeTkVtnZrZZk/+dcltiCgue0Vg== X-Received: by 10.55.75.8 with SMTP id y8mr10023302qka.255.1505042581565; Sun, 10 Sep 2017 04:23:01 -0700 (PDT) Received: from localhost ([2601:184:4780:aac0:25f8:dd96:a084:785a]) by smtp.gmail.com with ESMTPSA id p60sm4231329qtd.93.2017.09.10.04.22.59 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sun, 10 Sep 2017 04:23:00 -0700 (PDT) From: Rob Clark To: U-Boot Mailing List Date: Sun, 10 Sep 2017 07:21:33 -0400 Message-Id: <20170910112149.21358-17-robdclark@gmail.com> X-Mailer: git-send-email 2.13.5 In-Reply-To: <20170910112149.21358-1-robdclark@gmail.com> References: <20170910112149.21358-1-robdclark@gmail.com> MIME-Version: 1.0 Cc: Stephen Warren , Heinrich Schuchardt , Philipp Skadorov , Genevieve Chan , Tien Fong Chee Subject: [U-Boot] [PATCH v3 8/9] fs/fat: fix case for FAT shortnames 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: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" Noticed when comparing our output to linux. There are some lcase bits which control whether filename and/or extension should be downcase'd. Signed-off-by: Rob Clark Reviewed-by: Łukasz Majewski --- fs/fat/fat.c | 16 ++++++++++------ fs/fat/fat_write.c | 4 ++-- include/fat.h | 6 +++++- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/fs/fat/fat.c b/fs/fat/fat.c index c951d84f57..65873a2c2a 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -29,11 +29,13 @@ static const int vfat_enabled = 0; #endif /* - * Convert a string to lowercase. + * Convert a string to lowercase. Converts at most 'len' characters, + * 'len' may be larger than the length of 'str' if 'str' is NULL + * terminated. */ -static void downcase(char *str) +static void downcase(char *str, size_t len) { - while (*str != '\0') { + while (*str != '\0' && len--) { *str = tolower(*str); str++; } @@ -131,10 +133,13 @@ static void get_name(dir_entry *dirent, char *s_name) ptr = s_name; while (*ptr && *ptr != ' ') ptr++; + if (dirent->lcase & CASE_LOWER_BASE) + downcase(s_name, (unsigned)(ptr - s_name)); if (dirent->ext[0] && dirent->ext[0] != ' ') { - *ptr = '.'; - ptr++; + *ptr++ = '.'; memcpy(ptr, dirent->ext, 3); + if (dirent->lcase & CASE_LOWER_EXT) + downcase(ptr, 3); ptr[3] = '\0'; while (*ptr && *ptr != ' ') ptr++; @@ -144,7 +149,6 @@ static void get_name(dir_entry *dirent, char *s_name) *s_name = '\0'; else if (*s_name == aRING) *s_name = DELETED_FLAG; - downcase(s_name); } static int flush_dirty_fat_buffer(fsdata *mydata); diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c index 4ca024c208..d0468baf8f 100644 --- a/fs/fat/fat_write.c +++ b/fs/fat/fat_write.c @@ -345,7 +345,7 @@ get_long_file_name(fsdata *mydata, int curclust, __u8 *cluster, *l_name = '\0'; else if (*l_name == aRING) *l_name = DELETED_FLAG; - downcase(l_name); + downcase(l_name, INT_MAX); /* Return the real directory entry */ *retdent = realdent; @@ -981,7 +981,7 @@ static int do_fat_write(const char *filename, void *buffer, loff_t size, memcpy(l_filename, filename, name_len); l_filename[name_len] = 0; /* terminate the string */ - downcase(l_filename); + downcase(l_filename, INT_MAX); startsect = mydata->rootdir_sect; retdent = find_directory_entry(mydata, startsect, diff --git a/include/fat.h b/include/fat.h index 83cd90017e..0f58939124 100644 --- a/include/fat.h +++ b/include/fat.h @@ -128,10 +128,14 @@ typedef struct volume_info /* Boot sign comes last, 2 bytes */ } volume_info; +/* see dir_entry::lcase: */ +#define CASE_LOWER_BASE 8 /* base (name) is lower case */ +#define CASE_LOWER_EXT 16 /* extension is lower case */ + typedef struct dir_entry { char name[8],ext[3]; /* Name and extension */ __u8 attr; /* Attribute bits */ - __u8 lcase; /* Case for base and extension */ + __u8 lcase; /* Case for name and ext (CASE_LOWER_x) */ __u8 ctime_ms; /* Creation time, milliseconds */ __u16 ctime; /* Creation time */ __u16 cdate; /* Creation date */ From patchwork Sun Sep 10 11:21:34 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Clark X-Patchwork-Id: 812103 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="tT1fSq/F"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3xqphW4Zcbz9sDB for ; Sun, 10 Sep 2017 21:28:11 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 5D399C21DDF; Sun, 10 Sep 2017 11:25:29 +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 8B161C21EA8; Sun, 10 Sep 2017 11:23:38 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 6501DC21EA8; Sun, 10 Sep 2017 11:23:12 +0000 (UTC) Received: from mail-qt0-f193.google.com (mail-qt0-f193.google.com [209.85.216.193]) by lists.denx.de (Postfix) with ESMTPS id 28D37C21E3C for ; Sun, 10 Sep 2017 11:23:06 +0000 (UTC) Received: by mail-qt0-f193.google.com with SMTP id q8so4090087qtb.1 for ; Sun, 10 Sep 2017 04:23:06 -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=q0Qolx1SkIrEQb3hYqzrxMkSkrB0yBal+ZscwQZLcmY=; b=tT1fSq/FDkqcK4ELUNEXlBhtpzTFkynWc3bL1mrvNrWLtHVtXwZK9iuvV+jdxdciAs 7I+5JuTH/jY9I3mp5F2bpa4RaCcOEndTJaXQndvj8qCS4Q1xSf0N6bhSL9gT3Bb0V609 sN1E4MYzOvqkqBOcJXGTmwVLcVvleAQVZZiSsil7MNQOgzyxAwZFpUSyahtt+EpQ57qG y2hXQIlUfSy0kY5Nc3fpaIyL+92a42i2uqVnYuFyBrJGII1yYDe3bxuWrPJ/Z5jR10Jq NsYAIzJ4/69o2k6M/srfYO6hD6YlK5w9X+3h7+0o46Fz+nVSwCWLjXvqKu15GzK4rkSa h84A== 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=q0Qolx1SkIrEQb3hYqzrxMkSkrB0yBal+ZscwQZLcmY=; b=nghfU//d5L/tS+5XFgMof1JKhuBoc0eqV9YUSmdVH5CoZGm5pkopDNDQ66YAeime5l UxnAqzhqSY9ZAWFlTLfMgFq+qR0JsF5lIgZGJohlnnqGUMhUPr0rJ7itHB/zL+zapsY4 sS0tq/jjZOmmn5wGYQOqiWxGj6ivngx2aE4mfdQM+fGBQaDOROwTLk0PQezMXmy1SPqu 3X3UMELik4uFfTm5yJX73Tzv7wkHZF/QophngXwcVvNwP3J63gC+1dQ5BFFgZpDaffIR 1Im8hstFZp0cjSX9Jlu/LA9CGDd8GRFHtwqaly6YwmwBIzFU1FmZCHeFOYjMxJI3WU3A RUzQ== X-Gm-Message-State: AHPjjUhf8dXJnfYNGWrwFHH2GpV+bfcL4QDA0uKaKBsFx3FMw1vuIvMs VZ8a7SQcjYreU+mnRYc= X-Google-Smtp-Source: AOwi7QA3lIYJLcewfedlpgddVabOXgJUnHnt8dhPstCFxNpxM7e1VjRvWQQMjInmrtLgz3+lt+mBEA== X-Received: by 10.237.36.205 with SMTP id u13mr12543745qtc.75.1505042584901; Sun, 10 Sep 2017 04:23:04 -0700 (PDT) Received: from localhost ([2601:184:4780:aac0:25f8:dd96:a084:785a]) by smtp.gmail.com with ESMTPSA id a12sm4366604qta.3.2017.09.10.04.23.03 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sun, 10 Sep 2017 04:23:03 -0700 (PDT) From: Rob Clark To: U-Boot Mailing List Date: Sun, 10 Sep 2017 07:21:34 -0400 Message-Id: <20170910112149.21358-18-robdclark@gmail.com> X-Mailer: git-send-email 2.13.5 In-Reply-To: <20170910112149.21358-1-robdclark@gmail.com> References: <20170910112149.21358-1-robdclark@gmail.com> Cc: Heinrich Schuchardt Subject: [U-Boot] [PATCH v2 09/21] efi_loader: use proper device-paths for net 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" Signed-off-by: Rob Clark --- lib/efi_loader/efi_net.c | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/lib/efi_loader/efi_net.c b/lib/efi_loader/efi_net.c index 0b949d86e8..aa0618fd3a 100644 --- a/lib/efi_loader/efi_net.c +++ b/lib/efi_loader/efi_net.c @@ -26,9 +26,6 @@ struct efi_net_obj { /* EFI Interface callback struct for network */ struct efi_simple_network net; struct efi_simple_network_mode net_mode; - /* Device path to the network adapter */ - struct efi_device_path_mac_addr dp_mac; - struct efi_device_path_file_path dp_end; /* PXE struct to transmit dhcp data */ struct efi_pxe pxe; struct efi_pxe_mode pxe_mode; @@ -213,16 +210,6 @@ void efi_net_set_dhcp_ack(void *pkt, int len) int efi_net_register(void **handle) { struct efi_net_obj *netobj; - struct efi_device_path_mac_addr dp_net = { - .dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE, - .dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR, - .dp.length = sizeof(dp_net), - }; - struct efi_device_path_file_path dp_end = { - .dp.type = DEVICE_PATH_TYPE_END, - .dp.sub_type = DEVICE_PATH_SUB_TYPE_END, - .dp.length = sizeof(dp_end), - }; if (!eth_get_dev()) { /* No eth device active, don't expose any */ @@ -236,7 +223,8 @@ int efi_net_register(void **handle) netobj->parent.protocols[0].guid = &efi_net_guid; netobj->parent.protocols[0].protocol_interface = &netobj->net; netobj->parent.protocols[1].guid = &efi_guid_device_path; - netobj->parent.protocols[1].protocol_interface = &netobj->dp_mac; + netobj->parent.protocols[1].protocol_interface = + efi_dp_from_eth(); netobj->parent.protocols[2].guid = &efi_pxe_guid; netobj->parent.protocols[2].protocol_interface = &netobj->pxe; netobj->parent.handle = &netobj->net; @@ -255,9 +243,6 @@ int efi_net_register(void **handle) netobj->net.receive = efi_net_receive; netobj->net.mode = &netobj->net_mode; netobj->net_mode.state = EFI_NETWORK_STARTED; - netobj->dp_mac = dp_net; - netobj->dp_end = dp_end; - memcpy(netobj->dp_mac.mac.addr, eth_get_ethaddr(), 6); memcpy(netobj->net_mode.current_address.mac_addr, eth_get_ethaddr(), 6); netobj->net_mode.max_packet_size = PKTSIZE; From patchwork Sun Sep 10 11:21:36 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Clark X-Patchwork-Id: 812111 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="UHYDqa4X"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3xqprj0Zjbz9sDB for ; Sun, 10 Sep 2017 21:35:17 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id D742CC21F5B; Sun, 10 Sep 2017 11:30:57 +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 402A7C21F3C; Sun, 10 Sep 2017 11:27:41 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 6ECC7C21F01; Sun, 10 Sep 2017 11:23:40 +0000 (UTC) Received: from mail-qt0-f196.google.com (mail-qt0-f196.google.com [209.85.216.196]) by lists.denx.de (Postfix) with ESMTPS id 160F9C21E0F for ; Sun, 10 Sep 2017 11:23:33 +0000 (UTC) Received: by mail-qt0-f196.google.com with SMTP id q8so4090410qtb.1 for ; Sun, 10 Sep 2017 04:23:33 -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=GKVPX3C6Z1ZPcvHI1fm+8gyMoefAOck5Gls/3FNNXDk=; b=UHYDqa4Xf4uq/MoXDYCfBKrsGnAPRHPLM0SVQE/YkTBJsk34xps4irqAt9XXavF+g5 5qYJ8z6swj1SZh2jFAbAWIXSnVqoxdgF1EB2eA2qFq2PEKzvwbWREtS1Cjipoba6TfDv B5BlOjTTpuky2+km8dKSaNwBt8behqCcm8L3bQLiDcnBXgK9KtH+Ltpct7AtobEY3Rl3 J4RrGt34+YCwnBdnPeppxlqt79uGlGD8RjgiFYQvIrbQ427iTB7rLk0q5ktPgctzlk0U wv3vt5hrxo9bpFxgGKFhgI3gfanUJlqnY8Z0LcdhbglI9QaUImaI0WC2nMyXztwVv4J3 HZCg== 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=GKVPX3C6Z1ZPcvHI1fm+8gyMoefAOck5Gls/3FNNXDk=; b=fu7K8sG5ks/bGMoKELwuQ3HpiyEQfot41G//RPN476l6qWtn30Oq0/VhBoCSJSEbzY DyOYeGNVzymLeRExaJ/ENVm1tvy4XK7FtvkPiiuG3nrm42kgGbrdFQ2d98V3dskEG/il HVNQEaW1pxfjQNBtwvqtxjEmy/sL/Jl4vVooI1nMQ/HFHlLSeolyBJuO0ERt3h+bAgf9 jtY9RRbUhoJ2aD6midRsHZnQfDcaZMGAeqMpAxqq4OMEE27us3LCN82H/MM48SpWjfQJ AOr/UnSPr+plDy9QEEMaiUjIl4d+Spn01vxpmoR07osvP1ip8aPctop/qbNQpsSRv3Av uPtA== X-Gm-Message-State: AHPjjUjzYhkmpTp0Q9w8+79Sa9qKBRFzck4aGDKulj5QmYBDHxAyqopJ lFCdry7aeBCZwS49aKo= X-Google-Smtp-Source: AOwi7QBQf4XoswbBELHY4e8CRrOJw2H5Zc+S4nbg8Wrg5RYmk8Ph3HVs8LYRx0NTaUzebf+9vCKzbg== X-Received: by 10.237.36.205 with SMTP id u13mr12544966qtc.75.1505042611660; Sun, 10 Sep 2017 04:23:31 -0700 (PDT) Received: from localhost ([2601:184:4780:aac0:25f8:dd96:a084:785a]) by smtp.gmail.com with ESMTPSA id f20sm4477342qta.86.2017.09.10.04.23.30 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sun, 10 Sep 2017 04:23:30 -0700 (PDT) From: Rob Clark To: U-Boot Mailing List Date: Sun, 10 Sep 2017 07:21:36 -0400 Message-Id: <20170910112149.21358-20-robdclark@gmail.com> X-Mailer: git-send-email 2.13.5 In-Reply-To: <20170910112149.21358-1-robdclark@gmail.com> References: <20170910112149.21358-1-robdclark@gmail.com> Cc: Heinrich Schuchardt Subject: [U-Boot] [PATCH v2 10/21] efi_loader: refactor boot device and loaded_image handling 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" Get rid of the hacky fake boot-device and duplicate device-path constructing (which needs to match what efi_disk and efi_net do). Instead convert over to use efi_device_path helpers to construct device-paths, and use that to look up the actual boot device. Also, extract out a helper to plug things in properly to the loaded_image. In a following patch we'll want to re-use this in efi_load_image() to handle the case of loading an image from a file_path. Signed-off-by: Rob Clark --- cmd/bootefi.c | 201 +++++++++++++----------------------------- include/efi_loader.h | 5 +- lib/efi_loader/efi_boottime.c | 36 ++++++++ lib/efi_loader/efi_net.c | 5 +- 4 files changed, 100 insertions(+), 147 deletions(-) diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 3196d86040..0980088668 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -22,97 +22,14 @@ DECLARE_GLOBAL_DATA_PTR; static uint8_t efi_obj_list_initalized; -/* - * When booting using the "bootefi" command, we don't know which - * physical device the file came from. So we create a pseudo-device - * called "bootefi" with the device path /bootefi. - * - * In addition to the originating device we also declare the file path - * of "bootefi" based loads to be /bootefi. - */ -static struct efi_device_path_file_path bootefi_image_path[] = { - { - .dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE, - .dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH, - .dp.length = sizeof(bootefi_image_path[0]), - .str = { 'b','o','o','t','e','f','i' }, - }, { - .dp.type = DEVICE_PATH_TYPE_END, - .dp.sub_type = DEVICE_PATH_SUB_TYPE_END, - .dp.length = sizeof(bootefi_image_path[0]), - } -}; - -static struct efi_device_path_file_path bootefi_device_path[] = { - { - .dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE, - .dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH, - .dp.length = sizeof(bootefi_image_path[0]), - .str = { 'b','o','o','t','e','f','i' }, - }, { - .dp.type = DEVICE_PATH_TYPE_END, - .dp.sub_type = DEVICE_PATH_SUB_TYPE_END, - .dp.length = sizeof(bootefi_image_path[0]), - } -}; - -/* The EFI loaded_image interface for the image executed via "bootefi" */ -static struct efi_loaded_image loaded_image_info = { - .device_handle = bootefi_device_path, - .file_path = bootefi_image_path, -}; - -/* The EFI object struct for the image executed via "bootefi" */ -static struct efi_object loaded_image_info_obj = { - .handle = &loaded_image_info, - .protocols = { - { - /* - * When asking for the loaded_image interface, just - * return handle which points to loaded_image_info - */ - .guid = &efi_guid_loaded_image, - .protocol_interface = &loaded_image_info, - }, - { - /* - * When asking for the device path interface, return - * bootefi_device_path - */ - .guid = &efi_guid_device_path, - .protocol_interface = bootefi_device_path, - }, - { - .guid = &efi_guid_console_control, - .protocol_interface = (void *) &efi_console_control - }, - { - .guid = &efi_guid_device_path_to_text_protocol, - .protocol_interface = (void *) &efi_device_path_to_text - }, - }, -}; - -/* The EFI object struct for the device the "bootefi" image was loaded from */ -static struct efi_object bootefi_device_obj = { - .handle = bootefi_device_path, - .protocols = { - { - /* When asking for the device path interface, return - * bootefi_device_path */ - .guid = &efi_guid_device_path, - .protocol_interface = bootefi_device_path - } - }, -}; +static struct efi_device_path *bootefi_image_path; +static struct efi_device_path *bootefi_device_path; /* Initialize and populate EFI object list */ static void efi_init_obj_list(void) { efi_obj_list_initalized = 1; - list_add_tail(&loaded_image_info_obj.link, &efi_obj_list); - list_add_tail(&bootefi_device_obj.link, &efi_obj_list); efi_console_register(); #ifdef CONFIG_PARTITIONS efi_disk_register(); @@ -121,13 +38,7 @@ static void efi_init_obj_list(void) efi_gop_register(); #endif #ifdef CONFIG_NET - void *nethandle = loaded_image_info.device_handle; - efi_net_register(&nethandle); - - if (!memcmp(bootefi_device_path[0].str, "N\0e\0t", 6)) - loaded_image_info.device_handle = nethandle; - else - loaded_image_info.device_handle = bootefi_device_path; + efi_net_register(); #endif #ifdef CONFIG_GENERATE_SMBIOS_TABLE efi_smbios_register(); @@ -210,14 +121,27 @@ static unsigned long efi_run_in_el2(asmlinkage ulong (*entry)( * Load an EFI payload into a newly allocated piece of memory, register all * EFI objects it would want to access and jump to it. */ -static unsigned long do_bootefi_exec(void *efi, void *fdt) +static unsigned long do_bootefi_exec(void *efi, void *fdt, + struct efi_device_path *device_path, + struct efi_device_path *image_path) { + struct efi_loaded_image loaded_image_info = {}; + struct efi_object loaded_image_info_obj = {}; + ulong ret; + ulong (*entry)(void *image_handle, struct efi_system_table *st) asmlinkage; ulong fdt_pages, fdt_size, fdt_start, fdt_end; const efi_guid_t fdt_guid = EFI_FDT_GUID; bootm_headers_t img = { 0 }; + /* Initialize and populate EFI object list */ + if (!efi_obj_list_initalized) + efi_init_obj_list(); + + efi_setup_loaded_image(&loaded_image_info, &loaded_image_info_obj, + device_path, image_path); + /* * gd lives in a fixed register which may get clobbered while we execute * the payload. So save it here and restore it on every callback entry @@ -252,18 +176,18 @@ static unsigned long do_bootefi_exec(void *efi, void *fdt) /* Load the EFI payload */ entry = efi_load_pe(efi, &loaded_image_info); - if (!entry) - return -ENOENT; - - /* Initialize and populate EFI object list */ - if (!efi_obj_list_initalized) - efi_init_obj_list(); + if (!entry) { + ret = -ENOENT; + goto exit; + } /* Call our payload! */ debug("%s:%d Jumping to 0x%lx\n", __func__, __LINE__, (long)entry); if (setjmp(&loaded_image_info.exit_jmp)) { - return loaded_image_info.exit_status; + ret = loaded_image_info.exit_status; + EFI_EXIT(ret); + goto exit; } #ifdef CONFIG_ARM64 @@ -282,7 +206,13 @@ static unsigned long do_bootefi_exec(void *efi, void *fdt) } #endif - return efi_do_enter(&loaded_image_info, &systab, entry); + ret = efi_do_enter(&loaded_image_info, &systab, entry); + +exit: + /* image has returned, loaded-image obj goes *poof*: */ + list_del(&loaded_image_info_obj.link); + + return ret; } @@ -315,7 +245,8 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } printf("## Starting EFI application at %08lx ...\n", addr); - r = do_bootefi_exec((void *)addr, (void*)fdt_addr); + r = do_bootefi_exec((void *)addr, (void *)fdt_addr, + bootefi_device_path, bootefi_image_path); printf("## Application terminated, r = %lu\n", r & ~EFI_ERROR_MASK); @@ -344,58 +275,44 @@ U_BOOT_CMD( bootefi_help_text ); -void efi_set_bootdev(const char *dev, const char *devnr, const char *path) +static int parse_partnum(const char *devnr) { - __maybe_unused struct blk_desc *desc; - char devname[32] = { 0 }; /* dp->str is u16[32] long */ - char *colon, *s; - -#if defined(CONFIG_BLK) || CONFIG_IS_ENABLED(ISO_PARTITION) - desc = blk_get_dev(dev, simple_strtol(devnr, NULL, 10)); -#endif - -#ifdef CONFIG_BLK - if (desc) { - snprintf(devname, sizeof(devname), "%s", desc->bdev->name); - } else -#endif - - { - /* Assemble the condensed device name we use in efi_disk.c */ - snprintf(devname, sizeof(devname), "%s%s", dev, devnr); + const char *str = strchr(devnr, ':'); + if (str) { + str++; + return simple_strtoul(str, NULL, 16); } + return 0; +} - colon = strchr(devname, ':'); - -#if CONFIG_IS_ENABLED(ISO_PARTITION) - /* For ISOs we create partition block devices */ - if (desc && (desc->type != DEV_TYPE_UNKNOWN) && - (desc->part_type == PART_TYPE_ISO)) { - if (!colon) - snprintf(devname, sizeof(devname), "%s:1", devname); +void efi_set_bootdev(const char *dev, const char *devnr, const char *path) +{ + char filename[32] = { 0 }; /* dp->str is u16[32] long */ + char *s; - colon = NULL; - } -#endif + if (strcmp(dev, "Net")) { + struct blk_desc *desc; + int part; - if (colon) - *colon = '\0'; + desc = blk_get_dev(dev, simple_strtol(devnr, NULL, 10)); + part = parse_partnum(devnr); - /* Patch bootefi_device_path to the target device */ - memset(bootefi_device_path[0].str, 0, sizeof(bootefi_device_path[0].str)); - ascii2unicode(bootefi_device_path[0].str, devname); + bootefi_device_path = efi_dp_from_part(desc, part); + } else { +#ifdef CONFIG_NET + bootefi_device_path = efi_dp_from_eth(); +#endif + } - /* Patch bootefi_image_path to the target file path */ - memset(bootefi_image_path[0].str, 0, sizeof(bootefi_image_path[0].str)); if (strcmp(dev, "Net")) { /* Add leading / to fs paths, because they're absolute */ - snprintf(devname, sizeof(devname), "/%s", path); + snprintf(filename, sizeof(filename), "/%s", path); } else { - snprintf(devname, sizeof(devname), "%s", path); + snprintf(filename, sizeof(filename), "%s", path); } /* DOS style file path: */ - s = devname; + s = filename; while ((s = strchr(s, '/'))) *s++ = '\\'; - ascii2unicode(bootefi_image_path[0].str, devname); + bootefi_image_path = efi_dp_from_file(NULL, 0, filename); } diff --git a/include/efi_loader.h b/include/efi_loader.h index f39c2ee6da..ec8803f588 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -136,7 +136,7 @@ int efi_disk_register(void); /* Called by bootefi to make GOP (graphical) interface available */ int efi_gop_register(void); /* Called by bootefi to make the network interface available */ -int efi_net_register(void **handle); +int efi_net_register(void); /* Called by bootefi to make SMBIOS tables available */ void efi_smbios_register(void); @@ -193,6 +193,9 @@ uint64_t efi_add_memory_map(uint64_t start, uint64_t pages, int memory_type, int efi_memory_init(void); /* Adds new or overrides configuration table entry to the system table */ efi_status_t efi_install_configuration_table(const efi_guid_t *guid, void *table); +void efi_setup_loaded_image(struct efi_loaded_image *info, struct efi_object *obj, + struct efi_device_path *device_path, + struct efi_device_path *file_path); #ifdef CONFIG_EFI_LOADER_BOUNCE_BUFFER extern void *efi_bounce_buffer; diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index b962b62a97..837e61d8fe 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -726,6 +726,42 @@ static efi_status_t EFIAPI efi_install_configuration_table_ext(efi_guid_t *guid, return EFI_EXIT(efi_install_configuration_table(guid, table)); } +/* Initialize a loaded_image_info + loaded_image_info object with correct + * protocols, boot-device, etc. + */ +void efi_setup_loaded_image(struct efi_loaded_image *info, struct efi_object *obj, + struct efi_device_path *device_path, + struct efi_device_path *file_path) +{ + obj->handle = info; + + /* + * When asking for the device path interface, return + * bootefi_device_path + */ + obj->protocols[0].guid = &efi_guid_device_path; + obj->protocols[0].protocol_interface = device_path; + + /* + * When asking for the loaded_image interface, just + * return handle which points to loaded_image_info + */ + obj->protocols[1].guid = &efi_guid_loaded_image; + obj->protocols[1].protocol_interface = info; + + obj->protocols[2].guid = &efi_guid_console_control; + obj->protocols[2].protocol_interface = (void *)&efi_console_control; + + obj->protocols[3].guid = &efi_guid_device_path_to_text_protocol; + obj->protocols[3].protocol_interface = + (void *)&efi_device_path_to_text; + + info->file_path = file_path; + info->device_handle = efi_dp_find_obj(device_path, NULL); + + list_add_tail(&obj->link, &efi_obj_list); +} + static efi_status_t EFIAPI efi_load_image(bool boot_policy, efi_handle_t parent_image, struct efi_device_path *file_path, diff --git a/lib/efi_loader/efi_net.c b/lib/efi_loader/efi_net.c index aa0618fd3a..91f1e4a69e 100644 --- a/lib/efi_loader/efi_net.c +++ b/lib/efi_loader/efi_net.c @@ -207,7 +207,7 @@ void efi_net_set_dhcp_ack(void *pkt, int len) } /* This gets called from do_bootefi_exec(). */ -int efi_net_register(void **handle) +int efi_net_register(void) { struct efi_net_obj *netobj; @@ -253,8 +253,5 @@ int efi_net_register(void **handle) /* Hook net up to the device list */ list_add_tail(&netobj->parent.link, &efi_obj_list); - if (handle) - *handle = &netobj->net; - return 0; } From patchwork Sun Sep 10 11:21:37 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Clark X-Patchwork-Id: 812117 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="rTB6oWZA"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3xqpwC1LyYz9sDB for ; Sun, 10 Sep 2017 21:38:19 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id DF4ACC21F8B; Sun, 10 Sep 2017 11:28:31 +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 F0AA0C21F21; Sun, 10 Sep 2017 11:25:14 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 70277C21E0E; Sun, 10 Sep 2017 11:23:44 +0000 (UTC) Received: from mail-qt0-f180.google.com (mail-qt0-f180.google.com [209.85.216.180]) by lists.denx.de (Postfix) with ESMTPS id A554EC21F2C for ; Sun, 10 Sep 2017 11:23:36 +0000 (UTC) Received: by mail-qt0-f180.google.com with SMTP id s18so12589529qta.3 for ; Sun, 10 Sep 2017 04:23:36 -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=6HvBct8q6psLtX5Ntu8lA4vBKmA7RUhiz1i0vjYcfNc=; b=rTB6oWZAYRJJbONNATWe1kCNq8HdYrIuS8n3UsL4zDTEDJju22XcCSnm8INFZiaCG/ iLIMRG0qDFZGBHTttbtEmBmLtbRxgcvw1n9MnzRMLuLFBhY/DfrlM5e/517bnKHJI5dr tcegFe2JnJa0cCvfCvJ2GYZ16bphZMoSjfOpaQXPjedj2+hsMYFDaUDEc2m16JB5VO5+ KRycAmRKBCEqSdvwzrRMTAeQzLuBrcPZDcdIvpK/TjgkVbWHZiYhrCzJrO/pFxAXMu/B 3eU6Z8SxhFfjTOVG9Iivg1QLlrd1s0cJPZzl9M7jNfYERfXWwDzsXZmdyKM9lnqhdUBq 2X1Q== 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=6HvBct8q6psLtX5Ntu8lA4vBKmA7RUhiz1i0vjYcfNc=; b=ffle5UFfMcZ3Q8HQbR+E/zEz1LB/+CryACHmGNB/gn32Vxj0qNwJCJat3+uDHzTPIQ BdYraR5MUfBY8PtEFVh8ow3KIZYQAuIRTjPbZoF/t70JJe31+KZpWjFuhx7PoAWR8Kne I0SKVfIsnd8OTKoEXT6ISfkrY37brHH9AIIs6BZYMdQM7xZR8kSCtugfIClt92FrxQjx L3ndKWbnAwcVLBYOawUl7kDz2jBCfg/QEWrsdM9zXfuuKqlvug+OTbPYYIB4Ho65SvXg AVeNzA7Hzi3OiYsmb6tkPOWihVtA1n6oKtqkFipbrYcB92Cdx0rwQHS/m1+bMyEuVOMT wztA== X-Gm-Message-State: AHPjjUhqfL9RG2D7aHakZ4XatxtSsZnucUJH3K1t1C5ZPFRzgOVO8lRC 2TNWp96uOWAgpKFpcjc= X-Google-Smtp-Source: AOwi7QBWVOPIwI2JDZnMvU3GAzfEZjldfU0tDtykjER+LNjkrzLjUzIF4MA2NUhsypYdytTgkII0sA== X-Received: by 10.200.44.167 with SMTP id 36mr179437qtw.285.1505042615151; Sun, 10 Sep 2017 04:23:35 -0700 (PDT) Received: from localhost ([2601:184:4780:aac0:25f8:dd96:a084:785a]) by smtp.gmail.com with ESMTPSA id t17sm4505438qtc.45.2017.09.10.04.23.33 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sun, 10 Sep 2017 04:23:34 -0700 (PDT) From: Rob Clark To: U-Boot Mailing List Date: Sun, 10 Sep 2017 07:21:37 -0400 Message-Id: <20170910112149.21358-21-robdclark@gmail.com> X-Mailer: git-send-email 2.13.5 In-Reply-To: <20170910112149.21358-1-robdclark@gmail.com> References: <20170910112149.21358-1-robdclark@gmail.com> Cc: Heinrich Schuchardt , Peter Jones Subject: [U-Boot] [PATCH v2 11/21] efi_loader: add file/filesys support 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" fallback.efi (and probably other things) use UEFI's simple-file-system protocol and file support to search for OS's to boot. Signed-off-by: Rob Clark --- include/efi.h | 2 + include/efi_api.h | 65 +++++ include/efi_loader.h | 13 + lib/efi_loader/Makefile | 1 + lib/efi_loader/efi_disk.c | 32 +++ lib/efi_loader/efi_file.c | 556 ++++++++++++++++++++++++++++++++++++++ lib/efi_loader/efi_image_loader.c | 3 + 7 files changed, 672 insertions(+) create mode 100644 lib/efi_loader/efi_file.c diff --git a/include/efi.h b/include/efi.h index 87b0b43f20..ddd2b96417 100644 --- a/include/efi.h +++ b/include/efi.h @@ -81,6 +81,8 @@ typedef struct { #define EFI_IP_ADDRESS_CONFLICT (EFI_ERROR_MASK | 34) #define EFI_HTTP_ERROR (EFI_ERROR_MASK | 35) +#define EFI_WARN_DELETE_FAILURE 2 + typedef unsigned long efi_status_t; typedef u64 efi_physical_addr_t; typedef u64 efi_virtual_addr_t; diff --git a/include/efi_api.h b/include/efi_api.h index 0c36122107..1aae96355f 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -666,4 +666,69 @@ struct efi_pxe { struct efi_pxe_mode *mode; }; +#define EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID \ + EFI_GUID(0x964e5b22, 0x6459, 0x11d2, \ + 0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b) +#define EFI_FILE_PROTOCOL_REVISION 0x00010000 + +struct efi_file_handle { + u64 rev; + efi_status_t (EFIAPI *open)(struct efi_file_handle *file, + struct efi_file_handle **new_handle, + s16 *file_name, u64 open_mode, u64 attributes); + efi_status_t (EFIAPI *close)(struct efi_file_handle *file); + efi_status_t (EFIAPI *delete)(struct efi_file_handle *file); + efi_status_t (EFIAPI *read)(struct efi_file_handle *file, + u64 *buffer_size, void *buffer); + efi_status_t (EFIAPI *write)(struct efi_file_handle *file, + u64 *buffer_size, void *buffer); + efi_status_t (EFIAPI *getpos)(struct efi_file_handle *file, + u64 *pos); + efi_status_t (EFIAPI *setpos)(struct efi_file_handle *file, + u64 pos); + efi_status_t (EFIAPI *getinfo)(struct efi_file_handle *file, + efi_guid_t *info_type, u64 *buffer_size, void *buffer); + efi_status_t (EFIAPI *setinfo)(struct efi_file_handle *file, + efi_guid_t *info_type, u64 buffer_size, void *buffer); + efi_status_t (EFIAPI *flush)(struct efi_file_handle *file); +}; + +#define EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID \ + EFI_GUID(0x964e5b22, 0x6459, 0x11d2, \ + 0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b) +#define EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION 0x00010000 + +struct efi_simple_file_system_protocol { + u64 rev; + efi_status_t (EFIAPI *open_volume)(struct efi_simple_file_system_protocol *this, + struct efi_file_handle **root); +}; + +#define EFI_FILE_INFO_GUID \ + EFI_GUID(0x9576e92, 0x6d3f, 0x11d2, \ + 0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b) + +#define EFI_FILE_MODE_READ 0x0000000000000001 +#define EFI_FILE_MODE_WRITE 0x0000000000000002 +#define EFI_FILE_MODE_CREATE 0x8000000000000000 + +#define EFI_FILE_READ_ONLY 0x0000000000000001 +#define EFI_FILE_HIDDEN 0x0000000000000002 +#define EFI_FILE_SYSTEM 0x0000000000000004 +#define EFI_FILE_RESERVED 0x0000000000000008 +#define EFI_FILE_DIRECTORY 0x0000000000000010 +#define EFI_FILE_ARCHIVE 0x0000000000000020 +#define EFI_FILE_VALID_ATTR 0x0000000000000037 + +struct efi_file_info { + u64 size; + u64 file_size; + u64 physical_size; + struct efi_time create_time; + struct efi_time last_access_time; + struct efi_time modification_time; + u64 attribute; + s16 file_name[0]; +}; + #endif diff --git a/include/efi_loader.h b/include/efi_loader.h index ec8803f588..b0c1e8fb78 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -65,6 +65,8 @@ extern const efi_guid_t efi_guid_console_control; extern const efi_guid_t efi_guid_device_path; extern const efi_guid_t efi_guid_loaded_image; extern const efi_guid_t efi_guid_device_path_to_text_protocol; +extern const efi_guid_t efi_simple_file_system_protocol_guid; +extern const efi_guid_t efi_file_info_guid; extern unsigned int __efi_runtime_start, __efi_runtime_stop; extern unsigned int __efi_runtime_rel_start, __efi_runtime_rel_stop; @@ -140,6 +142,9 @@ int efi_net_register(void); /* Called by bootefi to make SMBIOS tables available */ void efi_smbios_register(void); +struct efi_simple_file_system_protocol * +efi_fs_from_path(struct efi_device_path *fp); + /* Called by networking code to memorize the dhcp ack package */ void efi_net_set_dhcp_ack(void *pkt, int len); @@ -168,6 +173,14 @@ efi_status_t efi_set_timer(struct efi_event *event, enum efi_timer_delay type, /* Call this to signal an event */ void efi_signal_event(struct efi_event *event); +/* open file system: */ +struct efi_simple_file_system_protocol *efi_simple_file_system( + struct blk_desc *desc, int part, struct efi_device_path *dp); + +/* open file from device-path: */ +struct efi_file_handle *efi_file_from_path(struct efi_device_path *fp); + + /* Generic EFI memory allocator, call this to get memory */ void *efi_alloc(uint64_t len, int memory_type); /* More specific EFI memory allocator, called by EFI payloads */ diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile index f35e5ce8a8..cce92cfeb5 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -16,6 +16,7 @@ always := $(efiprogs-y) obj-$(CONFIG_CMD_BOOTEFI_HELLO) += helloworld_efi.o obj-y += efi_image_loader.o efi_boottime.o efi_runtime.o efi_console.o obj-y += efi_memory.o efi_device_path_to_text.o efi_device_path.o +obj-y += efi_file.o obj-$(CONFIG_LCD) += efi_gop.o obj-$(CONFIG_DM_VIDEO) += efi_gop.o obj-$(CONFIG_PARTITIONS) += efi_disk.o diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index 14f3e020c8..9805585eb1 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -31,6 +31,8 @@ struct efi_disk_obj { struct efi_device_path *dp; /* partition # */ unsigned part; + /* handle to filesys proto (for partition objects) */ + struct efi_simple_file_system_protocol *volume; /* Offset into disk for simple partitions */ lbaint_t offset; /* Internal block device */ @@ -172,6 +174,28 @@ static const struct efi_block_io block_io_disk_template = { .flush_blocks = &efi_disk_flush_blocks, }; +/* + * Find filesystem from a device-path. The passed in path 'p' probably + * contains one or more /File(name) nodes, so the comparison stops at + * the first /File() node, and returns the pointer to that via 'rp'. + * This is mostly intended to be a helper to map a device-path to an + * efi_file_handle object. + */ +struct efi_simple_file_system_protocol * +efi_fs_from_path(struct efi_device_path *fp) +{ + struct efi_object *efiobj; + struct efi_disk_obj *diskobj; + + efiobj = efi_dp_find_obj(fp, NULL); + if (!efiobj) + return NULL; + + diskobj = container_of(efiobj, struct efi_disk_obj, parent); + + return diskobj->volume; +} + static void efi_disk_add_dev(const char *name, const char *if_typename, struct blk_desc *desc, @@ -194,6 +218,14 @@ static void efi_disk_add_dev(const char *name, diskobj->parent.protocols[0].protocol_interface = &diskobj->ops; diskobj->parent.protocols[1].guid = &efi_guid_device_path; diskobj->parent.protocols[1].protocol_interface = diskobj->dp; + if (part >= 1) { + diskobj->volume = efi_simple_file_system(desc, part, + diskobj->dp); + diskobj->parent.protocols[2].guid = + &efi_simple_file_system_protocol_guid; + diskobj->parent.protocols[2].protocol_interface = + diskobj->volume; + } diskobj->parent.handle = diskobj; diskobj->ops = block_io_disk_template; diskobj->ifname = if_typename; diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c new file mode 100644 index 0000000000..118d83ad7c --- /dev/null +++ b/lib/efi_loader/efi_file.c @@ -0,0 +1,556 @@ +/* + * EFI utils + * + * Copyright (c) 2017 Rob Clark + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include + +struct file_system { + struct efi_simple_file_system_protocol base; + struct efi_device_path *dp; + struct blk_desc *desc; + int part; +}; +#define to_fs(x) container_of(x, struct file_system, base) + +struct file_handle { + struct efi_file_handle base; + struct file_system *fs; + loff_t offset; /* current file position/cursor */ + int isdir; + + /* for reading a directory: */ + struct fs_dir_stream *dirs; + struct fs_dirent *dent; + + char path[0]; +}; +#define to_fh(x) container_of(x, struct file_handle, base) + +static const struct efi_file_handle efi_file_handle_protocol; + +static char *basename(struct file_handle *fh) +{ + char *s = strrchr(fh->path, '/'); + if (s) + return s + 1; + return fh->path; +} + +static int set_blk_dev(struct file_handle *fh) +{ + return fs_set_blk_dev_with_part(fh->fs->desc, fh->fs->part); +} + +static int is_dir(struct file_handle *fh) +{ + struct fs_dir_stream *dirs; + + set_blk_dev(fh); + dirs = fs_opendir(fh->path); + if (!dirs) + return 0; + + fs_closedir(dirs); + + return 1; +} + +static int sanitize_path(char *path) +{ + char *p ; + + /* backslash to slash: */ + p = path; + while ((p = strchr(p, '\\'))) + *p++ = '/'; + + /* handle double-slashes: */ + p = path; + while ((p = strstr(p, "//"))) { + char *src = p + 1; + memmove(p, src, strlen(src) + 1); + } + + /* handle extra /.'s */ + p = path; + while ((p = strstr(p, "/."))) { + /* + * You'd be tempted to do this *after* handling ".."s + * below to avoid having to check if "/." is start of + * a "/..", but that won't have the correct results.. + * for example, "/foo/./../bar" would get resolved to + * "/foo/bar" if you did these two passes in the other + * order + */ + if (p[2] == '.') { + p += 2; + continue; + } + char *src = p + 2; + memmove(p, src, strlen(src) + 1); + } + + /* handle extra /..'s: */ + p = path; + while ((p = strstr(p, "/.."))) { + char *src = p + 3; + + p--; + + /* find beginning of previous path entry: */ + while (true) { + if (p < path) + return -1; + if (*p == '/') + break; + p--; + } + + memmove(p, src, strlen(src) + 1); + } + + return 0; +} + +/* NOTE: despite what you would expect, 'file_name' is actually a path. + * With windoze style backlashes, ofc. + */ +static struct efi_file_handle *file_open(struct file_system *fs, + struct file_handle *parent, s16 *file_name, u64 mode) +{ + struct file_handle *fh; + char f0[MAX_UTF8_PER_UTF16] = {0}; + int plen = 0; + int flen = 0; + + if (file_name) { + utf16_to_utf8((u8 *)f0, (u16 *)file_name, 1); + flen = utf16_strlen((u16 *)file_name); + } + + /* we could have a parent, but also an absolute path: */ + if (f0[0] == '\\') { + plen = 0; + } else if (parent) { + plen = strlen(parent->path) + 1; + } + + /* +2 is for null and '/' */ + fh = calloc(1, sizeof(*fh) + plen + (flen * MAX_UTF8_PER_UTF16) + 2); + + fh->base = efi_file_handle_protocol; + fh->fs = fs; + + if (parent) { + char *p = fh->path; + + if (plen > 0) { + strcpy(p, parent->path); + p += plen - 1; + *p++ = '/'; + } + + utf16_to_utf8((u8 *)p, (u16 *)file_name, flen); + + if (sanitize_path(fh->path)) + goto error; + + /* check if file exists: */ + if (set_blk_dev(fh)) + goto error; + + if (!((mode & EFI_FILE_MODE_CREATE) || fs_exists(fh->path))) + goto error; + + /* figure out if file is a directory: */ + fh->isdir = is_dir(fh); + } else { + fh->isdir = 1; + strcpy(fh->path, ""); + } + + return &fh->base; + +error: + free(fh); + return NULL; +} + +static efi_status_t EFIAPI efi_file_open(struct efi_file_handle *file, + struct efi_file_handle **new_handle, + s16 *file_name, u64 open_mode, u64 attributes) +{ + struct file_handle *fh = to_fh(file); + + EFI_ENTRY("%p, %p, \"%ls\", %llx, %llu", file, new_handle, file_name, + open_mode, attributes); + + *new_handle = file_open(fh->fs, fh, file_name, open_mode); + if (!*new_handle) + return EFI_EXIT(EFI_NOT_FOUND); + + return EFI_EXIT(EFI_SUCCESS); +} + +static efi_status_t file_close(struct file_handle *fh) +{ + fs_closedir(fh->dirs); + free(fh); + return EFI_SUCCESS; +} + +static efi_status_t EFIAPI efi_file_close(struct efi_file_handle *file) +{ + struct file_handle *fh = to_fh(file); + EFI_ENTRY("%p", file); + return EFI_EXIT(file_close(fh)); +} + +static efi_status_t EFIAPI efi_file_delete(struct efi_file_handle *file) +{ + struct file_handle *fh = to_fh(file); + EFI_ENTRY("%p", file); + file_close(fh); + return EFI_EXIT(EFI_WARN_DELETE_FAILURE); +} + +static efi_status_t file_read(struct file_handle *fh, u64 *buffer_size, + void *buffer) +{ + loff_t actread; + + if (fs_read(fh->path, (ulong)buffer, fh->offset, + *buffer_size, &actread)) + return EFI_DEVICE_ERROR; + + *buffer_size = actread; + fh->offset += actread; + + return EFI_SUCCESS; +} + +static efi_status_t dir_read(struct file_handle *fh, u64 *buffer_size, + void *buffer) +{ + struct efi_file_info *info = buffer; + struct fs_dirent *dent; + unsigned required_size; + + if (!fh->dirs) { + assert(fh->offset == 0); + fh->dirs = fs_opendir(fh->path); + if (!fh->dirs) + return EFI_DEVICE_ERROR; + } + + /* + * So this is a bit awkward. Since fs layer is stateful and we + * can't rewind an entry, in the EFI_BUFFER_TOO_SMALL case below + * we might have to return without consuming the dent.. so we + * have to stash it for next call. + */ + if (fh->dent) { + dent = fh->dent; + fh->dent = NULL; + } else { + dent = fs_readdir(fh->dirs); + } + + + if (!dent) { + /* no more files in directory: */ + /* workaround shim.efi bug/quirk.. as find_boot_csv() + * loops through directory contents, it initially calls + * read w/ zero length buffer to find out how much mem + * to allocate for the EFI_FILE_INFO, then allocates, + * and then calls a 2nd time. If we return size of + * zero the first time, it happily passes that to + * AllocateZeroPool(), and when that returns NULL it + * thinks it is EFI_OUT_OF_RESOURCES. So on first + * call return a non-zero size: + */ + if (*buffer_size == 0) + *buffer_size = sizeof(*info); + else + *buffer_size = 0; + return EFI_SUCCESS; + } + + /* check buffer size: */ + required_size = sizeof(*info) + 2 * (strlen(dent->name) + 1); + if (*buffer_size < required_size) { + *buffer_size = required_size; + fh->dent = dent; + return EFI_BUFFER_TOO_SMALL; + } + + *buffer_size = required_size; + memset(info, 0, required_size); + + info->size = required_size; + info->file_size = dent->size; + info->physical_size = dent->size; + + if (dent->type == FS_DT_DIR) + info->attribute |= EFI_FILE_DIRECTORY; + + ascii2unicode((u16 *)info->file_name, dent->name); + + fh->offset++; + + return EFI_SUCCESS; +} + +static efi_status_t EFIAPI efi_file_read(struct efi_file_handle *file, + u64 *buffer_size, void *buffer) +{ + struct file_handle *fh = to_fh(file); + efi_status_t ret = EFI_SUCCESS; + + EFI_ENTRY("%p, %p, %p", file, buffer_size, buffer); + + if (set_blk_dev(fh)) { + ret = EFI_DEVICE_ERROR; + goto error; + } + + if (fh->isdir) + ret = dir_read(fh, buffer_size, buffer); + else + ret = file_read(fh, buffer_size, buffer); + +error: + return EFI_EXIT(ret); +} + +static efi_status_t EFIAPI efi_file_write(struct efi_file_handle *file, + u64 *buffer_size, void *buffer) +{ + struct file_handle *fh = to_fh(file); + efi_status_t ret = EFI_SUCCESS; + loff_t actwrite; + + EFI_ENTRY("%p, %p, %p", file, buffer_size, buffer); + + if (set_blk_dev(fh)) { + ret = EFI_DEVICE_ERROR; + goto error; + } + + if (fs_write(fh->path, (ulong)buffer, fh->offset, *buffer_size, + &actwrite)) { + ret = EFI_DEVICE_ERROR; + goto error; + } + + *buffer_size = actwrite; + fh->offset += actwrite; + +error: + return EFI_EXIT(ret); +} + +static efi_status_t EFIAPI efi_file_getpos(struct efi_file_handle *file, + u64 *pos) +{ + struct file_handle *fh = to_fh(file); + EFI_ENTRY("%p, %p", file, pos); + *pos = fh->offset; + return EFI_EXIT(EFI_SUCCESS); +} + +static efi_status_t EFIAPI efi_file_setpos(struct efi_file_handle *file, + u64 pos) +{ + struct file_handle *fh = to_fh(file); + efi_status_t ret = EFI_SUCCESS; + + EFI_ENTRY("%p, %llu", file, pos); + + if (fh->isdir) { + if (pos != 0) { + ret = EFI_UNSUPPORTED; + goto error; + } + fs_closedir(fh->dirs); + fh->dirs = NULL; + } + + if (pos == ~0ULL) { + loff_t file_size; + + if (set_blk_dev(fh)) { + ret = EFI_DEVICE_ERROR; + goto error; + } + + if (fs_size(fh->path, &file_size)) { + ret = EFI_DEVICE_ERROR; + goto error; + } + + pos = file_size; + } + + fh->offset = pos; + +error: + return EFI_EXIT(ret); +} + +static efi_status_t EFIAPI efi_file_getinfo(struct efi_file_handle *file, + efi_guid_t *info_type, u64 *buffer_size, void *buffer) +{ + struct file_handle *fh = to_fh(file); + efi_status_t ret = EFI_SUCCESS; + + EFI_ENTRY("%p, %p, %p, %p", file, info_type, buffer_size, buffer); + + if (!guidcmp(info_type, &efi_file_info_guid)) { + struct efi_file_info *info = buffer; + char *filename = basename(fh); + unsigned required_size; + loff_t file_size; + + /* check buffer size: */ + required_size = sizeof(*info) + 2 * (strlen(filename) + 1); + if (*buffer_size < required_size) { + *buffer_size = required_size; + ret = EFI_BUFFER_TOO_SMALL; + goto error; + } + + if (set_blk_dev(fh)) { + ret = EFI_DEVICE_ERROR; + goto error; + } + + if (fs_size(fh->path, &file_size)) { + ret = EFI_DEVICE_ERROR; + goto error; + } + + memset(info, 0, required_size); + + info->size = required_size; + info->file_size = file_size; + info->physical_size = file_size; + + if (fh->isdir) + info->attribute |= EFI_FILE_DIRECTORY; + + ascii2unicode((u16 *)info->file_name, filename); + } else { + ret = EFI_UNSUPPORTED; + } + +error: + return EFI_EXIT(ret); +} + +static efi_status_t EFIAPI efi_file_setinfo(struct efi_file_handle *file, + efi_guid_t *info_type, u64 buffer_size, void *buffer) +{ + EFI_ENTRY("%p, %p, %llu, %p", file, info_type, buffer_size, buffer); + return EFI_EXIT(EFI_UNSUPPORTED); +} + +static efi_status_t EFIAPI efi_file_flush(struct efi_file_handle *file) +{ + EFI_ENTRY("%p", file); + return EFI_EXIT(EFI_SUCCESS); +} + +static const struct efi_file_handle efi_file_handle_protocol = { + .rev = EFI_FILE_PROTOCOL_REVISION, + .open = efi_file_open, + .close = efi_file_close, + .delete = efi_file_delete, + .read = efi_file_read, + .write = efi_file_write, + .getpos = efi_file_getpos, + .setpos = efi_file_setpos, + .getinfo = efi_file_getinfo, + .setinfo = efi_file_setinfo, + .flush = efi_file_flush, +}; + +struct efi_file_handle *efi_file_from_path(struct efi_device_path *fp) +{ + struct efi_simple_file_system_protocol *v; + struct efi_file_handle *f; + efi_status_t ret; + + v = efi_fs_from_path(fp); + if (!v) + return NULL; + + EFI_CALL(ret = v->open_volume(v, &f)); + if (ret != EFI_SUCCESS) + return NULL; + + /* skip over device-path nodes before the file path: */ + while (fp && !EFI_DP_TYPE(fp, MEDIA_DEVICE, FILE_PATH)) + fp = efi_dp_next(fp); + + while (fp) { + struct efi_device_path_file_path *fdp = + container_of(fp, struct efi_device_path_file_path, dp); + struct efi_file_handle *f2; + + if (!EFI_DP_TYPE(fp, MEDIA_DEVICE, FILE_PATH)) { + printf("bad file path!\n"); + f->close(f); + return NULL; + } + + EFI_CALL(ret = f->open(f, &f2, (s16 *)fdp->str, + EFI_FILE_MODE_READ, 0)); + if (ret != EFI_SUCCESS) + return NULL; + + fp = efi_dp_next(fp); + + EFI_CALL(f->close(f)); + f = f2; + } + + return f; +} + +static efi_status_t EFIAPI +efi_open_volume(struct efi_simple_file_system_protocol *this, + struct efi_file_handle **root) +{ + struct file_system *fs = to_fs(this); + + EFI_ENTRY("%p, %p", this, root); + + *root = file_open(fs, NULL, NULL, 0); + + return EFI_EXIT(EFI_SUCCESS); +} + +struct efi_simple_file_system_protocol * +efi_simple_file_system(struct blk_desc *desc, int part, + struct efi_device_path *dp) +{ + struct file_system *fs; + + fs = calloc(1, sizeof(*fs)); + fs->base.rev = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION; + fs->base.open_volume = efi_open_volume; + fs->desc = desc; + fs->part = part; + fs->dp = dp; + + return &fs->base; +} diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c index f961407f50..469acae082 100644 --- a/lib/efi_loader/efi_image_loader.c +++ b/lib/efi_loader/efi_image_loader.c @@ -17,6 +17,9 @@ DECLARE_GLOBAL_DATA_PTR; const efi_guid_t efi_guid_device_path = DEVICE_PATH_GUID; const efi_guid_t efi_guid_loaded_image = LOADED_IMAGE_GUID; +const efi_guid_t efi_simple_file_system_protocol_guid = + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID; +const efi_guid_t efi_file_info_guid = EFI_FILE_INFO_GUID; static efi_status_t efi_loader_relocate(const IMAGE_BASE_RELOCATION *rel, unsigned long rel_size, void *efi_reloc) From patchwork Sun Sep 10 11:21:38 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Clark X-Patchwork-Id: 812110 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="YxnXTyvs"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3xqpq166f1z9sDB for ; Sun, 10 Sep 2017 21:33:49 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 923B3C21E8C; Sun, 10 Sep 2017 11:30:39 +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 45D6BC21EBF; Sun, 10 Sep 2017 11:27:34 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 6B78FC21DC3; Sun, 10 Sep 2017 11:23:44 +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 1FEC5C21F3A for ; Sun, 10 Sep 2017 11:23:39 +0000 (UTC) Received: by mail-qt0-f195.google.com with SMTP id q8so4090458qtb.1 for ; Sun, 10 Sep 2017 04:23:39 -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=DKsVzCsw32z5Rh0dgOU0MOQ8zk25bcDzhP7cBWZSGfE=; b=YxnXTyvsyDqjMMCQ2u4FNsP3q6RZOSTjrZwG4TRV6I8YeKX1xfWeyMw99/geLPVbmT i/DyAjGLRspe4xjKt4ovsGmAwnJc/vTNaYHbFRWvJrz6tOALUVw6O4Wf6iPc9s6h4MFv mRQXAs1XvhF2MqzprzYiSpi56N0uZL0kSbxRC4u5jjH7UC/vy353YTQF4abKQI14Vpda jxvAIAwdNl76JmsixAOjU2WHutu94dNzgDstLUyl9tG4ZrouOE/WnauXm68R2J4w57mB 23zKmHAT3i60b/YICnYD/X0S1O3AfyLhoNwHohTZawtVpBZ2MsmXCWKGclFb0K62xCwj akHw== 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=DKsVzCsw32z5Rh0dgOU0MOQ8zk25bcDzhP7cBWZSGfE=; b=Y2Wr0ZgVcBUUoMXQ8YUt5fNMvRX4gwzwSKO/2yLxnUKVVGXESRVZK3JC8VgIDDiod6 xdpEMFwt2SVe7Z6MrYWnMc25h8zmgFrVHhBNjBqNM8fEB40GsIjQAcjY3dP1O+ivyaHh 7L26PI6V8urN4lsDZXsSzEVK0ZIxSO6qe4rX3X28pQhjUGkWx2XPXgTC/g606bOSBWTa h/hvU1P+Ck3ojOVcDM5AGdB436kmEknYAA1cXEXudFOdEjPbB9wyF6/6UOnNOH8ukAhh zAg8k2d8wPzWaTontiz17usfpL90usngvpuuZkXvcFkB4qk6QuIqjdV986G5MSJnKxDm PbXA== X-Gm-Message-State: AHPjjUgoUcw5nGucTKcZIofg9PduFWQVdSqz/h71gcroR/3p8dM76ukP p+EeS+ekUbwENeeDurI= X-Google-Smtp-Source: AOwi7QBHiNxrzgWo9i/AVRifxdWDhl2BeZRhja2GMc8XdALeXxkY4Hk7wo6Ix37CjzG1fyk1q928DQ== X-Received: by 10.200.42.46 with SMTP id k43mr8546114qtk.273.1505042617870; Sun, 10 Sep 2017 04:23:37 -0700 (PDT) Received: from localhost ([2601:184:4780:aac0:25f8:dd96:a084:785a]) by smtp.gmail.com with ESMTPSA id x65sm4049637qke.48.2017.09.10.04.23.36 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sun, 10 Sep 2017 04:23:36 -0700 (PDT) From: Rob Clark To: U-Boot Mailing List Date: Sun, 10 Sep 2017 07:21:38 -0400 Message-Id: <20170910112149.21358-22-robdclark@gmail.com> X-Mailer: git-send-email 2.13.5 In-Reply-To: <20170910112149.21358-1-robdclark@gmail.com> References: <20170910112149.21358-1-robdclark@gmail.com> Cc: Heinrich Schuchardt Subject: [U-Boot] [PATCH v2 12/21] efi_loader: support load_image() from a file-path 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" Previously we only supported the case when the EFI application loaded the image into memory for us. But fallback.efi does not do this. Signed-off-by: Rob Clark --- lib/efi_loader/efi_boottime.c | 85 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 70 insertions(+), 15 deletions(-) diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 837e61d8fe..ec40f41bcb 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -762,6 +762,47 @@ void efi_setup_loaded_image(struct efi_loaded_image *info, struct efi_object *ob list_add_tail(&obj->link, &efi_obj_list); } +static efi_status_t load_image_from_path(struct efi_device_path *file_path, + void **buffer) +{ + struct efi_file_info *info = NULL; + struct efi_file_handle *f; + static efi_status_t ret; + uint64_t bs; + + f = efi_file_from_path(file_path); + if (!f) + return EFI_DEVICE_ERROR; + + bs = 0; + EFI_CALL(ret = f->getinfo(f, (efi_guid_t *)&efi_file_info_guid, + &bs, info)); + if (ret == EFI_BUFFER_TOO_SMALL) { + info = malloc(bs); + EFI_CALL(ret = f->getinfo(f, (efi_guid_t *)&efi_file_info_guid, + &bs, info)); + } + if (ret != EFI_SUCCESS) + goto error; + + ret = efi_allocate_pool(EFI_LOADER_DATA, info->file_size, buffer); + if (ret) + goto error; + + EFI_CALL(ret = f->read(f, &info->file_size, *buffer)); + +error: + free(info); + EFI_CALL(f->close(f)); + + if (ret != EFI_SUCCESS) { + efi_free_pool(*buffer); + *buffer = NULL; + } + + return ret; +} + static efi_status_t EFIAPI efi_load_image(bool boot_policy, efi_handle_t parent_image, struct efi_device_path *file_path, @@ -769,25 +810,40 @@ static efi_status_t EFIAPI efi_load_image(bool boot_policy, unsigned long source_size, efi_handle_t *image_handle) { - static struct efi_object loaded_image_info_obj = { - .protocols = { - { - .guid = &efi_guid_loaded_image, - }, - }, - }; struct efi_loaded_image *info; struct efi_object *obj; EFI_ENTRY("%d, %p, %p, %p, %ld, %p", boot_policy, parent_image, file_path, source_buffer, source_size, image_handle); - info = malloc(sizeof(*info)); - loaded_image_info_obj.protocols[0].protocol_interface = info; - obj = malloc(sizeof(loaded_image_info_obj)); - memset(info, 0, sizeof(*info)); - memcpy(obj, &loaded_image_info_obj, sizeof(loaded_image_info_obj)); - obj->handle = info; - info->file_path = file_path; + + info = calloc(1, sizeof(*info)); + obj = calloc(1, sizeof(*obj)); + + if (!source_buffer) { + struct efi_device_path *dp, *fp; + efi_status_t ret; + + ret = load_image_from_path(file_path, &source_buffer); + if (ret != EFI_SUCCESS) { + free(info); + free(obj); + return EFI_EXIT(ret); + } + + /* + * split file_path which contains both the device and + * file parts: + */ + efi_dp_split_file_path(file_path, &dp, &fp); + + efi_setup_loaded_image(info, obj, dp, fp); + } else { + /* In this case, file_path is the "device" path, ie. + * something like a HARDWARE_DEVICE:MEMORY_MAPPED + */ + efi_setup_loaded_image(info, obj, file_path, NULL); + } + info->reserved = efi_load_pe(source_buffer, info); if (!info->reserved) { free(info); @@ -796,7 +852,6 @@ static efi_status_t EFIAPI efi_load_image(bool boot_policy, } *image_handle = info; - list_add_tail(&obj->link, &efi_obj_list); return EFI_EXIT(EFI_SUCCESS); } From patchwork Sun Sep 10 11:21:39 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Clark X-Patchwork-Id: 812122 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="lISHHo7v"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3xqpyy5233z9sDB for ; Sun, 10 Sep 2017 21:40:42 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 74F02C21F8C; Sun, 10 Sep 2017 11:31:52 +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 E4009C21F04; Sun, 10 Sep 2017 11:29:43 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id BE801C21F0F; Sun, 10 Sep 2017 11:23: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 BD07BC21F3E for ; Sun, 10 Sep 2017 11:23:41 +0000 (UTC) Received: by mail-qt0-f195.google.com with SMTP id q8so4090472qtb.1 for ; Sun, 10 Sep 2017 04:23:41 -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=rRpS4m7+k9Kgg68zb96oaEj5ZZmnh1UimVhSWh7Vh34=; b=lISHHo7vdGyKqJ1RmbKU3PSerbKbyOAdN42q7xFac8dR3InrhiO+z/X8+0ANCO7oxJ TPVrkNvsc7bOHFak2twJxJl7s9v+CWU+Wu+lzrzdQ+5JLZUcSsrpJtLz3/OuMLL4Y/QF GbWYD/5xVUGdtlj4P/tdyQUrbQ0xg4JOTF7MM40Ca5wHxvJnIGwTRQ/o6UJSPD7h0gGa ZDTtcz4tlpoFG/FXh+6A4rI62UTiysyS/yMpMQdwOtO3Z36DylbeJh7lRQpxa5d0Xm7O vXsj2g0oc/JdfK2PUW++CPI/VAxold6mHORMy8zcTJ7ZIS1VxuRq3FlZHj4TXjXJLtZD eK7A== 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=rRpS4m7+k9Kgg68zb96oaEj5ZZmnh1UimVhSWh7Vh34=; b=l4vT3MmR2V3NJO1hSm+0PrJ5k4/OXHQhGVBa9bwQr3+N3onm+yBJlmQTCwmw35s36Q 1u/dWDkPNdXF+v6qPf821gS2ACtMWB/HsAGlP+Hb0KH1y2iJNOaj7yDfbOQQWKxWAlAC u/nJdLQfv165cGM5y5Y/GDM0Z1bMCE3P0qTa+mKX1THp/3sVZCJbWu3EaOyiEH1EudfI m7juSG05HYpCrYd/fdF31RZs0HMuXbWusiAhGM41GMW+7XXPY6akJdjaiomrkRE4LehT Dwbgdtmyx1HyYfeqjNnkQ8ACiGjodaCz9JXeeU9SRgdOpvLBCIqMO3q+Kv8Q6etoTOZt u+zg== X-Gm-Message-State: AHPjjUheHdgAH+sQ8hYOcHSYto240xErPFUQKLSp4ouXWjOhNhDNYVqm oSQskkT3mKMcNkc4Ryw= X-Google-Smtp-Source: AOwi7QDlxRYAyJzSKiDr3NrcDpGCqQIozbHO4GT7Zojc7m1aJK8FJrYJauqXC8IbWp0wzneZFdZXuQ== X-Received: by 10.200.24.187 with SMTP id s56mr2032516qtj.64.1505042620546; Sun, 10 Sep 2017 04:23:40 -0700 (PDT) Received: from localhost ([2601:184:4780:aac0:25f8:dd96:a084:785a]) by smtp.gmail.com with ESMTPSA id f4sm4491825qte.76.2017.09.10.04.23.39 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sun, 10 Sep 2017 04:23:39 -0700 (PDT) From: Rob Clark To: U-Boot Mailing List Date: Sun, 10 Sep 2017 07:21:39 -0400 Message-Id: <20170910112149.21358-23-robdclark@gmail.com> X-Mailer: git-send-email 2.13.5 In-Reply-To: <20170910112149.21358-1-robdclark@gmail.com> References: <20170910112149.21358-1-robdclark@gmail.com> Cc: Heinrich Schuchardt Subject: [U-Boot] [PATCH v2 13/21] efi_loader: make pool allocations cacheline aligned 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" This avoids printf() spam about file reads (such as loading an image) into unaligned buffers (and the associated memcpy()). And generally seems like a good idea. Signed-off-by: Rob Clark --- lib/efi_loader/efi_memory.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index 9e079f1fa3..1f0b9d0449 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -43,7 +43,7 @@ void *efi_bounce_buffer; */ struct efi_pool_allocation { u64 num_pages; - char data[]; + char data[] __attribute__((aligned(ARCH_DMA_MINALIGN))); }; /* @@ -356,7 +356,8 @@ efi_status_t efi_allocate_pool(int pool_type, unsigned long size, { efi_status_t r; efi_physical_addr_t t; - u64 num_pages = (size + sizeof(u64) + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT; + u64 num_pages = (size + sizeof(struct efi_pool_allocation) + + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT; if (size == 0) { *buffer = NULL; From patchwork Sun Sep 10 11:21:40 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Clark X-Patchwork-Id: 812123 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="UmFky+pD"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3xqpz65SCcz9sNV for ; Sun, 10 Sep 2017 21:40:50 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 8B2BBC21F79; Sun, 10 Sep 2017 11:32:25 +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 0EDBFC21F1A; Sun, 10 Sep 2017 11:30:28 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 96CB2C21E0F; Sun, 10 Sep 2017 11:23:54 +0000 (UTC) Received: from mail-qk0-f193.google.com (mail-qk0-f193.google.com [209.85.220.193]) by lists.denx.de (Postfix) with ESMTPS id 05DE5C21F44 for ; Sun, 10 Sep 2017 11:23:46 +0000 (UTC) Received: by mail-qk0-f193.google.com with SMTP id d70so3978394qkc.1 for ; Sun, 10 Sep 2017 04:23:45 -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=TcXSVnkuzNuuhq/qGicmO35MPEloXzfvi9hiWlZsjUI=; b=UmFky+pD+5SPxnZQ0DY7+TqrqH+FnhqXsWMOChxeNmPuSDaQYwiX0YB4uiWEZkTN2u a9reXp0StRrBpPa3aetgGXDZX853P8obAN1ESSsXIzSpK5z7/8QJpcpCY7A4Lpvo3ega 2JVZ/gLwokSRh8NFSZwae8ogZUEdhWwK6e1kjTjmxAIr4zlDWA5lVm0qTBAJlOCbi/v6 J0IGHPQoDfur3pxcLCQ8LGbLMFF3iRONMfqkcpKkSjxvI+qkRkWCgQLprpiDDusGWDe4 i9CN+TiHjoInpiuQHFoPTBluzkPRluZkAPuYzv7eFCfgLduPBJq8OHMGAq8tAmNt+pmZ BBrQ== 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=TcXSVnkuzNuuhq/qGicmO35MPEloXzfvi9hiWlZsjUI=; b=qTS171OqzZOshSnNIftjQg3vl1Y7pzfwDZkIaKk5ZyGasI31rKnrrxT39EYGPHAVzx 8+cFVI5CXRnVklb7ELCJX11jEnNNskgOmsXVCbY8PA/zzEQHoN+ulNiqitGAI46ZTiJT IdxK9UNkMEUXP2f9bh7BQ94i0Yh016jr4gj/Fcte/vep6DenDw7CyHZpXf97aRF7zopX 48MeubQLeViChghj8KknUDY5ezif4KtDzIjdRaKTuEsf7xkXB+3kyiA/wwNbBVJiMOR9 BxaFyk6kAxiQbp9oDPNyxQbFG5J9ZxhP80Gk/mAB01+fi+Jzyh7obwJqZkzl5IZHs8bf CRpg== X-Gm-Message-State: AHPjjUjMn9ttkqIsQMtgmHY8A4MLbPVGLu7o9mfXyM64JX/UDQddGw7L Q1Y73PI8B5omiANRtcg= X-Google-Smtp-Source: AOwi7QAX4c9r/0NHDjdN5mAMo8nnj9Zl9Wy2km1IB3EYUfU7TQ8JEGu9dhak3VwXzWvvHrvQ1SaMYQ== X-Received: by 10.55.43.65 with SMTP id r62mr11445393qkh.250.1505042624503; Sun, 10 Sep 2017 04:23:44 -0700 (PDT) Received: from localhost ([2601:184:4780:aac0:25f8:dd96:a084:785a]) by smtp.gmail.com with ESMTPSA id y11sm4256526qkb.20.2017.09.10.04.23.42 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sun, 10 Sep 2017 04:23:43 -0700 (PDT) From: Rob Clark To: U-Boot Mailing List Date: Sun, 10 Sep 2017 07:21:40 -0400 Message-Id: <20170910112149.21358-24-robdclark@gmail.com> X-Mailer: git-send-email 2.13.5 In-Reply-To: <20170910112149.21358-1-robdclark@gmail.com> References: <20170910112149.21358-1-robdclark@gmail.com> Cc: Heinrich Schuchardt Subject: [U-Boot] [PATCH v2 14/21] efi_loader: efi variable support 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" Add EFI variable support, mapping to u-boot environment variables. Variables are pretty important for setting up boot order, among other things. If the board supports saveenv, then it will be called in ExitBootServices() to persist variables set by the efi payload. (For example, fallback.efi configuring BootOrder and BootXXXX load-option variables.) Variables are *not* currently exposed at runtime, post ExitBootServices. On boards without a dedicated device for storage, which the loaded OS is not trying to also use, this is rather tricky. One idea, at least for boards that can persist RAM across reboot, is to keep a "journal" of modified variables in RAM, and then turn halt into a reboot into u-boot, plus store variables, plus halt. Whatever the solution, it likely involves some per-board support. Mapping between EFI variables and u-boot variables: efi_$guid_$varname = {attributes}(type)value For example: efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_OsIndicationsSupported= "{ro,boot,run}(blob)0000000000000000" efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_BootOrder= "(blob)00010000" The attributes are a comma separated list of these possible attributes: + ro - read-only + boot - boot-services access + run - runtime access NOTE: with current implementation, no variables are available after ExitBootServices, and all are persisted (if possible). If not specified, the attributes default to "{boot}". The required type is one of: + utf8 - raw utf8 string + blob - arbitrary length hex string Signed-off-by: Rob Clark --- cmd/bootefi.c | 4 + include/efi.h | 19 +++ include/efi_loader.h | 10 ++ lib/efi_loader/Makefile | 2 +- lib/efi_loader/efi_boottime.c | 6 + lib/efi_loader/efi_runtime.c | 17 ++- lib/efi_loader/efi_variable.c | 335 ++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 388 insertions(+), 5 deletions(-) create mode 100644 lib/efi_loader/efi_variable.c diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 0980088668..d3ae33e25b 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -181,6 +181,10 @@ static unsigned long do_bootefi_exec(void *efi, void *fdt, goto exit; } + /* we don't support much: */ + env_set("efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_OsIndicationsSupported", + "{ro,boot}(blob)0000000000000000"); + /* Call our payload! */ debug("%s:%d Jumping to 0x%lx\n", __func__, __LINE__, (long)entry); diff --git a/include/efi.h b/include/efi.h index ddd2b96417..04e83220b4 100644 --- a/include/efi.h +++ b/include/efi.h @@ -324,6 +324,25 @@ extern char image_base[]; /* Start and end of U-Boot image (for payload) */ extern char _binary_u_boot_bin_start[], _binary_u_boot_bin_end[]; +/* + * Variable Attributes + */ +#define EFI_VARIABLE_NON_VOLATILE 0x0000000000000001 +#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x0000000000000002 +#define EFI_VARIABLE_RUNTIME_ACCESS 0x0000000000000004 +#define EFI_VARIABLE_HARDWARE_ERROR_RECORD 0x0000000000000008 +#define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS 0x0000000000000010 +#define EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS 0x0000000000000020 +#define EFI_VARIABLE_APPEND_WRITE 0x0000000000000040 + +#define EFI_VARIABLE_MASK (EFI_VARIABLE_NON_VOLATILE | \ + EFI_VARIABLE_BOOTSERVICE_ACCESS | \ + EFI_VARIABLE_RUNTIME_ACCESS | \ + EFI_VARIABLE_HARDWARE_ERROR_RECORD | \ + EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS | \ + EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS | \ + EFI_VARIABLE_APPEND_WRITE) + /** * efi_get_sys_table() - Get access to the main EFI system table * diff --git a/include/efi_loader.h b/include/efi_loader.h index b0c1e8fb78..9eee62dc9c 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -277,6 +277,16 @@ efi_status_t __efi_runtime EFIAPI efi_get_time( struct efi_time_cap *capabilities); void efi_get_time_init(void); +efi_status_t EFIAPI efi_get_variable(s16 *variable_name, + efi_guid_t *vendor, u32 *attributes, + unsigned long *data_size, void *data); +efi_status_t EFIAPI efi_get_next_variable( + unsigned long *variable_name_size, + s16 *variable_name, efi_guid_t *vendor); +efi_status_t EFIAPI efi_set_variable(s16 *variable_name, + efi_guid_t *vendor, u32 attributes, + unsigned long data_size, void *data); + #else /* defined(EFI_LOADER) && !defined(CONFIG_SPL_BUILD) */ /* Without CONFIG_EFI_LOADER we don't have a runtime section, stub it out */ diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile index cce92cfeb5..f58cb13337 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -16,7 +16,7 @@ always := $(efiprogs-y) obj-$(CONFIG_CMD_BOOTEFI_HELLO) += helloworld_efi.o obj-y += efi_image_loader.o efi_boottime.o efi_runtime.o efi_console.o obj-y += efi_memory.o efi_device_path_to_text.o efi_device_path.o -obj-y += efi_file.o +obj-y += efi_file.o efi_variable.o obj-$(CONFIG_LCD) += efi_gop.o obj-$(CONFIG_DM_VIDEO) += efi_gop.o obj-$(CONFIG_PARTITIONS) += efi_disk.o diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index ec40f41bcb..c406ff82ff 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -942,6 +943,11 @@ static efi_status_t EFIAPI efi_exit_boot_services(void *image_handle, { EFI_ENTRY("%p, %ld", image_handle, map_key); +#if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE) + /* save any EFI variables that have been written: */ + env_save(); +#endif + board_quiesce_devices(); /* Fix up caches for EFI payloads if necessary */ diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c index ad7f3754bd..2f95c766ac 100644 --- a/lib/efi_loader/efi_runtime.c +++ b/lib/efi_loader/efi_runtime.c @@ -184,7 +184,16 @@ static const struct efi_runtime_detach_list_struct efi_runtime_detach_list[] = { /* Clean up system table */ .ptr = &systab.boottime, .patchto = NULL, - }, + }, { + .ptr = &efi_runtime_services.get_variable, + .patchto = &efi_device_error, + }, { + .ptr = &efi_runtime_services.get_next_variable, + .patchto = &efi_device_error, + }, { + .ptr = &efi_runtime_services.set_variable, + .patchto = &efi_device_error, + } }; static bool efi_runtime_tobedetached(void *p) @@ -382,9 +391,9 @@ struct efi_runtime_services __efi_runtime_data efi_runtime_services = { .set_wakeup_time = (void *)&efi_unimplemented, .set_virtual_address_map = &efi_set_virtual_address_map, .convert_pointer = (void *)&efi_invalid_parameter, - .get_variable = (void *)&efi_device_error, - .get_next_variable = (void *)&efi_device_error, - .set_variable = (void *)&efi_device_error, + .get_variable = efi_get_variable, + .get_next_variable = efi_get_next_variable, + .set_variable = efi_set_variable, .get_next_high_mono_count = (void *)&efi_device_error, .reset_system = &efi_reset_system_boottime, }; diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c new file mode 100644 index 0000000000..5569b3d3f0 --- /dev/null +++ b/lib/efi_loader/efi_variable.c @@ -0,0 +1,335 @@ +/* + * EFI utils + * + * Copyright (c) 2017 Rob Clark + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include + +#define READ_ONLY BIT(31) + +/* + * Mapping between EFI variables and u-boot variables: + * + * efi_$guid_$varname = {attributes}(type)value + * + * For example: + * + * efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_OsIndicationsSupported= + * "{ro,boot,run}(blob)0000000000000000" + * efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_BootOrder= + * "(blob)00010000" + * + * The attributes are a comma separated list of these possible + * attributes: + * + * + ro - read-only + * + boot - boot-services access + * + run - runtime access + * + * NOTE: with current implementation, no variables are available after + * ExitBootServices, and all are persisted (if possible). + * + * If not specified, the attributes default to "{boot}". + * + * The required type is one of: + * + * + utf8 - raw utf8 string + * + blob - arbitrary length hex string + * + * Maybe a utf16 type would be useful to for a string value to be auto + * converted to utf16? + */ + +#define MAX_VAR_NAME 31 +#define MAX_NATIVE_VAR_NAME \ + (strlen("efi_xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx_") + \ + (MAX_VAR_NAME * MAX_UTF8_PER_UTF16)) + +static int hex(unsigned char ch) +{ + if (ch >= 'a' && ch <= 'f') + return ch-'a'+10; + if (ch >= '0' && ch <= '9') + return ch-'0'; + if (ch >= 'A' && ch <= 'F') + return ch-'A'+10; + return -1; +} + +static const char *hex2mem(u8 *mem, const char *hexstr, int count) +{ + memset(mem, 0, count/2); + + do { + int nibble; + + *mem = 0; + + if (!count || !*hexstr) + break; + + nibble = hex(*hexstr); + if (nibble < 0) + break; + + *mem = nibble; + count--; + hexstr++; + + if (!count || !*hexstr) + break; + + nibble = hex(*hexstr); + if (nibble < 0) + break; + + *mem = (*mem << 4) | nibble; + count--; + hexstr++; + mem++; + + } while (1); + + if (*hexstr) + return hexstr; + + return NULL; +} + +static char *mem2hex(char *hexstr, const u8 *mem, int count) +{ + static const char hexchars[] = "0123456789abcdef"; + + while (count-- > 0) { + u8 ch = *mem++; + *hexstr++ = hexchars[ch >> 4]; + *hexstr++ = hexchars[ch & 0xf]; + } + + return hexstr; +} + +static efi_status_t efi_to_native(char *native, s16 *variable_name, + efi_guid_t *vendor) +{ + size_t len; + + len = utf16_strlen((u16 *)variable_name); + if (len >= MAX_VAR_NAME) + return EFI_DEVICE_ERROR; + + native += sprintf(native, "efi_%pUl_", vendor); + native = (char *)utf16_to_utf8((u8 *)native, (u16 *)variable_name, len); + *native = '\0'; + + return EFI_SUCCESS; +} + +static const char *prefix(const char *str, const char *prefix) +{ + size_t n = strlen(prefix); + if (!strncmp(prefix, str, n)) + return str + n; + return NULL; +} + +/* parse attributes part of variable value, if present: */ +static const char *parse_attr(const char *str, u32 *attrp) +{ + u32 attr = 0; + char sep = '{'; + + if (*str != '{') { + *attrp = EFI_VARIABLE_BOOTSERVICE_ACCESS; + return str; + } + + while (*str == sep) { + const char *s; + + str++; + + if ((s = prefix(str, "ro"))) { + attr |= READ_ONLY; + } else if ((s = prefix(str, "boot"))) { + attr |= EFI_VARIABLE_BOOTSERVICE_ACCESS; + } else if ((s = prefix(str, "run"))) { + attr |= EFI_VARIABLE_RUNTIME_ACCESS; + } else { + printf("invalid attribute: %s\n", str); + break; + } + + str = s; + sep = ','; + } + + str++; + + *attrp = attr; + + return str; +} + +/* http://wiki.phoenix.com/wiki/index.php/EFI_RUNTIME_SERVICES#GetVariable.28.29 */ +efi_status_t EFIAPI efi_get_variable(s16 *variable_name, + efi_guid_t *vendor, u32 *attributes, + unsigned long *data_size, void *data) +{ + char native_name[MAX_NATIVE_VAR_NAME + 1]; + efi_status_t ret; + unsigned long in_size; + const char *val, *s; + u32 attr; + + EFI_ENTRY("%p %p %p %p %p", variable_name, vendor, attributes, + data_size, data); + + if (!variable_name || !vendor || !data_size) + return EFI_EXIT(EFI_INVALID_PARAMETER); + + ret = efi_to_native(native_name, variable_name, vendor); + if (ret) + return EFI_EXIT(ret); + + debug("%s: get '%s'\n", __func__, native_name); + + val = env_get(native_name); + if (!val) + return EFI_EXIT(EFI_NOT_FOUND); + + val = parse_attr(val, &attr); + + in_size = *data_size; + + if ((s = prefix(val, "(blob)"))) { + unsigned len = strlen(s); + + /* two characters per byte: */ + len = DIV_ROUND_UP(len, 2); + *data_size = len; + + if (in_size < len) + return EFI_EXIT(EFI_BUFFER_TOO_SMALL); + + if (!data) + return EFI_EXIT(EFI_INVALID_PARAMETER); + + if (hex2mem(data, s, len * 2)) + return EFI_EXIT(EFI_DEVICE_ERROR); + + debug("%s: got value: \"%s\"\n", __func__, s); + } else if ((s = prefix(val, "(utf8)"))) { + unsigned len = strlen(s) + 1; + + *data_size = len; + + if (in_size < len) + return EFI_EXIT(EFI_BUFFER_TOO_SMALL); + + if (!data) + return EFI_EXIT(EFI_INVALID_PARAMETER); + + memcpy(data, s, len); + ((char *)data)[len] = '\0'; + + debug("%s: got value: \"%s\"\n", __func__, (char *)data); + } else { + debug("%s: invalid value: '%s'\n", __func__, val); + return EFI_EXIT(EFI_DEVICE_ERROR); + } + + if (attributes) + *attributes = attr & EFI_VARIABLE_MASK; + + return EFI_EXIT(EFI_SUCCESS); +} + +/* http://wiki.phoenix.com/wiki/index.php/EFI_RUNTIME_SERVICES#GetNextVariableName.28.29 */ +efi_status_t EFIAPI efi_get_next_variable( + unsigned long *variable_name_size, + s16 *variable_name, efi_guid_t *vendor) +{ + EFI_ENTRY("%p %p %p", variable_name_size, variable_name, vendor); + + return EFI_EXIT(EFI_DEVICE_ERROR); +} + +/* http://wiki.phoenix.com/wiki/index.php/EFI_RUNTIME_SERVICES#SetVariable.28.29 */ +efi_status_t EFIAPI efi_set_variable(s16 *variable_name, + efi_guid_t *vendor, u32 attributes, + unsigned long data_size, void *data) +{ + char native_name[MAX_NATIVE_VAR_NAME + 1]; + efi_status_t ret = EFI_SUCCESS; + char *val, *s; + u32 attr; + + EFI_ENTRY("%p %p %x %lu %p", variable_name, vendor, attributes, + data_size, data); + + if (!variable_name || !vendor) + return EFI_EXIT(EFI_INVALID_PARAMETER); + + ret = efi_to_native(native_name, variable_name, vendor); + if (ret) + return EFI_EXIT(ret); + +#define ACCESS_ATTR (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS) + + if ((data_size == 0) || !(attributes & ACCESS_ATTR)) { + /* delete the variable: */ + env_set(native_name, NULL); + return EFI_EXIT(EFI_SUCCESS); + } + + val = env_get(native_name); + if (val) { + parse_attr(val, &attr); + + if (attr & READ_ONLY) + return EFI_EXIT(EFI_WRITE_PROTECTED); + } + + val = malloc(2 * data_size + strlen("{ro,run,boot}(blob)") + 1); + if (!val) + return EFI_EXIT(EFI_OUT_OF_RESOURCES); + + s = val; + + /* store attributes: */ + attributes &= (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS); + s += sprintf(s, "{"); + while (attributes) { + u32 attr = 1 << (ffs(attributes) - 1); + + if (attr == EFI_VARIABLE_BOOTSERVICE_ACCESS) + s += sprintf(s, "boot"); + else if (attr == EFI_VARIABLE_RUNTIME_ACCESS) + s += sprintf(s, "run"); + + attributes &= ~attr; + if (attributes) + s += sprintf(s, ","); + } + s += sprintf(s, "}"); + + /* store payload: */ + s += sprintf(s, "(blob)"); + s = mem2hex(s, data, data_size); + *s = '\0'; + + debug("%s: setting: %s=%s\n", __func__, native_name, val); + + if (env_set(native_name, val)) + ret = EFI_DEVICE_ERROR; + + free(val); + + return EFI_EXIT(ret); +} From patchwork Sun Sep 10 11:21:41 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Clark X-Patchwork-Id: 812109 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="aDlAmegW"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3xqppm1w3Lz9sDB for ; Sun, 10 Sep 2017 21:33:36 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 032CAC21F0D; Sun, 10 Sep 2017 11:29:24 +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 0F1E0C21E99; Sun, 10 Sep 2017 11:26:24 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 1EB34C21E0E; Sun, 10 Sep 2017 11:23:58 +0000 (UTC) Received: from mail-qk0-f195.google.com (mail-qk0-f195.google.com [209.85.220.195]) by lists.denx.de (Postfix) with ESMTPS id 7236FC21F47 for ; Sun, 10 Sep 2017 11:23:49 +0000 (UTC) Received: by mail-qk0-f195.google.com with SMTP id r66so3818359qke.4 for ; Sun, 10 Sep 2017 04:23:49 -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=skbTbgRelK07Cb0goRHnPKzzyU4R4WNBSRXUhJTeYMI=; b=aDlAmegWkkLnMGpxr1ujPz2bjaqF1NIXr95gprxpYJ5Jdz9tFrgikD0TT5Sjgzvhj6 AlHVF8+w6uFC0bbKKS2NtULELnCuT/KJpwljP44bBd8Ay4QpkhO0YCmNNieDP9my5UP0 uoJVTPtKzfQ5kaRfBnSZ/Is5AJXcBY0i0cZc8oG0P1ssq/0ZzvJ3Qr0Ucf3jTicQLwW6 APERIPJOZinkiLRLlRY1vJZIWgvuW4i+YzrBE2YVCengWUCztIaOA8ThU3MCVVOQcvwO B40Rp509juKveoJXlbCT9ODxGSaMxmWA7DUGVmFlOJKbtuJdsMv4VQdEqXmcfDcP6rM4 L0yA== 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=skbTbgRelK07Cb0goRHnPKzzyU4R4WNBSRXUhJTeYMI=; b=f1ZivF3G4vPSDCiv6tZ0E+0kJ4QNZjh42799w2Rxq8d4PaBd4uXHBSV3kJm1YyOE3x DhNBIUXbCdu6ro/aklsowIHoLZPr1b/l6rit6bobcl4T7pJdjSyxoIyWibGvOEsZSMjA UaU1RPbtLAI4m7vDw7V/APFr+J3yzwu6fWZafwX8KKFfDoK3vvzjA9UFZGkTzWi5jThv 95CkCXoevyRwJj3pb8qh2+DDrbU7Eq24YL/JgvBhEMGkkOQYN2OSeeRQ9EzM/kV45nPO +5dpe6Q0/PUL1GzZwntzF6lYkHZxSGap9CveUeNHk9/pQoDNuV1LDFaHHwyHQFVt+X0O ZX+g== X-Gm-Message-State: AHPjjUjeYBrzruIwr3xIRIzFkVOTNpAgjm6Ottjp+lq8CIXi3zfnz9Nt gA5zENlrnB1DIXtHgOQ= X-Google-Smtp-Source: AOwi7QDVh3RPwjxSyHQbscLn/GGSOJQpdOwGtFMGvdNxnwOVbSe29ApyF0vThkfGo+WVDnlQpFycPA== X-Received: by 10.55.123.1 with SMTP id w1mr1047748qkc.114.1505042628084; Sun, 10 Sep 2017 04:23:48 -0700 (PDT) Received: from localhost ([2601:184:4780:aac0:25f8:dd96:a084:785a]) by smtp.gmail.com with ESMTPSA id n1sm4059614qkf.50.2017.09.10.04.23.46 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sun, 10 Sep 2017 04:23:46 -0700 (PDT) From: Rob Clark To: U-Boot Mailing List Date: Sun, 10 Sep 2017 07:21:41 -0400 Message-Id: <20170910112149.21358-25-robdclark@gmail.com> X-Mailer: git-send-email 2.13.5 In-Reply-To: <20170910112149.21358-1-robdclark@gmail.com> References: <20170910112149.21358-1-robdclark@gmail.com> Cc: Heinrich Schuchardt , Peter Jones Subject: [U-Boot] [PATCH v2 15/21] efi_loader: add bootmgr 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" Similar to a "real" UEFI implementation, the bootmgr looks at the BootOrder and BootXXXX variables to try to find an EFI payload to load and boot. This is added as a sub-command of bootefi. The idea is that the distro bootcmd would first try loading a payload via the bootmgr, and then if that fails (ie. first boot or corrupted EFI variables) it would fallback to loading bootaa64.efi. (Which would then load fallback.efi which would look for \EFI\*\boot.csv and populate BootOrder and BootXXXX based on what it found.) Signed-off-by: Rob Clark --- cmd/bootefi.c | 48 ++++++++++- include/config_distro_bootcmd.h | 5 ++ include/efi_api.h | 4 + include/efi_loader.h | 6 ++ lib/efi_loader/Makefile | 2 +- lib/efi_loader/efi_bootmgr.c | 169 ++++++++++++++++++++++++++++++++++++++ lib/efi_loader/efi_boottime.c | 6 +- lib/efi_loader/efi_image_loader.c | 1 + 8 files changed, 235 insertions(+), 6 deletions(-) create mode 100644 lib/efi_loader/efi_bootmgr.c diff --git a/cmd/bootefi.c b/cmd/bootefi.c index d3ae33e25b..fcd8dbafc1 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -219,6 +219,36 @@ exit: return ret; } +static int do_bootefi_bootmgr_exec(unsigned long fdt_addr) +{ + struct efi_device_path *device_path, *file_path; + void *addr; + efi_status_t r; + + /* Initialize and populate EFI object list */ + if (!efi_obj_list_initalized) + efi_init_obj_list(); + + /* + * gd lives in a fixed register which may get clobbered while we execute + * the payload. So save it here and restore it on every callback entry + */ + efi_save_gd(); + + addr = efi_bootmgr_load(&device_path, &file_path); + if (!addr) + return 1; + + printf("## Starting EFI application at %p ...\n", addr); + r = do_bootefi_exec(addr, (void *)fdt_addr, device_path, file_path); + printf("## Application terminated, r = %lu\n", + r & ~EFI_ERROR_MASK); + + if (r != EFI_SUCCESS) + return 1; + + return 0; +} /* Interpreter command to boot an arbitrary EFI image from memory */ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) @@ -237,7 +267,14 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) memcpy((char *)addr, __efi_hello_world_begin, size); } else #endif - { + if (!strcmp(argv[1], "bootmgr")) { + unsigned long fdt_addr = 0; + + if (argc > 2) + fdt_addr = simple_strtoul(argv[2], NULL, 16); + + return do_bootefi_bootmgr_exec(fdt_addr); + } else { saddr = argv[1]; addr = simple_strtoul(saddr, NULL, 16); @@ -270,7 +307,11 @@ static char bootefi_help_text[] = "hello\n" " - boot a sample Hello World application stored within U-Boot" #endif - ; + "bootmgr [fdt addr]\n" + " - load and boot EFI payload based on BootOrder/BootXXXX variables.\n" + "\n" + " If specified, the device tree located at gets\n" + " exposed as EFI configuration table.\n"; #endif U_BOOT_CMD( @@ -308,6 +349,9 @@ void efi_set_bootdev(const char *dev, const char *devnr, const char *path) #endif } + if (!path) + return; + if (strcmp(dev, "Net")) { /* Add leading / to fs paths, because they're absolute */ snprintf(filename, sizeof(filename), "/%s", path); diff --git a/include/config_distro_bootcmd.h b/include/config_distro_bootcmd.h index 9ed6b9892c..e0d0034ed3 100644 --- a/include/config_distro_bootcmd.h +++ b/include/config_distro_bootcmd.h @@ -112,6 +112,11 @@ #define BOOTENV_SHARED_EFI \ "boot_efi_binary=" \ + "if fdt addr ${fdt_addr_r}; then " \ + "bootefi bootmgr ${fdt_addr_r};" \ + "else " \ + "bootefi bootmgr ${fdtcontroladdr};" \ + "fi;" \ "load ${devtype} ${devnum}:${distro_bootpart} " \ "${kernel_addr_r} efi/boot/"BOOTEFI_NAME"; " \ "if fdt addr ${fdt_addr_r}; then " \ diff --git a/include/efi_api.h b/include/efi_api.h index 1aae96355f..d0aefa8221 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -211,6 +211,10 @@ struct efi_runtime_services { EFI_GUID(0x00000000, 0x0000, 0x0000, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00) +#define EFI_GLOBAL_VARIABLE_GUID \ + EFI_GUID(0x8be4df61, 0x93ca, 0x11d2, 0xaa, 0x0d, \ + 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c) + #define LOADED_IMAGE_PROTOCOL_GUID \ EFI_GUID(0x5b1b31a1, 0x9562, 0x11d2, 0x8e, 0x3f, \ 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b) diff --git a/include/efi_loader.h b/include/efi_loader.h index 9eee62dc9c..adc0bcf609 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -61,6 +61,7 @@ extern const struct efi_device_path_to_text_protocol efi_device_path_to_text; uint16_t *efi_dp_str(struct efi_device_path *dp); +extern const efi_guid_t efi_global_variable_guid; extern const efi_guid_t efi_guid_console_control; extern const efi_guid_t efi_guid_device_path; extern const efi_guid_t efi_guid_loaded_image; @@ -209,6 +210,8 @@ efi_status_t efi_install_configuration_table(const efi_guid_t *guid, void *table void efi_setup_loaded_image(struct efi_loaded_image *info, struct efi_object *obj, struct efi_device_path *device_path, struct efi_device_path *file_path); +efi_status_t efi_load_image_from_path(struct efi_device_path *file_path, + void **buffer); #ifdef CONFIG_EFI_LOADER_BOUNCE_BUFFER extern void *efi_bounce_buffer; @@ -287,6 +290,9 @@ efi_status_t EFIAPI efi_set_variable(s16 *variable_name, efi_guid_t *vendor, u32 attributes, unsigned long data_size, void *data); +void *efi_bootmgr_load(struct efi_device_path **device_path, + struct efi_device_path **file_path); + #else /* defined(EFI_LOADER) && !defined(CONFIG_SPL_BUILD) */ /* Without CONFIG_EFI_LOADER we don't have a runtime section, stub it out */ diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile index f58cb13337..930c0e218e 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -16,7 +16,7 @@ always := $(efiprogs-y) obj-$(CONFIG_CMD_BOOTEFI_HELLO) += helloworld_efi.o obj-y += efi_image_loader.o efi_boottime.o efi_runtime.o efi_console.o obj-y += efi_memory.o efi_device_path_to_text.o efi_device_path.o -obj-y += efi_file.o efi_variable.o +obj-y += efi_file.o efi_variable.o efi_bootmgr.o obj-$(CONFIG_LCD) += efi_gop.o obj-$(CONFIG_DM_VIDEO) += efi_gop.o obj-$(CONFIG_PARTITIONS) += efi_disk.o diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c new file mode 100644 index 0000000000..9b2d39944e --- /dev/null +++ b/lib/efi_loader/efi_bootmgr.c @@ -0,0 +1,169 @@ +/* + * EFI utils + * + * Copyright (c) 2017 Rob Clark + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + +static const struct efi_boot_services *bs; +static const struct efi_runtime_services *rs; + +#define LOAD_OPTION_ACTIVE 0x00000001 +#define LOAD_OPTION_FORCE_RECONNECT 0x00000002 +#define LOAD_OPTION_HIDDEN 0x00000008 + +/* + * bootmgr implements the logic of trying to find a payload to boot + * based on the BootOrder + BootXXXX variables, and then loading it. + * + * TODO detecting a special key held (f9?) and displaying a boot menu + * like you would get on a PC would be clever. + * + * TODO if we had a way to write and persist variables after the OS + * has started, we'd also want to check OsIndications to see if we + * should do normal or recovery boot. + */ + + +/* + * See section 3.1.3 in the v2.7 UEFI spec for more details on + * the layout of EFI_LOAD_OPTION. In short it is: + * + * typedef struct _EFI_LOAD_OPTION { + * UINT32 Attributes; + * UINT16 FilePathListLength; + * // CHAR16 Description[]; <-- variable length, NULL terminated + * // EFI_DEVICE_PATH_PROTOCOL FilePathList[]; <-- FilePathListLength bytes + * // UINT8 OptionalData[]; + * } EFI_LOAD_OPTION; + */ +struct load_option { + u32 attributes; + u16 file_path_length; + u16 *label; + struct efi_device_path *file_path; + u8 *optional_data; +}; + +static void parse_load_option(struct load_option *lo, void *ptr) +{ + lo->attributes = *(u32 *)ptr; + ptr += sizeof(u32); + + lo->file_path_length = *(u16 *)ptr; + ptr += sizeof(u16); + + lo->label = ptr; + ptr += (utf16_strlen(lo->label) + 1) * 2; + + lo->file_path = ptr; + ptr += lo->file_path_length; + + lo->optional_data = ptr; +} + +/* free() the result */ +static void *get_var(u16 *name, const efi_guid_t *vendor, + unsigned long *size) +{ + efi_guid_t *v = (efi_guid_t *)vendor; + efi_status_t ret; + void *buf = NULL; + + *size = 0; + EFI_CALL(ret = rs->get_variable((s16 *)name, v, NULL, size, buf)); + if (ret == EFI_BUFFER_TOO_SMALL) { + buf = malloc(*size); + EFI_CALL(ret = rs->get_variable((s16 *)name, v, NULL, size, buf)); + } + + if (ret != EFI_SUCCESS) { + free(buf); + *size = 0; + return NULL; + } + + return buf; +} + +static void *try_load_entry(uint16_t n, struct efi_device_path **device_path, + struct efi_device_path **file_path) +{ + struct load_option lo; + u16 varname[] = L"Boot0000"; + u16 hexmap[] = L"0123456789ABCDEF"; + void *load_option, *image = NULL; + unsigned long size; + + varname[4] = hexmap[(n & 0xf000) >> 12]; + varname[5] = hexmap[(n & 0x0f00) >> 8]; + varname[6] = hexmap[(n & 0x00f0) >> 4]; + varname[7] = hexmap[(n & 0x000f) >> 0]; + + load_option = get_var(varname, &efi_global_variable_guid, &size); + if (!load_option) + return NULL; + + parse_load_option(&lo, load_option); + + if (lo.attributes & LOAD_OPTION_ACTIVE) { + efi_status_t ret; + u16 *str = NULL; + + debug("%s: trying to load \"%ls\" from: %ls\n", __func__, + lo.label, (str = efi_dp_str(lo.file_path))); + efi_free_pool(str); + + ret = efi_load_image_from_path(lo.file_path, &image); + + if (ret != EFI_SUCCESS) + goto error; + + printf("Booting: %ls\n", lo.label); + efi_dp_split_file_path(lo.file_path, device_path, file_path); + } + +error: + free(load_option); + + return image; +} + +void *efi_bootmgr_load(struct efi_device_path **device_path, + struct efi_device_path **file_path) +{ + uint16_t *bootorder; + unsigned long size; + void *image = NULL; + int i, num; + + __efi_entry_check(); + + bs = systab.boottime; + rs = systab.runtime; + + bootorder = get_var(L"BootOrder", &efi_global_variable_guid, &size); + if (!bootorder) + goto error; + + num = size / sizeof(uint16_t); + for (i = 0; i < num; i++) { + debug("%s: trying to load Boot%04X\n", __func__, bootorder[i]); + image = try_load_entry(bootorder[i], device_path, file_path); + if (image) + break; + } + + free(bootorder); + +error: + __efi_exit_check(); + + return image; +} diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index c406ff82ff..cea242cd49 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -763,8 +763,8 @@ void efi_setup_loaded_image(struct efi_loaded_image *info, struct efi_object *ob list_add_tail(&obj->link, &efi_obj_list); } -static efi_status_t load_image_from_path(struct efi_device_path *file_path, - void **buffer) +efi_status_t efi_load_image_from_path(struct efi_device_path *file_path, + void **buffer) { struct efi_file_info *info = NULL; struct efi_file_handle *f; @@ -824,7 +824,7 @@ static efi_status_t EFIAPI efi_load_image(bool boot_policy, struct efi_device_path *dp, *fp; efi_status_t ret; - ret = load_image_from_path(file_path, &source_buffer); + ret = efi_load_image_from_path(file_path, &source_buffer); if (ret != EFI_SUCCESS) { free(info); free(obj); diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c index 469acae082..242e6a504b 100644 --- a/lib/efi_loader/efi_image_loader.c +++ b/lib/efi_loader/efi_image_loader.c @@ -15,6 +15,7 @@ DECLARE_GLOBAL_DATA_PTR; +const efi_guid_t efi_global_variable_guid = EFI_GLOBAL_VARIABLE_GUID; const efi_guid_t efi_guid_device_path = DEVICE_PATH_GUID; const efi_guid_t efi_guid_loaded_image = LOADED_IMAGE_GUID; const efi_guid_t efi_simple_file_system_protocol_guid = From patchwork Sun Sep 10 11:21:42 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Clark X-Patchwork-Id: 812113 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="rhJlTUUc"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3xqpsm5z1Jz9sDB for ; Sun, 10 Sep 2017 21:36:12 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 92C46C21EFC; Sun, 10 Sep 2017 11:29:06 +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 A5B5FC21EA7; Sun, 10 Sep 2017 11:25:44 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 314B8C21F0B; Sun, 10 Sep 2017 11:24:01 +0000 (UTC) Received: from mail-qk0-f193.google.com (mail-qk0-f193.google.com [209.85.220.193]) by lists.denx.de (Postfix) with ESMTPS id 3FDAFC21E99 for ; Sun, 10 Sep 2017 11:23:52 +0000 (UTC) Received: by mail-qk0-f193.google.com with SMTP id o77so3977747qke.2 for ; Sun, 10 Sep 2017 04:23:52 -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=aVs62jdusCV4U13TNa5Z8JR5qecfUqasBVP2m7gcUPM=; b=rhJlTUUc/92H6MYqFK0fIFG2Mshp8B0U/RfMDuXYCEgzS67FOXu1oX85SOio5jjmpi dpEHzre+xqDfcaOwxLvP8wFDpTBSLJkRv/35rFdiX6ENbrT8pgAxSUqNFUBWvTk/Z5yG vRbkeXsWqofaBBuRYZaGX9D5/7yQjK9UBfDSGnfi9H/HRg9jYFAERLL4gtN/i8xvB08/ 8Uep9WRMGCpX80ylm+171R6B9kG4abcOHQw8DbWnUXu4gcuP3Enc2NMofw+/AkV/Yqa7 YHqBD3HwPth9bXkmO0pgLjir8QLxFIdJB4mhKcb3JSMA5PiDdKJrjGU5ncUPIVdlNkR0 PlFQ== 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=aVs62jdusCV4U13TNa5Z8JR5qecfUqasBVP2m7gcUPM=; b=tKImFhrGoz4V15x31imJsBi1dvO+WX/FuKwMjn8z5Y6IfBwe/XlPWqr352F9816zN1 sDgz+Q6lPb429askD6/kTEEnnMIx8BlG52Vydt8U1ZOkLG9NF6Q3E0vERaHJXUqul/VT WBxIq6Q8tVYlHlVgUpxVMSh3ZauVbZkI/tayA60bAMPY4So+FMlptFiQBMYme9ecGre7 CIofhSFyGHPmts/bj1Lcm4mStrAiqo8bmyLhAUNE9ldHZ4Pw3IECNUYqb2SGMSvFvRey TToANId0gW+TTa/IU4EuK7ZKXXVOkClPO1SacgrgwMMTUy7duq/bJAItxkjNBp0ZqRrV srNw== X-Gm-Message-State: AHPjjUhvzqItr2/aFs5mXCRMjR1lc+bhwqaWuxpapsC0RTmAqsIEc4a7 shClu4BhTmCoWLVS6yQ= X-Google-Smtp-Source: AOwi7QA+0eSDBGe9CFpUMDuXbeFYqgiw82VIB/CN8C5u8mhjKIyyrQsjBP0w13rNBi31ZUbsvWXZcA== X-Received: by 10.233.230.1 with SMTP id z1mr10607588qkf.198.1505042631036; Sun, 10 Sep 2017 04:23:51 -0700 (PDT) Received: from localhost ([2601:184:4780:aac0:25f8:dd96:a084:785a]) by smtp.gmail.com with ESMTPSA id e18sm4452286qtc.59.2017.09.10.04.23.49 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sun, 10 Sep 2017 04:23:49 -0700 (PDT) From: Rob Clark To: U-Boot Mailing List Date: Sun, 10 Sep 2017 07:21:42 -0400 Message-Id: <20170910112149.21358-26-robdclark@gmail.com> X-Mailer: git-send-email 2.13.5 In-Reply-To: <20170910112149.21358-1-robdclark@gmail.com> References: <20170910112149.21358-1-robdclark@gmail.com> Cc: Heinrich Schuchardt , Peter Jones Subject: [U-Boot] [PATCH v2 16/21] efi_loader: file_path should be variable length 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" After "efi_loader: refactor boot device and loaded_image handling" we can drop this hack. Signed-off-by: Rob Clark --- include/efi_api.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/efi_api.h b/include/efi_api.h index d0aefa8221..604c5b7ec4 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -373,7 +373,7 @@ struct efi_device_path_cdrom_path { struct efi_device_path_file_path { struct efi_device_path dp; - u16 str[32]; + u16 str[]; } __packed; #define BLOCK_IO_GUID \ From patchwork Sun Sep 10 11:21:43 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Clark X-Patchwork-Id: 812124 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="jcIQosUJ"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3xqpzG744zz9sNV for ; Sun, 10 Sep 2017 21:40:58 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id B50A9C21F16; Sun, 10 Sep 2017 11:32:07 +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 DA42DC21F65; Sun, 10 Sep 2017 11:29:44 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 3C050C21E97; Sun, 10 Sep 2017 11:24:04 +0000 (UTC) Received: from mail-qt0-f193.google.com (mail-qt0-f193.google.com [209.85.216.193]) by lists.denx.de (Postfix) with ESMTPS id 484A6C21F5B for ; Sun, 10 Sep 2017 11:23:55 +0000 (UTC) Received: by mail-qt0-f193.google.com with SMTP id u48so1199436qtc.4 for ; Sun, 10 Sep 2017 04:23:55 -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=agLKFCHofSoXSGDDqTTx4I8hvrEJSirlG3r1W1vdczo=; b=jcIQosUJKyBJwLxzrxJUmsWmFhKR5B7UZq+zLZ/X/zCXpGMlNYLLJTjlUoN9NOCyut T1MvWKxqiF0hFmH8n7awyZjUZPXb58iAQma5kW0VYmBtvoN44oa2MOb3fScE2FNYu0l/ T1O4u3O5cq13Bn+t5ShXpu5dCOA90FGnFaglRb9md3vy41MD+HaKszvwOAqdoCK8wtOp NZI2tjIOH7ZAtgExqBrGmCX82IM+zdUCqo2WbCV9duN9jkJWJNTF8MqyCu0T3WmSi6Iy fTeYp6WD1540Lr0DNoMUB4BN7Nst6LbYTF/zvZMMhORtaml8IQo1OOffSM93TGbEoqJC lX4g== 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=agLKFCHofSoXSGDDqTTx4I8hvrEJSirlG3r1W1vdczo=; b=XI70dPtD3rEDRZGPHKSMtbFYUj/VWoveF4OR1YbpH09H+rNj587ne7n8iG+7t7GM6g juX2RnrpVpP0ymyNq1KYjYNpUNPmAA+gl0RHByAvH767VGQjlP2Q8ytln+odWf2ZxJaY yNonueIEeS39ulwbX+CIYWPbRKswfD5sgxQLJ2MLIYT/H++KbzyrMKgcuWF69gCR8kGA 9OU60uNT6L+kpN80csGdlaKuFCXvcAZbQlOOnnTyJpFxUVbw+5eZAxFQedzBi94TXnvo nckufllWfFa9WM9NOUJ40lHCxMW+8nAzb5gSfzqgcPv991zzhfAQI1fDFaPCPVOZAxGr O/Fg== X-Gm-Message-State: AHPjjUjQaK+COIEyb3LfVK6bbSXt8mgd9+3JbMWjhq8jzeT8lwXk4Mvs 7L4wGy25kYtesSjBw4E= X-Google-Smtp-Source: AOwi7QBxuzLj5a0vL95orDqaRZ8+Mu/H6KABnygOlptvmyvFUmw2B3PcMF1CggGKO6sIdctlHR54xQ== X-Received: by 10.200.52.232 with SMTP id x37mr12122870qtb.85.1505042634021; Sun, 10 Sep 2017 04:23:54 -0700 (PDT) Received: from localhost ([2601:184:4780:aac0:25f8:dd96:a084:785a]) by smtp.gmail.com with ESMTPSA id 13sm4588046qtp.74.2017.09.10.04.23.52 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sun, 10 Sep 2017 04:23:52 -0700 (PDT) From: Rob Clark To: U-Boot Mailing List Date: Sun, 10 Sep 2017 07:21:43 -0400 Message-Id: <20170910112149.21358-27-robdclark@gmail.com> X-Mailer: git-send-email 2.13.5 In-Reply-To: <20170910112149.21358-1-robdclark@gmail.com> References: <20170910112149.21358-1-robdclark@gmail.com> Cc: Heinrich Schuchardt Subject: [U-Boot] [PATCH v2 17/21] efi_loader: set loaded image code/data type properly 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" These should be set according to the image type. Shell.efi and SCT.efi use these fields to determine what sort of image they are loading. Signed-off-by: Rob Clark --- include/pe.h | 6 ++++++ lib/efi_loader/efi_image_loader.c | 22 ++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/include/pe.h b/include/pe.h index deb35a0ea4..4ef3e92efa 100644 --- a/include/pe.h +++ b/include/pe.h @@ -62,6 +62,12 @@ typedef struct _IMAGE_DATA_DIRECTORY { #define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 +/* PE32+ Subsystem type for EFI images */ +#define IMAGE_SUBSYSTEM_EFI_APPLICATION 10 +#define IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11 +#define IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12 +#define IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER 13 + typedef struct _IMAGE_OPTIONAL_HEADER64 { uint16_t Magic; /* 0x20b */ uint8_t MajorLinkerVersion; diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c index 242e6a504b..af29cc4f04 100644 --- a/lib/efi_loader/efi_image_loader.c +++ b/lib/efi_loader/efi_image_loader.c @@ -94,6 +94,7 @@ void *efi_load_pe(void *efi, struct efi_loaded_image *loaded_image_info) unsigned long virt_size = 0; bool can_run_nt64 = true; bool can_run_nt32 = true; + uint16_t image_type; #if defined(CONFIG_ARM64) can_run_nt32 = false; @@ -139,6 +140,7 @@ void *efi_load_pe(void *efi, struct efi_loaded_image *loaded_image_info) entry = efi_reloc + opt->AddressOfEntryPoint; rel_size = opt->DataDirectory[rel_idx].Size; rel = efi_reloc + opt->DataDirectory[rel_idx].VirtualAddress; + image_type = opt->Subsystem; } else if (can_run_nt32 && (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)) { IMAGE_OPTIONAL_HEADER32 *opt = &nt->OptionalHeader; @@ -152,12 +154,32 @@ void *efi_load_pe(void *efi, struct efi_loaded_image *loaded_image_info) entry = efi_reloc + opt->AddressOfEntryPoint; rel_size = opt->DataDirectory[rel_idx].Size; rel = efi_reloc + opt->DataDirectory[rel_idx].VirtualAddress; + image_type = opt->Subsystem; } else { printf("%s: Invalid optional header magic %x\n", __func__, nt->OptionalHeader.Magic); return NULL; } + switch (image_type) { + case IMAGE_SUBSYSTEM_EFI_APPLICATION: + loaded_image_info->image_code_type = EFI_LOADER_CODE; + loaded_image_info->image_data_type = EFI_LOADER_DATA; + break; + case IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER: + loaded_image_info->image_code_type = EFI_BOOT_SERVICES_CODE; + loaded_image_info->image_data_type = EFI_BOOT_SERVICES_DATA; + break; + case IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER: + case IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER: + loaded_image_info->image_code_type = EFI_RUNTIME_SERVICES_CODE; + loaded_image_info->image_data_type = EFI_RUNTIME_SERVICES_DATA; + break; + default: + printf("%s: invalid image type: %u\n", __func__, image_type); + break; + } + /* Load sections into RAM */ for (i = num_sections - 1; i >= 0; i--) { IMAGE_SECTION_HEADER *sec = §ions[i]; From patchwork Sun Sep 10 11:21:44 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Clark X-Patchwork-Id: 812125 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="JGt8GNKO"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3xqpzv1FQnz9sDB for ; Sun, 10 Sep 2017 21:41:31 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id E04E2C21E3C; Sun, 10 Sep 2017 11:30:21 +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 280FDC21F64; Sun, 10 Sep 2017 11:26:37 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 6E5BEC21F56; Sun, 10 Sep 2017 11:24:07 +0000 (UTC) Received: from mail-qt0-f194.google.com (mail-qt0-f194.google.com [209.85.216.194]) by lists.denx.de (Postfix) with ESMTPS id 55CBDC21F51 for ; Sun, 10 Sep 2017 11:23:58 +0000 (UTC) Received: by mail-qt0-f194.google.com with SMTP id u48so1199456qtc.4 for ; Sun, 10 Sep 2017 04:23:58 -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=JxCT757wgQICSsbBlPdYYntd3CmqgUV/Om6Fv6OmC04=; b=JGt8GNKOkMS7rSWK4Q9YMblJaTj7o77UekWH3S5sOvlqr/V+D2XCcoWQgQAUMGBQkK L6XWPHBxdgk6rPKciILKiRoajViJXp7ze9C43yx41fSMQd88M+KWPuLC3opKh3jEjWUM 5tPpYPQFTFaA8lo8bRIjweVxUnBn4yNMNAQchn4wCi6MYnwTv4J25XnECtJyuUy6ifTI i+RFE6mDHpE9YBr3/RBINmIz5fqPdkZq3itUPTAdSdYeba3LKTmeahjRrfKLSxhDeDnd 4eIuL0VgSeElXb4+YfNQKpdQP8JM8jbLYofgPIsPJhtnXNjiDB56sBWk65Kt3C/Xdpxv XEyA== 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=JxCT757wgQICSsbBlPdYYntd3CmqgUV/Om6Fv6OmC04=; b=oOtyJctdo0udTbTRQcpAmOx/MW4eWw8HnffB+8AiakQdNVI0bCyh7rYc6G56Qt51ta 3gVHKrm1ruKgVKs3IrJyDw5FXF8IiAkDq4KJLSUyF1zNGff49prgg2sfBmsM4GeW5l1K ZQ0w13MXHhWMsimfPHb3l4e7Bi24GmjClV0z/doTNqYCwxzeKyh4LHtfmZGJz0sL1Au3 PCDy+2b2pjtOYHX0fvt8CGe1/hUFSTU/9hKYzU5eWyo0mP+h4YW6LiQFaDEP65B2z0SE P7n13tQbRUhOaz31TxXjY46Wo2TT6pPCLaTSkb/JHQHwMxB75umrmRSe7De9u+ngo1NJ 848w== X-Gm-Message-State: AHPjjUgmubmg7Eo2LG1bTVqyG/P6AFpxy3eYjvG8wll7gcitmAdAtf53 +5NXMcZeoA3sBng7UG4= X-Google-Smtp-Source: AOwi7QCOR8QZ+Mht9wVmMv5MrI338ub18bOBuFYQJdjI+wXqxoZL685hoMCFe6ZwwFQIk7OHvUv3SA== X-Received: by 10.200.28.117 with SMTP id j50mr11252093qtk.312.1505042636909; Sun, 10 Sep 2017 04:23:56 -0700 (PDT) Received: from localhost ([2601:184:4780:aac0:25f8:dd96:a084:785a]) by smtp.gmail.com with ESMTPSA id t32sm4489679qtb.5.2017.09.10.04.23.55 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sun, 10 Sep 2017 04:23:55 -0700 (PDT) From: Rob Clark To: U-Boot Mailing List Date: Sun, 10 Sep 2017 07:21:44 -0400 Message-Id: <20170910112149.21358-28-robdclark@gmail.com> X-Mailer: git-send-email 2.13.5 In-Reply-To: <20170910112149.21358-1-robdclark@gmail.com> References: <20170910112149.21358-1-robdclark@gmail.com> Cc: Heinrich Schuchardt Subject: [U-Boot] [PATCH v2 18/21] efi_loader: print GUIDs 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" Utilize printf GUID support to print GUIDs. Signed-off-by: Rob Clark --- lib/efi_loader/efi_boottime.c | 22 +++++++++++----------- lib/efi_loader/efi_variable.c | 6 +++--- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index cea242cd49..b6f32c98d9 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -514,7 +514,7 @@ static efi_status_t EFIAPI efi_install_protocol_interface_ext(void **handle, efi_guid_t *protocol, int protocol_interface_type, void *protocol_interface) { - EFI_ENTRY("%p, %p, %d, %p", handle, protocol, protocol_interface_type, + EFI_ENTRY("%p, %pUl, %d, %p", handle, protocol, protocol_interface_type, protocol_interface); return EFI_EXIT(efi_install_protocol_interface(handle, protocol, @@ -526,7 +526,7 @@ static efi_status_t EFIAPI efi_reinstall_protocol_interface(void *handle, efi_guid_t *protocol, void *old_interface, void *new_interface) { - EFI_ENTRY("%p, %p, %p, %p", handle, protocol, old_interface, + EFI_ENTRY("%p, %pUl, %p, %p", handle, protocol, old_interface, new_interface); return EFI_EXIT(EFI_ACCESS_DENIED); } @@ -575,7 +575,7 @@ out: static efi_status_t EFIAPI efi_uninstall_protocol_interface_ext(void *handle, efi_guid_t *protocol, void *protocol_interface) { - EFI_ENTRY("%p, %p, %p", handle, protocol, protocol_interface); + EFI_ENTRY("%p, %pUl, %p", handle, protocol, protocol_interface); return EFI_EXIT(efi_uninstall_protocol_interface(handle, protocol, protocol_interface)); @@ -585,7 +585,7 @@ static efi_status_t EFIAPI efi_register_protocol_notify(efi_guid_t *protocol, struct efi_event *event, void **registration) { - EFI_ENTRY("%p, %p, %p", protocol, event, registration); + EFI_ENTRY("%pUl, %p, %p", protocol, event, registration); return EFI_EXIT(EFI_OUT_OF_RESOURCES); } @@ -655,7 +655,7 @@ static efi_status_t EFIAPI efi_locate_handle_ext( efi_guid_t *protocol, void *search_key, unsigned long *buffer_size, efi_handle_t *buffer) { - EFI_ENTRY("%d, %p, %p, %p, %p", search_type, protocol, search_key, + EFI_ENTRY("%d, %pUl, %p, %p, %p", search_type, protocol, search_key, buffer_size, buffer); return EFI_EXIT(efi_locate_handle(search_type, protocol, search_key, @@ -723,7 +723,7 @@ efi_status_t efi_install_configuration_table(const efi_guid_t *guid, void *table static efi_status_t EFIAPI efi_install_configuration_table_ext(efi_guid_t *guid, void *table) { - EFI_ENTRY("%p, %p", guid, table); + EFI_ENTRY("%pUl, %p", guid, table); return EFI_EXIT(efi_install_configuration_table(guid, table)); } @@ -1012,7 +1012,7 @@ static efi_status_t EFIAPI efi_close_protocol(void *handle, void *agent_handle, void *controller_handle) { - EFI_ENTRY("%p, %p, %p, %p", handle, protocol, agent_handle, + EFI_ENTRY("%p, %pUl, %p, %p", handle, protocol, agent_handle, controller_handle); return EFI_EXIT(EFI_NOT_FOUND); } @@ -1022,7 +1022,7 @@ static efi_status_t EFIAPI efi_open_protocol_information(efi_handle_t handle, struct efi_open_protocol_info_entry **entry_buffer, unsigned long *entry_count) { - EFI_ENTRY("%p, %p, %p, %p", handle, protocol, entry_buffer, + EFI_ENTRY("%p, %pUl, %p, %p", handle, protocol, entry_buffer, entry_count); return EFI_EXIT(EFI_NOT_FOUND); } @@ -1088,7 +1088,7 @@ static efi_status_t EFIAPI efi_locate_handle_buffer( efi_status_t r; unsigned long buffer_size = 0; - EFI_ENTRY("%d, %p, %p, %p, %p", search_type, protocol, search_key, + EFI_ENTRY("%d, %pUl, %p, %p, %p", search_type, protocol, search_key, no_handles, buffer); if (!no_handles || !buffer) { @@ -1120,7 +1120,7 @@ static efi_status_t EFIAPI efi_locate_protocol(efi_guid_t *protocol, struct list_head *lhandle; int i; - EFI_ENTRY("%p, %p, %p", protocol, registration, protocol_interface); + EFI_ENTRY("%pUl, %p, %p", protocol, registration, protocol_interface); if (!protocol || !protocol_interface) return EFI_EXIT(EFI_INVALID_PARAMETER); @@ -1228,7 +1228,7 @@ static efi_status_t EFIAPI efi_open_protocol( int i; efi_status_t r = EFI_INVALID_PARAMETER; - EFI_ENTRY("%p, %p, %p, %p, %p, 0x%x", handle, protocol, + EFI_ENTRY("%p, %pUl, %p, %p, %p, 0x%x", handle, protocol, protocol_interface, agent_handle, controller_handle, attributes); diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c index 5569b3d3f0..6c177da3a6 100644 --- a/lib/efi_loader/efi_variable.c +++ b/lib/efi_loader/efi_variable.c @@ -187,7 +187,7 @@ efi_status_t EFIAPI efi_get_variable(s16 *variable_name, const char *val, *s; u32 attr; - EFI_ENTRY("%p %p %p %p %p", variable_name, vendor, attributes, + EFI_ENTRY("\"%ls\" %pUl %p %p %p", variable_name, vendor, attributes, data_size, data); if (!variable_name || !vendor || !data_size) @@ -255,7 +255,7 @@ efi_status_t EFIAPI efi_get_next_variable( unsigned long *variable_name_size, s16 *variable_name, efi_guid_t *vendor) { - EFI_ENTRY("%p %p %p", variable_name_size, variable_name, vendor); + EFI_ENTRY("%p \"%ls\" %pUl", variable_name_size, variable_name, vendor); return EFI_EXIT(EFI_DEVICE_ERROR); } @@ -270,7 +270,7 @@ efi_status_t EFIAPI efi_set_variable(s16 *variable_name, char *val, *s; u32 attr; - EFI_ENTRY("%p %p %x %lu %p", variable_name, vendor, attributes, + EFI_ENTRY("\"%ls\" %pUl %x %lu %p", variable_name, vendor, attributes, data_size, data); if (!variable_name || !vendor) From patchwork Sun Sep 10 11:21:45 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Clark X-Patchwork-Id: 812116 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="boxm05w7"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3xqpvj447Bz9sDB for ; Sun, 10 Sep 2017 21:37:53 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 4C9B6C21E8C; Sun, 10 Sep 2017 11:29:51 +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 5D41FC21F2D; Sun, 10 Sep 2017 11:26:26 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 85C7DC21E41; Sun, 10 Sep 2017 11:24:10 +0000 (UTC) Received: from mail-qt0-f194.google.com (mail-qt0-f194.google.com [209.85.216.194]) by lists.denx.de (Postfix) with ESMTPS id 5F7DBC21F0A for ; Sun, 10 Sep 2017 11:24:01 +0000 (UTC) Received: by mail-qt0-f194.google.com with SMTP id q8so4090729qtb.1 for ; Sun, 10 Sep 2017 04:24:01 -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=zmASFMSzYWSBSdugC77vjUNtmmQgCCSF2tHQAtczTpw=; b=boxm05w7nVv48S45/bKwIKjF/Gp5Wtx9LgdVGxLs4c1upk7qJyh6zakp5SigduKBZO PINwNEdq3jfhH96AQds5mmT0/kfpaCQG7johB8Mgp7wvldhvsZxMWZfgBIgEEY57WfL0 Z3yTvA45ewyhnGjCvAeDWmFGvT3ucrvifLl/sOfUWWI0BBJ6cNu/2YQ69T33teQOO/pe 89pIj3Rj3wLr94wBtgl89/Zfu5IqJ6Rfu7WPsM6FHxO+tnSFJb5ZtjjlPrKIrRlV2oD/ BNarFUIYM8Q1SBgWfz/DNvuSDAu0TeiPLN1D37+BGJdpFyiT060tba4DK8iKR+GcYJLe tCGA== 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=zmASFMSzYWSBSdugC77vjUNtmmQgCCSF2tHQAtczTpw=; b=UlnP43pYeNuq3ZLXolFVUuCl5EGcAh2wi1DmL2ugyPotkgECCFOvCCtz9uyRySNwlG V6lYbcG6XilDrhFDcZVhBa6fDoUweusrgJNo9IgP6RiYn1jFRBpF9CTy9hf73wgKNWwJ k2FDGXzoh25MM8bnel8Td92WGhnM2n+nAOy5EesrDhiYZxAxFG61XY0pxCr94+04xrSd t4aoG4ZEfeYnO1G2hpKBc4y+yc5jjYtSC4h1pyOf1xclLK1wZlGyhs5lcr3sxK+6l8pi sp0D8FobaQCP86ysmNGmVRdTtmN28jLqpYcyHs+luslV/YbcaQxdIcPWaGZPc52vgYG8 e+Hg== X-Gm-Message-State: AHPjjUjUX4L3f7R3yzpAyqpao5bkUf41cydAvvaWiW0kA/reor9mpd36 sJ81NNQdTs2aU30krxk= X-Google-Smtp-Source: AOwi7QDbGNeIw41Jee/zf19SfBxERxFMhqM2sxKduamVZLkC2TWM0sE/Kw2cM89WP9iDael+VaBxOw== X-Received: by 10.200.50.149 with SMTP id z21mr12918338qta.37.1505042640131; Sun, 10 Sep 2017 04:24:00 -0700 (PDT) Received: from localhost ([2601:184:4780:aac0:25f8:dd96:a084:785a]) by smtp.gmail.com with ESMTPSA id k20sm4185334qtj.2.2017.09.10.04.23.58 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sun, 10 Sep 2017 04:23:58 -0700 (PDT) From: Rob Clark To: U-Boot Mailing List Date: Sun, 10 Sep 2017 07:21:45 -0400 Message-Id: <20170910112149.21358-29-robdclark@gmail.com> X-Mailer: git-send-email 2.13.5 In-Reply-To: <20170910112149.21358-1-robdclark@gmail.com> References: <20170910112149.21358-1-robdclark@gmail.com> Cc: Heinrich Schuchardt Subject: [U-Boot] [PATCH v2 19/21] efi_loader: split out escape sequence based size query 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 need to do something different for vidconsole, since it cannot respond to the query on stdin. Prep work for next patch. Signed-off-by: Rob Clark --- lib/efi_loader/efi_console.c | 53 +++++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c index 3fc82b8726..e8c02870eb 100644 --- a/lib/efi_loader/efi_console.c +++ b/lib/efi_loader/efi_console.c @@ -186,6 +186,34 @@ static bool cout_mode_matches(struct cout_mode *mode, int rows, int cols) return (mode->rows == rows) && (mode->columns == cols); } +static int query_console_serial(int *rows, int *cols) +{ + /* Ask the terminal about its size */ + int n[3]; + u64 timeout; + + /* Empty input buffer */ + while (tstc()) + getc(); + + printf(ESC"[18t"); + + /* Check if we have a terminal that understands */ + timeout = timer_get_us() + 1000000; + while (!tstc()) + if (timer_get_us() > timeout) + return -1; + + /* Read {depth,rows,cols} */ + if (term_read_reply(n, 3, 't')) + return -1; + + *cols = n[2]; + *rows = n[1]; + + return 0; +} + static efi_status_t EFIAPI efi_cout_query_mode( struct efi_simple_text_output_protocol *this, unsigned long mode_number, unsigned long *columns, @@ -194,33 +222,12 @@ static efi_status_t EFIAPI efi_cout_query_mode( EFI_ENTRY("%p, %ld, %p, %p", this, mode_number, columns, rows); if (!console_size_queried) { - /* Ask the terminal about its size */ - int n[3]; - int cols; - int rows; - u64 timeout; + int rows, cols; console_size_queried = true; - /* Empty input buffer */ - while (tstc()) - getc(); - - printf(ESC"[18t"); - - /* Check if we have a terminal that understands */ - timeout = timer_get_us() + 1000000; - while (!tstc()) - if (timer_get_us() > timeout) - goto out; - - /* Read {depth,rows,cols} */ - if (term_read_reply(n, 3, 't')) { + if (query_console_serial(&rows, &cols)) goto out; - } - - cols = n[2]; - rows = n[1]; /* Test if we can have Mode 1 */ if (cols >= 80 && rows >= 50) { From patchwork Sun Sep 10 11:21:46 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Clark X-Patchwork-Id: 812119 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="FLqNBvcD"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3xqpxr2SB3z9sDB for ; Sun, 10 Sep 2017 21:39:44 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id D4743C21F6A; Sun, 10 Sep 2017 11:31:38 +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 7E3CBC21EA8; Sun, 10 Sep 2017 11:29:26 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 1DBD3C21F12; Sun, 10 Sep 2017 11:24:13 +0000 (UTC) Received: from mail-qt0-f193.google.com (mail-qt0-f193.google.com [209.85.216.193]) by lists.denx.de (Postfix) with ESMTPS id 3507FC21F5B for ; Sun, 10 Sep 2017 11:24:04 +0000 (UTC) Received: by mail-qt0-f193.google.com with SMTP id b1so1748041qtc.0 for ; Sun, 10 Sep 2017 04:24:04 -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=vtK1zZTLszv9J+4U8WH5KLG+0f5uZYnvDQoIBqpAXI4=; b=FLqNBvcDzWl+xPdi1uy7SNJqaf5h2slDJUNiRes2rQLmLYIMPQqBOPyGyQaAKQpuCQ Kn275vLQdFIHtkK4Vjij/wn1aieRmZVymmzUgqqSijR+WFeiqjKKCoJsIUYFq9odyJw1 q3XUvA1eZ2Q4R+P7EYIFj/dEgAZA4kT8gwvbdaLxacVNuP+FoFOe8yoiMxHqeyYKJUrZ f5yCn28rpTpJBUA2yAQmwuejp3gcOj87FUfPBL01NWAYXGeKfAG4sL2SRxuHQrNx/+4y dMfzLd0/uDtAno0J6VIRtPMU6Lh0ze2X3zp8fqMOFlJJ1+B6cOVcElgcKgssX7Z1RFf2 rrtQ== 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=vtK1zZTLszv9J+4U8WH5KLG+0f5uZYnvDQoIBqpAXI4=; b=FIyGO5kLpUSZC7U3drjtrRIvrhqVA4SPcLucQ/xcL5pVUirCgi78nxguPid2tfMe8g d7jEt1FP1OZWADSgQCCkZi/MmbYvL+BjGi1PoLGY5ERvmpStlSP7e2WzBsuiRoTW7OSx pjRo5BwiP+m+sPIyz2v2/9Qxy2ZgmRjPNX7irJLJrJTUObtJemiuJ/D884pQn3aCwZUa 92UG6z9wbtCrw2CoyXqpSDhL+tfELSxguWhaBqkxJkjAuTz6YizWics9VXn+zle5tDhi jdcl/5fAmUjFvElPQWmkic9IJ4ycUFM0cX2AqMluD2HNhyRsuTUD91VJ1MYX96Pj1xj8 7YqQ== X-Gm-Message-State: AHPjjUgpplo08I/S53M0vtI8z9IV2cROhKTCCn94JbJK/934lLAvqzyC BVK461D3myhogy4BARY= X-Google-Smtp-Source: AOwi7QBx3Z0YISaGH6IhfzUh3vj8OaGfn5Ds5XMX+rMV27atAoRPUgqxvGzBXUj7KCZYQqRvLcj5LA== X-Received: by 10.200.36.132 with SMTP id s4mr11390958qts.4.1505042642947; Sun, 10 Sep 2017 04:24:02 -0700 (PDT) Received: from localhost ([2601:184:4780:aac0:25f8:dd96:a084:785a]) by smtp.gmail.com with ESMTPSA id a91sm4608856qka.90.2017.09.10.04.24.01 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sun, 10 Sep 2017 04:24:02 -0700 (PDT) From: Rob Clark To: U-Boot Mailing List Date: Sun, 10 Sep 2017 07:21:46 -0400 Message-Id: <20170910112149.21358-30-robdclark@gmail.com> X-Mailer: git-send-email 2.13.5 In-Reply-To: <20170910112149.21358-1-robdclark@gmail.com> References: <20170910112149.21358-1-robdclark@gmail.com> Cc: Heinrich Schuchardt Subject: [U-Boot] [PATCH v2 20/21] efi_loader: Correctly figure out size for vidconsole 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" If stdout is vidconsole, we cannot rely on ANSI escape sequences to query the size, as vidconsole cannot reply on stdin. Instead special- case this if stdout is vidconsole. Signed-off-by: Rob Clark --- lib/efi_loader/efi_console.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c index e8c02870eb..9048a8d32c 100644 --- a/lib/efi_loader/efi_console.c +++ b/lib/efi_loader/efi_console.c @@ -8,7 +8,10 @@ #include #include +#include #include +#include +#include static bool console_size_queried; @@ -222,12 +225,23 @@ static efi_status_t EFIAPI efi_cout_query_mode( EFI_ENTRY("%p, %ld, %p, %p", this, mode_number, columns, rows); if (!console_size_queried) { + const char *stdout_name = env_get("stdout"); int rows, cols; console_size_queried = true; - if (query_console_serial(&rows, &cols)) + if (stdout_name && !strcmp(stdout_name, "vidconsole") && + IS_ENABLED(CONFIG_DM_VIDEO)) { + struct stdio_dev *stdout_dev = + stdio_get_by_name("vidconsole"); + struct udevice *dev = stdout_dev->priv; + struct vidconsole_priv *priv = + dev_get_uclass_priv(dev); + rows = priv->rows; + cols = priv->cols; + } else if (query_console_serial(&rows, &cols)) { goto out; + } /* Test if we can have Mode 1 */ if (cols >= 80 && rows >= 50) { From patchwork Sun Sep 10 11:21:47 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Clark X-Patchwork-Id: 812121 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="s1ESsyG6"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3xqpy823rcz9sDB for ; Sun, 10 Sep 2017 21:40:00 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 09D51C21F88; Sun, 10 Sep 2017 11:31:22 +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 5BB99C21F71; Sun, 10 Sep 2017 11:27:44 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 40DA4C21F67; Sun, 10 Sep 2017 11:24:16 +0000 (UTC) Received: from mail-qt0-f193.google.com (mail-qt0-f193.google.com [209.85.216.193]) by lists.denx.de (Postfix) with ESMTPS id B8007C21F51 for ; Sun, 10 Sep 2017 11:24:07 +0000 (UTC) Received: by mail-qt0-f193.google.com with SMTP id b1so1748192qtc.0 for ; Sun, 10 Sep 2017 04:24:07 -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=tTjJNgm+knfE2IVXbgcSZPd7Q9s0s6Q4yiWNU5LVgTo=; b=s1ESsyG65rLQ/6Rlzdh3C3i4Xk22lvWe31+JZiL9wIRhC1vVzCk1E6yqqe5QTve/sd LATgRored6ptYfP8QIM2v6UbLkrhCHF49YiKw8sjgmy/xr4pCLd42SWUjrDMOVO4JYhi Qrkfwrq0UocvOluDd0SspJsqC0ZKwc5w+i4ubQNCUbCcyA6VkI22b01EMPuoJF3eZnt7 SAVUcVZgA+1/YVIxZOQLRdTAVDX0UOGnsr6qKnO4QMde/rbJcweUgpdTPsbzXiw4suyP w6GBP7l7MdVxJQhDlGI3CWyqDIiVtbtjjSfF3B6Zmv5TOQ6LvGPoIlkC211+h9oIr5Y8 zf3g== 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=tTjJNgm+knfE2IVXbgcSZPd7Q9s0s6Q4yiWNU5LVgTo=; b=Pk3jDHfNKMDutvf6USsdc5mBoxAEPx1qRvJabFuiQUidFOspHFwxHwDGZxUIxwAJ66 sKpvUmoLEW0XI1jQiYzt85apocd5AvYvmTDsx9e976U3eXtxaodNA7hNTsC59tI8Phwb lmuuAEeDSvne6KLfb7i3kwwR2Of+bGaS98ic+flLMSp/B7s6+wd2V6hSm4wyjPugkEas /vDR6dEGRQdU15+hJqrMUAIxZZ80J3wgmWTrhuKt52Y6TfauxG1kAjBrvbi93VHc8GIF +JquQN+HNTUVj7Oka2o+KZrtvk8Ek00OZeH3yLFmmFMmDm6wAOmweGK4/iazO4vTvW7c xEWA== X-Gm-Message-State: AHPjjUiWlVAmtu4YnGqQm/LTNHhucjHXXzBKNmRau5zOjWMDeoC4KeS3 2u3uDRKWulinjbXWxLQ= X-Google-Smtp-Source: AOwi7QBbP9gMRkJrZvZDdu65PQPUeD8DlGPC9Ph+CUYPjp25ykz9ust586etfP4W9cTSgo2gOdHKXA== X-Received: by 10.237.63.124 with SMTP id q57mr12042083qtf.23.1505042646474; Sun, 10 Sep 2017 04:24:06 -0700 (PDT) Received: from localhost ([2601:184:4780:aac0:25f8:dd96:a084:785a]) by smtp.gmail.com with ESMTPSA id f6sm4184549qtb.68.2017.09.10.04.24.05 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sun, 10 Sep 2017 04:24:05 -0700 (PDT) From: Rob Clark To: U-Boot Mailing List Date: Sun, 10 Sep 2017 07:21:47 -0400 Message-Id: <20170910112149.21358-31-robdclark@gmail.com> X-Mailer: git-send-email 2.13.5 In-Reply-To: <20170910112149.21358-1-robdclark@gmail.com> References: <20170910112149.21358-1-robdclark@gmail.com> Cc: Heinrich Schuchardt , Peter Jones Subject: [U-Boot] [PATCH v2 21/21] efi_loader: Some console improvements for vidconsole 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" 1) use fputs() to reduce cache flushes from once-per-char to once-per-string 2) handle \r, \t, and \b in addition to just \n for tracking cursor position 3) cursor row/col are zero based, not one based Signed-off-by: Rob Clark Reviewed-by: Simon Glass --- include/efi_api.h | 6 +++-- lib/efi_loader/efi_console.c | 58 ++++++++++++++++++++++++++------------------ 2 files changed, 39 insertions(+), 25 deletions(-) diff --git a/include/efi_api.h b/include/efi_api.h index 604c5b7ec4..c3b9032a48 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -29,6 +29,8 @@ enum efi_timer_delay { }; #define UINTN size_t +typedef long INTN; +typedef uint16_t *efi_string_t; #define EVT_TIMER 0x80000000 #define EVT_RUNTIME 0x40000000 @@ -427,10 +429,10 @@ struct efi_simple_text_output_protocol { void *reset; efi_status_t (EFIAPI *output_string)( struct efi_simple_text_output_protocol *this, - const unsigned short *str); + const efi_string_t str); efi_status_t (EFIAPI *test_string)( struct efi_simple_text_output_protocol *this, - const unsigned short *str); + const efi_string_t str); efi_status_t(EFIAPI *query_mode)( struct efi_simple_text_output_protocol *this, unsigned long mode_number, unsigned long *columns, diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c index 9048a8d32c..afc725a2c7 100644 --- a/lib/efi_loader/efi_console.c +++ b/lib/efi_loader/efi_console.c @@ -140,34 +140,46 @@ static efi_status_t EFIAPI efi_cout_reset( return EFI_EXIT(EFI_UNSUPPORTED); } -static void print_unicode_in_utf8(u16 c) -{ - char utf8[MAX_UTF8_PER_UTF16] = { 0 }; - utf16_to_utf8((u8 *)utf8, &c, 1); - puts(utf8); -} - static efi_status_t EFIAPI efi_cout_output_string( struct efi_simple_text_output_protocol *this, - const unsigned short *string) + const efi_string_t string) { - struct cout_mode *mode; - u16 ch; + struct simple_text_output_mode *con = &efi_con_mode; + struct cout_mode *mode = &efi_cout_modes[con->mode]; - mode = &efi_cout_modes[efi_con_mode.mode]; EFI_ENTRY("%p, %p", this, string); - for (;(ch = *string); string++) { - print_unicode_in_utf8(ch); - efi_con_mode.cursor_column++; - if (ch == '\n') { - efi_con_mode.cursor_column = 1; - efi_con_mode.cursor_row++; - } else if (efi_con_mode.cursor_column > mode->columns) { - efi_con_mode.cursor_column = 1; - efi_con_mode.cursor_row++; + + unsigned n16 = utf16_strlen(string); + char buf[MAX_UTF8_PER_UTF16 * n16 + 1]; + char *p; + + *utf16_to_utf8((u8 *)buf, string, n16) = '\0'; + + fputs(stdout, buf); + + for (p = buf; *p; p++) { + switch (*p) { + case '\r': /* carriage-return */ + con->cursor_column = 0; + break; + case '\n': /* newline */ + con->cursor_column = 0; + con->cursor_row++; + break; + case '\t': /* tab, assume 8 char align */ + break; + case '\b': /* backspace */ + con->cursor_column = max(0, con->cursor_column - 1); + break; + default: + con->cursor_column++; + break; + } + if (con->cursor_column >= mode->columns) { + con->cursor_column = 0; + con->cursor_row++; } - if (efi_con_mode.cursor_row > mode->rows) - efi_con_mode.cursor_row = mode->rows; + con->cursor_row = min(con->cursor_row, (s32)mode->rows - 1); } return EFI_EXIT(EFI_SUCCESS); @@ -175,7 +187,7 @@ static efi_status_t EFIAPI efi_cout_output_string( static efi_status_t EFIAPI efi_cout_test_string( struct efi_simple_text_output_protocol *this, - const unsigned short *string) + const efi_string_t string) { EFI_ENTRY("%p, %p", this, string); return EFI_EXIT(EFI_SUCCESS);