From patchwork Wed Nov 20 02:43:00 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeremy Kerr X-Patchwork-Id: 1197776 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [203.11.71.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 47Hng20VTlz9sPV for ; Wed, 20 Nov 2019 14:07:26 +1100 (AEDT) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=ozlabs.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; secure) header.d=ozlabs.org header.i=@ozlabs.org header.b="KBt0xXgi"; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 47Hng15KRczDqsG for ; Wed, 20 Nov 2019 14:07:25 +1100 (AEDT) X-Original-To: petitboot@lists.ozlabs.org Delivered-To: petitboot@lists.ozlabs.org Received: from ozlabs.org (bilbo.ozlabs.org [IPv6:2401:3900:2:1::2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 47Hn9V06f7zDqHl for ; Wed, 20 Nov 2019 13:45:18 +1100 (AEDT) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=ozlabs.org Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; secure) header.d=ozlabs.org header.i=@ozlabs.org header.b="KBt0xXgi"; dkim-atps=neutral Received: by ozlabs.org (Postfix, from userid 1023) id 47Hn9T1hhtz9sPc; Wed, 20 Nov 2019 13:45:16 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ozlabs.org; s=201707; t=1574217917; bh=94PkWqYGMokyIgwrEWuqSl+bFj7lGb0aBnNltsnTyng=; h=From:To:Subject:Date:In-Reply-To:References:From; b=KBt0xXgiLQO4cTeJbLZ9wRr59B+rovqaBVDgiBVFdukVdi5yj0omzb3UNc2UpR2Iv ahM7VLOd6bm149+ZC2YT6FGPvlCGUSgg9A05wnU9BDijqXeab+Y0ervfimyNPx8g/+ F3Rl9bfBEcWkCHNlUiy05Owxnq+5UpZs+ClB73c/H6GeGtVYKEA5RvC6G/u0RcSryl e+ytBDyVfpud/KfORn4TFz15mm3Q+19XHfaDTTWHpyce3q3x1VWixPF+95vH5sQ4++ 1E6W++0CNIeUWUoeBmBc5bO+5vzHrFFoBrq//tbOquoWG+BWMllht3I5KaVRK0R9gz 6YpoG/tfw7UOA== From: Jeremy Kerr To: petitboot@lists.ozlabs.org Subject: [PATCH 08/14] discover/grub2: Allow (device)/path references in general script usage Date: Wed, 20 Nov 2019 10:43:00 +0800 Message-Id: <20191120024306.16526-9-jk@ozlabs.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20191120024306.16526-1-jk@ozlabs.org> References: <20191120024306.16526-1-jk@ozlabs.org> MIME-Version: 1.0 X-BeenThere: petitboot@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Petitboot bootloader development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: petitboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Petitboot" Currently, we have support for grub2 (device)/path syntax for boot resources. This change allows this syntax for general paths in grub2 scripts (for example, -f tests). This involves exposing grub2_lookup_device, to allow the script execution code to resolve pathnames. Signed-off-by: Jeremy Kerr --- discover/grub2/builtins.c | 50 ++++++++++++++++--- discover/grub2/grub2.c | 4 +- discover/grub2/grub2.h | 2 + test/parser/Makefile.am | 1 + test/parser/test-grub2-devpath-scripting.c | 56 ++++++++++++++++++++++ 5 files changed, 104 insertions(+), 9 deletions(-) create mode 100644 test/parser/test-grub2-devpath-scripting.c diff --git a/discover/grub2/builtins.c b/discover/grub2/builtins.c index 765c4d7..c726216 100644 --- a/discover/grub2/builtins.c +++ b/discover/grub2/builtins.c @@ -197,6 +197,32 @@ static int builtin_search(struct grub2_script *script, return 0; } +static int parse_to_device_path(struct grub2_script *script, + const char *desc, struct discover_device **devp, + char **pathp) +{ + struct discover_device *dev; + struct grub2_file *file; + + file = grub2_parse_file(script, desc); + if (!file) + return -1; + + dev = script->ctx->device; + if (file->dev) + dev = grub2_lookup_device(script->ctx->handler, file->dev); + + if (!dev) + return -1; + + *devp = dev; + *pathp = talloc_strdup(script, file->path); + + talloc_free(file); + + return 0; +} + /* Note that GRUB does not follow symlinks in evaluating all file * tests but -s, unlike below. However, it seems like a bad idea to * emulate GRUB's behavior (e.g., it would take extra work), so we @@ -204,12 +230,17 @@ static int builtin_search(struct grub2_script *script, static bool builtin_test_op_file(struct grub2_script *script, char op, const char *file) { + struct discover_device *dev; + struct stat statbuf; bool result; + char *path; int rc; - struct stat statbuf; - rc = parser_stat_path(script->ctx, script->ctx->device, - file, &statbuf); + rc = parse_to_device_path(script, file, &dev, &path); + if (rc) + return false; + + rc = parser_stat_path(script->ctx, dev, path, &statbuf); if (rc) return false; @@ -237,16 +268,21 @@ static bool builtin_test_op_file(struct grub2_script *script, char op, static bool builtin_test_op_dir(struct grub2_script *script, char op, const char *dir) { - int rc; + struct discover_device *dev; struct stat statbuf; + char *path; + int rc; if (op != 'd') return false; - rc = parser_stat_path(script->ctx, script->ctx->device, dir, &statbuf); - if (rc) { + rc = parse_to_device_path(script, dir, &dev, &path); + if (rc) + return false; + + rc = parser_stat_path(script->ctx, dev, path, &statbuf); + if (rc) return false; - } return S_ISDIR(statbuf.st_mode); } diff --git a/discover/grub2/grub2.c b/discover/grub2/grub2.c index a08a320..a8d115f 100644 --- a/discover/grub2/grub2.c +++ b/discover/grub2/grub2.c @@ -33,8 +33,8 @@ static const char *const grub2_conf_files[] = { NULL }; -static struct discover_device *grub2_lookup_device( - struct device_handler *handler, const char *desc) +struct discover_device *grub2_lookup_device(struct device_handler *handler, + const char *desc) { struct discover_device *dev; diff --git a/discover/grub2/grub2.h b/discover/grub2/grub2.h index ef32d4b..eabd6d6 100644 --- a/discover/grub2/grub2.h +++ b/discover/grub2/grub2.h @@ -200,6 +200,8 @@ bool resolve_grub2_resource(struct device_handler *handler, /* grub-style device+path parsing */ struct grub2_file *grub2_parse_file(struct grub2_script *script, const char *str); +struct discover_device *grub2_lookup_device(struct device_handler *handler, + const char *desc); /* external parser api */ struct grub2_parser *grub2_parser_create(struct discover_context *ctx); diff --git a/test/parser/Makefile.am b/test/parser/Makefile.am index 0378317..c8e059b 100644 --- a/test/parser/Makefile.am +++ b/test/parser/Makefile.am @@ -33,6 +33,7 @@ parser_TESTS = \ test/parser/test-grub2-search-uuid \ test/parser/test-grub2-search-label \ test/parser/test-grub2-devpath \ + test/parser/test-grub2-devpath-scripting \ test/parser/test-grub2-load-env \ test/parser/test-grub2-save-env \ test/parser/test-grub2-save-env-dash-f \ diff --git a/test/parser/test-grub2-devpath-scripting.c b/test/parser/test-grub2-devpath-scripting.c new file mode 100644 index 0000000..9046ab6 --- /dev/null +++ b/test/parser/test-grub2-devpath-scripting.c @@ -0,0 +1,56 @@ +/* check grub2 device+path string parsing, as used in scripts */ + +#include "parser-test.h" + +#if 0 /* PARSER_EMBEDDED_CONFIG */ + +v= + +# local device, file present +if [ -f "/1-present" ]; then v=${v}a; fi + +# local device, file absent +if [ -f "/1-absent" ]; then v=${v}b; fi; + +# local device by UUID, file present +if [ -f "(00000000-0000-0000-0000-000000000001)/1-present" ]; then v=${v}c; fi; + +# remote device by UUID, file present +if [ -f "(00000000-0000-0000-0000-000000000002)/2-present" ]; then v=${v}d; fi; + +# non-existent device +if [ -f "(00000000-0000-0000-0000-000000000003)/present" ]; then v=${v}e; fi; + +menuentry $v { + linux /vmlinux +} + +#endif + +void run_test(struct parser_test *test) +{ + struct discover_device *dev1, *dev2; + struct discover_boot_option *opt; + struct discover_context *ctx; + + ctx = test->ctx; + + /* set local uuid */ + dev1 = test->ctx->device; + dev1->uuid = "00000000-0000-0000-0000-000000000001"; + + dev2 = test_create_device(test, "extdev"); + dev2->uuid = "00000000-0000-0000-0000-000000000002"; + device_handler_add_device(ctx->handler, dev2); + + test_add_file_data(test, dev1, "/1-present", "x", 1); + test_add_file_data(test, dev2, "/2-present", "x", 1); + + test_read_conf_embedded(test, "/grub/grub.cfg"); + + test_run_parser(test, "grub2"); + + check_boot_option_count(ctx, 1); + opt = get_boot_option(ctx, 0); + check_name(opt, "acd"); +}