From patchwork Thu Jun 13 10:13:08 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mattijs Korpershoek X-Patchwork-Id: 1947324 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.a=rsa-sha256 header.s=20230601 header.b=Q5BQKxWP; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=patchwork.ozlabs.org) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4W0JCp6dwjz20Xd for ; Thu, 13 Jun 2024 20:13:58 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id AFA74888EA; Thu, 13 Jun 2024 12:13:36 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b="Q5BQKxWP"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 15E99883D3; Thu, 13 Jun 2024 12:13:35 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-wm1-x329.google.com (mail-wm1-x329.google.com [IPv6:2a00:1450:4864:20::329]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 02EAF888DD for ; Thu, 13 Jun 2024 12:13:33 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=mkorpershoek@baylibre.com Received: by mail-wm1-x329.google.com with SMTP id 5b1f17b1804b1-4218180a122so6353455e9.1 for ; Thu, 13 Jun 2024 03:13:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1718273612; x=1718878412; darn=lists.denx.de; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=8pcrNNtyvmSnnPWBu5V0jwxWwuKPIZMjnUEnkwn69b4=; b=Q5BQKxWPDx2bO3YtQH2syH/RZytCdudWrXFKirCDoM14Cuz/Hkg1+MdihJjDcw4fc3 lAPvFx8JlJl7G3lskmj+SIvGXETA7gVCjzvg7+xwzFrsOYTyo7mBrcZYARKWmplhJGOK dQ2VRzlhQI6pjQM4FJZTd1uPS97NNdsSjVYwgcIka1aK7oHYyCvgpYopl13NF77bXQKl meUythOZCExlJgX5/jE0+v0BOkCiyiNoyuiua0exRkPB7sSBe3Pch4c93MgMfD1bvihZ 6sflUgVwqMX8ha7m1TdKElQuCbQS6gBfGMhYXYJsycy1FyZLIumXptrZ8pAngsLmXHfv SwVA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1718273612; x=1718878412; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=8pcrNNtyvmSnnPWBu5V0jwxWwuKPIZMjnUEnkwn69b4=; b=cAl/XJGWP+SET6GU0LQkVI+vg7lSNiodKZzi2+TnhFKE2GFn04o4wmfoqFOgn/rP6G cRnkjFrLpG4DawOZjxhYCBgn6H1V72USpNuCtP0UphYbP3zYX01RolYlSpd7B8622fy5 ZTcMj3w5Yp1sg9ochKHcbaqDscfl2pijog1+JdCR0508yslUhmU5FTukTHGbKa4kxYMV tLeqU+sI9D403RHTVKxhg2hAKpFlHL/fw+Y4wklLUSQ1oFo4oNrhbBDwYqu4uxKjWsHj XMuCefzoc3wO+6zRKxjpUrt1sgvnR0iBFRD/gN7M1AW0gmuDxNYhPJNRW7Wx58gmuqYf xGWQ== X-Forwarded-Encrypted: i=1; AJvYcCXLu3Yk/LgCnKIJ2iP7oPKUEs/WP4ImqYCtdKCBmGCVM5csHONj4yTkHkvf6BaN+jvlJh1fpSFOCUdycAm9qfCJcK8ldg== X-Gm-Message-State: AOJu0YwQxav/dzr2SxSorhIrVPIzBDs2h1uAGKSAdPhTs1CNHT+momWE sWCbnWqfNawkEnJypLooPOTktyD7aSJ8NVqLdAtq5ZdfZLnm73a1qdc0KndxLGw= X-Google-Smtp-Source: AGHT+IFAZLvhTVMCgSQQpS1LpfH6y4q8AmNtmciMjTP0Th3gpbbCASSWnkMPZoschVaF0wnBodDQNA== X-Received: by 2002:adf:e781:0:b0:351:c960:b5af with SMTP id ffacd0b85a97d-35fdf787f8amr3849434f8f.17.1718273612486; Thu, 13 Jun 2024 03:13:32 -0700 (PDT) Received: from groot.home ([2a01:cb19:95ba:5000:d6dd:417f:52ac:335b]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-360750f2295sm1251573f8f.82.2024.06.13.03.13.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 13 Jun 2024 03:13:32 -0700 (PDT) From: Mattijs Korpershoek Date: Thu, 13 Jun 2024 12:13:08 +0200 Subject: [PATCH v2 1/5] boot: android: Provide vendor_bootimg_addr in boot_get_fdt() MIME-Version: 1.0 Message-Id: <20240613-bootmeth-android-v2-1-397f6e66eb29@baylibre.com> References: <20240613-bootmeth-android-v2-0-397f6e66eb29@baylibre.com> In-Reply-To: <20240613-bootmeth-android-v2-0-397f6e66eb29@baylibre.com> To: Simon Glass Cc: Julien Masson , Guillaume La Roque , Dmitrii Merkurev , Roman Stratiienko , Igor Opaniuk , u-boot@lists.denx.de, Mattijs Korpershoek X-Mailer: b4 0.14-dev-d4707 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 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" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean When calling android_image_get_dtb_by_index() using boot image v3+, we should also pass the vendor_boot ramdisk address. Use get_avendor_bootimg_addr() to do so. Notes: on boot image v2, this is harmless since get_avendor_bootimg_addr() returns -1. for legacy implementations that don't have CMD_ABOOTIMG, add a weak implementation to avoid linking errors. Signed-off-by: Mattijs Korpershoek Reviewed-by: Simon Glass Reviewed-by: Julien Masson Reviewed-by: Igor Opaniuk Reviewed-by: Guillaume La Roque --- boot/image-android.c | 5 +++++ boot/image-fdt.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/boot/image-android.c b/boot/image-android.c index ee626972c114..09c7a44e058a 100644 --- a/boot/image-android.c +++ b/boot/image-android.c @@ -56,6 +56,11 @@ static ulong add_trailer(ulong bootconfig_start_addr, ulong bootconfig_size) return BOOTCONFIG_TRAILER_SIZE; } +__weak ulong get_avendor_bootimg_addr(void) +{ + return -1; +} + static void android_boot_image_v3_v4_parse_hdr(const struct andr_boot_img_hdr_v3 *hdr, struct andr_image_data *data) { diff --git a/boot/image-fdt.c b/boot/image-fdt.c index 56dd7687f51c..8332792b8e80 100644 --- a/boot/image-fdt.c +++ b/boot/image-fdt.c @@ -502,7 +502,7 @@ int boot_get_fdt(void *buf, const char *select, uint arch, * Firstly check if this android boot image has dtb field. */ dtb_idx = (u32)env_get_ulong("adtb_idx", 10, 0); - if (android_image_get_dtb_by_index((ulong)hdr, 0, + if (android_image_get_dtb_by_index((ulong)hdr, get_avendor_bootimg_addr(), dtb_idx, &fdt_addr, &fdt_size)) { fdt_blob = (char *)map_sysmem(fdt_addr, 0); if (fdt_check_header(fdt_blob)) From patchwork Thu Jun 13 10:13:09 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mattijs Korpershoek X-Patchwork-Id: 1947325 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.a=rsa-sha256 header.s=20230601 header.b=LNAlMpCG; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=patchwork.ozlabs.org) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4W0JCv2C9mz20Xd for ; Thu, 13 Jun 2024 20:14:03 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 3230D888EF; Thu, 13 Jun 2024 12:13:38 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b="LNAlMpCG"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id B3028888E2; Thu, 13 Jun 2024 12:13:36 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-wr1-x432.google.com (mail-wr1-x432.google.com [IPv6:2a00:1450:4864:20::432]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id E89D7888E2 for ; Thu, 13 Jun 2024 12:13:33 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=mkorpershoek@baylibre.com Received: by mail-wr1-x432.google.com with SMTP id ffacd0b85a97d-35f188e09a8so690581f8f.2 for ; Thu, 13 Jun 2024 03:13:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1718273613; x=1718878413; darn=lists.denx.de; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=pRQvsZ0Ors9/qwlPi3O7OFLnn3bRqWMAveHYmhda0g0=; b=LNAlMpCGN23+bME0Jn0LmlboytQVF8oszGEThJ7mGMSWemypAVagwSh8298wJ4fDtN AZ7wzbMQplAo6cmlmi4OMW8USyuYyHzHYD5xsPffzTXsA04CBVpevnxteSIkUxlwATki FzHN0V7Q1YHAsZNmGhTSrnD7c9vsoEzhu6kZDqUzbOtB8hk9Ifefgv02XbzgtHF+YYc5 86u+oFrbJaOL+KtKGjNpYsDeGB7KyBd//Xc7eo33bx3h6rG5QEr2hlT0+hIqW+pQK2Lb bnwJ390TErdwR3Ggn9gLBnLo/VgvmFFXFv6PDLK82DeCZC8hyhKrmUUvRkm62KTbqF2W wldQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1718273613; x=1718878413; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=pRQvsZ0Ors9/qwlPi3O7OFLnn3bRqWMAveHYmhda0g0=; b=E2xQwhbn5aPWlqyttsZLSL+Rw4k3RpULXjnkDzMRjNZAJI+3o+TZUrYgU0tJXq/fpQ svBnRtSzA9AanltbrtlHpY7jCKz/VEdTgL3RMiRHe3PUQ/r+Iu2LAuIEzmtCkFVhpST6 /ZHxpYY5kGupEt7ogWK0jS03vc9bsbZmpzyqpoA3xXVtw81kJ7b3BNNKXBXXp+3qesTq /gU682SfMUm/VTcCfftQauk9m2vXxJ+41SUHpiLsyDAAsIJbupQ4cR+8wPx+PH/TUQGm 2DnQL/Z3YGHrvZNCCOS5pkS+15OM5KZWXKD7OcqCday8sdxbfpJ0oP+ksz+v/ndlFjXd sMkA== X-Forwarded-Encrypted: i=1; AJvYcCXwVPXKKjmySXWQNCdRAM0vwNCRRnCvoGC2sBlUg+8cjtybg8z1xqUQkbQrM03OseqEdCey6Bbd9BGPy3NF5PvZuEdIcA== X-Gm-Message-State: AOJu0Yxo2JFZLHb5c9aRDHNuNy1fO2M7PzT6i2TFG41p8gzmU0sJn7fE VVzccle/d/4RaxQPkrLMHm6f8xjGUDZYE4pgpR3liNmJHgmHCN2tRkafj+WF0SE= X-Google-Smtp-Source: AGHT+IFtHw3Y4hAsDMeT39a9+eC3hzW16vRGW5gpuy00/gkByQAyhRSLk1JlwZSDZNgQtZYqzP/eDQ== X-Received: by 2002:a05:6000:18e:b0:35f:d70:6193 with SMTP id ffacd0b85a97d-35fdf7adcc7mr3120507f8f.41.1718273613323; Thu, 13 Jun 2024 03:13:33 -0700 (PDT) Received: from groot.home ([2a01:cb19:95ba:5000:d6dd:417f:52ac:335b]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-360750f2295sm1251573f8f.82.2024.06.13.03.13.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 13 Jun 2024 03:13:32 -0700 (PDT) From: Mattijs Korpershoek Date: Thu, 13 Jun 2024 12:13:09 +0200 Subject: [PATCH v2 2/5] bootstd: Add bootflow_iter_check_mmc() helper MIME-Version: 1.0 Message-Id: <20240613-bootmeth-android-v2-2-397f6e66eb29@baylibre.com> References: <20240613-bootmeth-android-v2-0-397f6e66eb29@baylibre.com> In-Reply-To: <20240613-bootmeth-android-v2-0-397f6e66eb29@baylibre.com> To: Simon Glass Cc: Julien Masson , Guillaume La Roque , Dmitrii Merkurev , Roman Stratiienko , Igor Opaniuk , u-boot@lists.denx.de, Mattijs Korpershoek X-Mailer: b4 0.14-dev-d4707 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 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" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean Some bootflows might be able to only boot from MMC devices. Add a helper function these bootflows can use. Reviewed-by: Igor Opaniuk Signed-off-by: Mattijs Korpershoek Reviewed-by: Julien Masson Reviewed-by: Guillaume La Roque --- boot/bootflow.c | 12 ++++++++++++ include/bootflow.h | 9 +++++++++ 2 files changed, 21 insertions(+) diff --git a/boot/bootflow.c b/boot/bootflow.c index 9aa3179c3881..59d77d2385f4 100644 --- a/boot/bootflow.c +++ b/boot/bootflow.c @@ -575,6 +575,18 @@ int bootflow_iter_check_blk(const struct bootflow_iter *iter) return -ENOTSUPP; } +int bootflow_iter_check_mmc(const struct bootflow_iter *iter) +{ + const struct udevice *media = dev_get_parent(iter->dev); + enum uclass_id id = device_get_uclass_id(media); + + log_debug("uclass %d: %s\n", id, uclass_get_name(id)); + if (id == UCLASS_MMC) + return 0; + + return -ENOTSUPP; +} + int bootflow_iter_check_sf(const struct bootflow_iter *iter) { const struct udevice *media = dev_get_parent(iter->dev); diff --git a/include/bootflow.h b/include/bootflow.h index 080ee8501225..6058ddd89b16 100644 --- a/include/bootflow.h +++ b/include/bootflow.h @@ -407,6 +407,15 @@ void bootflow_remove(struct bootflow *bflow); */ int bootflow_iter_check_blk(const struct bootflow_iter *iter); +/** + * bootflow_iter_check_mmc() - Check that a bootflow uses a MMC device + * + * This checks the bootdev in the bootflow to make sure it uses a mmc device + * + * Return: 0 if OK, -ENOTSUPP if some other device is used (e.g. ethernet) + */ +int bootflow_iter_check_mmc(const struct bootflow_iter *iter); + /** * bootflow_iter_check_sf() - Check that a bootflow uses SPI FLASH * From patchwork Thu Jun 13 10:13:10 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mattijs Korpershoek X-Patchwork-Id: 1947326 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.a=rsa-sha256 header.s=20230601 header.b=dC18ICQx; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=patchwork.ozlabs.org) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4W0JD64zdWz20Xd for ; Thu, 13 Jun 2024 20:14:14 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id A8004888F5; Thu, 13 Jun 2024 12:13:38 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b="dC18ICQx"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 16A5B888E9; Thu, 13 Jun 2024 12:13:37 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-lf1-x12a.google.com (mail-lf1-x12a.google.com [IPv6:2a00:1450:4864:20::12a]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 1A514888D9 for ; Thu, 13 Jun 2024 12:13:35 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=mkorpershoek@baylibre.com Received: by mail-lf1-x12a.google.com with SMTP id 2adb3069b0e04-52962423ed8so1051608e87.2 for ; Thu, 13 Jun 2024 03:13:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1718273614; x=1718878414; darn=lists.denx.de; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=7zICqjiRabucE9uUo5x9KVLea6SvjoIO7CoPygjJi8o=; b=dC18ICQxGEI+QV3u3G1abW5qKtQNjsohzRH0kIllXG7Hw+2j+dZ7EvQN0+L8v7LIa5 SAdlimfDFp7j8dy/jdpfd1NEfb61S1fxVT8O4VvoJ5dBcS+cD1srVD4nEl2Nt7oobzT7 oAhYkc36buNPBg4b3aDvBFpTQ0NxZISvhkc4kJ8X4nlRH3hYxaEXqddr7O1x+iZisMW6 WqecgjXGz3rCrgS/jurLQ1rO9q/tRMGrBJVna7P2TBbeiImA8L3skqO1swb1YyVziN77 eUVtcy8aOV6aVySr7qZEO23LuHHXc+FPvO3bbTMwqtw0CB3uSTLUoN19mH8Xzczb/Cox 5mAw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1718273614; x=1718878414; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=7zICqjiRabucE9uUo5x9KVLea6SvjoIO7CoPygjJi8o=; b=MbDG3tuDQeeBLA4zOrU0jCo/LWWcpmMfKyBtTDxC1bLEcXiuqovIeNVPINEkt74DXv IAZiAUPeFu2CsxqyPBKFe9yWuY/JPLfjYmCsvlYMkUmLpKSleLxQS0cyPm2KJ2RYFr5f ZFQZ1ya4GFm+NwsKUuKsT6bHRRzoXDiInjZUvE3EF3iOMYc+6nBaYuM4HayUgDibphhq FYc1pzAz/pBEiFx5i8IAjaMiJqf0TFjmtEEfbgBkk2nsdq2OuhU/sHohgtFejsuwE6DH 85KdDJ/+zrGjyJUS85LNwl1C5eqQd4NG7EpLpw6qUZpg8+D+D5XlNvt0KFTFiBsJYqK4 wUAA== X-Forwarded-Encrypted: i=1; AJvYcCV7gbjnEPELdsOTpgh/Uv3T0xek4kTfhml6YqtHmG7cbkTDPteRBCO3g0ctKBtzwpkQT/chrjzzVHBtr+EReKsRZ8ot8g== X-Gm-Message-State: AOJu0Yykchfvi3wS1kw8KMWuKdG4Swekz/zqASOkzSsb+/p94+n9YjpM JJhmFR4o1Srxbp/qybl2973/9xcJH08SG1xRfvxU7fqA+6MKBsIndPFZtd0mes8= X-Google-Smtp-Source: AGHT+IGXZhL+fqYoqk7gl7oBeCLVmr8wPgInO4dPKHFqng8Z1yjHCXq7wIY9kYk9rXr4lJnz5HvtLQ== X-Received: by 2002:ac2:44b3:0:b0:52c:896f:bc3c with SMTP id 2adb3069b0e04-52c9a405922mr2578440e87.67.1718273614138; Thu, 13 Jun 2024 03:13:34 -0700 (PDT) Received: from groot.home ([2a01:cb19:95ba:5000:d6dd:417f:52ac:335b]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-360750f2295sm1251573f8f.82.2024.06.13.03.13.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 13 Jun 2024 03:13:33 -0700 (PDT) From: Mattijs Korpershoek Date: Thu, 13 Jun 2024 12:13:10 +0200 Subject: [PATCH v2 3/5] android: boot: Add set_abootimg_addr() and set_avendor_bootimg_addr() MIME-Version: 1.0 Message-Id: <20240613-bootmeth-android-v2-3-397f6e66eb29@baylibre.com> References: <20240613-bootmeth-android-v2-0-397f6e66eb29@baylibre.com> In-Reply-To: <20240613-bootmeth-android-v2-0-397f6e66eb29@baylibre.com> To: Simon Glass Cc: Julien Masson , Guillaume La Roque , Dmitrii Merkurev , Roman Stratiienko , Igor Opaniuk , u-boot@lists.denx.de, Mattijs Korpershoek X-Mailer: b4 0.14-dev-d4707 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 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" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean The only way to configure the load addresses for both bootimg and vendor_bootimg is by using the "abootimg" command. If we want to use the C API, there is no equivalent. Add set_abootimg_addr() and set_avendor_bootimg_addr() so that we can specify the load address from C. This can be useful for implementing an Android bootmethod. Reviewed-by: Igor Opaniuk Signed-off-by: Mattijs Korpershoek Reviewed-by: Julien Masson Reviewed-by: Simon Glass Reviewed-by: Guillaume La Roque --- cmd/abootimg.c | 10 ++++++++++ include/image.h | 14 ++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/cmd/abootimg.c b/cmd/abootimg.c index 327712a536c0..ae7a1a7c83b0 100644 --- a/cmd/abootimg.c +++ b/cmd/abootimg.c @@ -22,6 +22,11 @@ ulong get_abootimg_addr(void) return (_abootimg_addr == -1 ? image_load_addr : _abootimg_addr); } +void set_abootimg_addr(ulong addr) +{ + _abootimg_addr = addr; +} + ulong get_ainit_bootimg_addr(void) { return _ainit_bootimg_addr; @@ -32,6 +37,11 @@ ulong get_avendor_bootimg_addr(void) return _avendor_bootimg_addr; } +void set_avendor_bootimg_addr(ulong addr) +{ + _avendor_bootimg_addr = addr; +} + static int abootimg_get_ver(int argc, char *const argv[]) { const struct andr_boot_img_hdr_v0 *hdr; diff --git a/include/image.h b/include/image.h index c5b288f62b44..df2decbf5c2a 100644 --- a/include/image.h +++ b/include/image.h @@ -1970,6 +1970,13 @@ bool is_android_vendor_boot_image_header(const void *vendor_boot_img); */ ulong get_abootimg_addr(void); +/** + * set_abootimg_addr() - Set Android boot image address + * + * Return: no returned results + */ +void set_abootimg_addr(ulong addr); + /** * get_ainit_bootimg_addr() - Get Android init boot image address * @@ -1984,6 +1991,13 @@ ulong get_ainit_bootimg_addr(void); */ ulong get_avendor_bootimg_addr(void); +/** + * set_abootimg_addr() - Set Android vendor boot image address + * + * Return: no returned results + */ +void set_avendor_bootimg_addr(ulong addr); + /** * board_fit_config_name_match() - Check for a matching board name * From patchwork Thu Jun 13 10:13:11 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Mattijs Korpershoek X-Patchwork-Id: 1947327 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.a=rsa-sha256 header.s=20230601 header.b=BB2Wqu2y; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=patchwork.ozlabs.org) Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4W0JDL0nHDz20Xd for ; Thu, 13 Jun 2024 20:14:26 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 25EB3888FD; Thu, 13 Jun 2024 12:13:40 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b="BB2Wqu2y"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id A8962888FC; Thu, 13 Jun 2024 12:13:39 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-wr1-x430.google.com (mail-wr1-x430.google.com [IPv6:2a00:1450:4864:20::430]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id B50E9888E4 for ; Thu, 13 Jun 2024 12:13:36 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=mkorpershoek@baylibre.com Received: by mail-wr1-x430.google.com with SMTP id ffacd0b85a97d-35f14af40c2so741720f8f.0 for ; Thu, 13 Jun 2024 03:13:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1718273616; x=1718878416; darn=lists.denx.de; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=8zL8s3BSh7TJNgTmckDn4Ox9DAewjuGgXe7zc6IztNE=; b=BB2Wqu2yTUUZH7rC11Oc+qENoGCQW6xUwjw87NBb6iuj4EhpzpAQ6TBfD7/m6vitth xQxxqX0xdEWkddXxtYPwl/N32dh1ae645BCLd4209AHC+/f5MgCD1WqF6DqFImEE9Yfs Yh09AWFn4q0qrpQcR9l96Dn8fObt2ogkqO1FApcxLtGzW5LAHOBmXS/VGugVtANIxOTT sU08bzM2P1RHVIR097AwOg1d4PCHMln6iYlIKG8tl77FpJZg7eYYNHGjQCfeLKuLKC8U vvr1bhpdZZZGSbyE9p9e25uUkR1DpHpB7a3/T8e2akBJLxW3kpSFZOjmgwNQ+FGMPbya J7KA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1718273616; x=1718878416; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=8zL8s3BSh7TJNgTmckDn4Ox9DAewjuGgXe7zc6IztNE=; b=qJOeKzDM+owJA6XvTcPvDKiwVky/Fzy94p6BVuwi6SFP7VKXJCJACYYDQc8VMYuTCj oa4BBOBD4wW9QQwVv4BWe58YaYASH6bCKAKD1fvRvcSuOf6fvA1c60ufp9UI3oJgfDh5 Cjl98Bk6F7aGRSZMUQo0N0z/It0a7iNdwRziONYNQKJgK+Tr1Eeyzjk7FqfJXpTTDv87 qQ0Z/6BAfY3ZPVYrsR61vz6AeeQeKGf25bmSM7KOwajByxwpy4rRIehIgPllf3y2R56g Y9p5+ZQUrBeT1cIdm9LbN/PP9yf1EJvcBuoWrJAEz30r4rQ+r1JcOR8/Dti2I2hvfGus x1CA== X-Forwarded-Encrypted: i=1; AJvYcCUd5rbWAeYET8mknqQ/x2oUPYHAqTvfAnoQUjMW1jfKPemsZcoZo4qWHeGihhEwlFGOGgEH42hyA/AwQD0iU7WF2gGRHQ== X-Gm-Message-State: AOJu0YwT5nEO7tw18ZzM8EZWPNGnKvsURYwHLvD/g0tIaeX7k7yI/Irf /qQmOppIC4TAys5Aqo7CTSM8SMie8oio52goa17+qTmEcUfe7yJnoDEZU4qpqpAedUN5rrz0GyL nRQA= X-Google-Smtp-Source: AGHT+IGEwkeFgG1pUtaIurJweHAVn7LB7V0c5BpYd27CgNlG3kQ0hbDv0bDaeKI3TY8U6Sv17FpO8w== X-Received: by 2002:a5d:6c69:0:b0:360:7139:ba1c with SMTP id ffacd0b85a97d-3607139ba4amr1708029f8f.64.1718273616057; Thu, 13 Jun 2024 03:13:36 -0700 (PDT) Received: from groot.home ([2a01:cb19:95ba:5000:d6dd:417f:52ac:335b]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-360750f2295sm1251573f8f.82.2024.06.13.03.13.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 13 Jun 2024 03:13:35 -0700 (PDT) From: Mattijs Korpershoek Date: Thu, 13 Jun 2024 12:13:11 +0200 Subject: [PATCH v2 4/5] bootstd: Add a bootmeth for Android MIME-Version: 1.0 Message-Id: <20240613-bootmeth-android-v2-4-397f6e66eb29@baylibre.com> References: <20240613-bootmeth-android-v2-0-397f6e66eb29@baylibre.com> In-Reply-To: <20240613-bootmeth-android-v2-0-397f6e66eb29@baylibre.com> To: Simon Glass Cc: Julien Masson , Guillaume La Roque , Dmitrii Merkurev , Roman Stratiienko , Igor Opaniuk , u-boot@lists.denx.de, Mattijs Korpershoek X-Mailer: b4 0.14-dev-d4707 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 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" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean Android boot flow is a bit different than a regular Linux distro. Android relies on multiple partitions in order to boot. A typical boot flow would be: 1. Parse the Bootloader Control Block (BCB, misc partition) 2. If BCB requested bootonce-bootloader, start fastboot and wait. 3. If BCB requested recovery or normal android, run the following: 3.a. Get slot (A/B) from BCB 3.b. Run AVB (Android Verified Boot) on boot partitions 3.c. Load boot and vendor_boot partitions 3.d. Load device-tree, ramdisk and boot The AOSP documentation has more details at [1], [2], [3] This has been implemented via complex boot scripts such as [4]. However, these boot script are neither very maintainable nor generic. Moreover, DISTRO_DEFAULTS is being deprecated [5]. Add a generic Android bootflow implementation for bootstd. For this initial version, only boot image v4 is supported. [1] https://source.android.com/docs/core/architecture/bootloader [2] https://source.android.com/docs/core/architecture/partitions [3] https://source.android.com/docs/core/architecture/partitions/generic-boot [4] https://source.denx.de/u-boot/u-boot/-/blob/master/include/configs/meson64_android.h [5] https://lore.kernel.org/r/all/20230914165615.1058529-17-sjg@chromium.org/ Reviewed-by: Simon Glass Signed-off-by: Mattijs Korpershoek Reviewed-by: Julien Masson --- MAINTAINERS | 7 + boot/Kconfig | 16 ++ boot/Makefile | 2 + boot/bootmeth_android.c | 553 ++++++++++++++++++++++++++++++++++++++++++++++++ boot/bootmeth_android.h | 29 +++ doc/develop/bootstd.rst | 6 + 6 files changed, 613 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 66783d636e3d..6d2b87720565 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -939,6 +939,13 @@ F: include/bootstd.h F: net/eth_bootdevice.c F: test/boot/ +BOOTMETH_ANDROID +M: Mattijs Korpershoek +S: Maintained +T: git https://source.denx.de/u-boot/custodians/u-boot-dfu.git +F: boot/bootmeth_android.c +F: boot/bootmeth_android.h + BTRFS M: Marek BehĂșn R: Qu Wenruo diff --git a/boot/Kconfig b/boot/Kconfig index 6f3096c15a6f..88266c8d2ed3 100644 --- a/boot/Kconfig +++ b/boot/Kconfig @@ -494,6 +494,22 @@ config BOOTMETH_GLOBAL EFI bootmgr, since they take full control over which bootdevs are selected to boot. +config BOOTMETH_ANDROID + bool "Bootdev support for Android" + depends on X86 || ARM || SANDBOX + select ANDROID_AB + select ANDROID_BOOT_IMAGE + select CMD_BCB + select CMD_FASTBOOT + select PARTITION_TYPE_GUID + select PARTITION_UUIDS + help + Enables support for booting Android using bootstd. Android requires + multiple partitions (misc, boot, vbmeta, ...) in storage for booting. + + Note that only MMC bootdevs are supported at present. This is caused + by AVB being limited to MMC devices only. + config BOOTMETH_CROS bool "Bootdev support for Chromium OS" depends on X86 || ARM || SANDBOX diff --git a/boot/Makefile b/boot/Makefile index 84ccfeaecec4..75d1cd46fabf 100644 --- a/boot/Makefile +++ b/boot/Makefile @@ -66,3 +66,5 @@ obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_VBE_REQUEST) += vbe_request.o obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_VBE_SIMPLE) += vbe_simple.o obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_VBE_SIMPLE_FW) += vbe_simple_fw.o obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_VBE_SIMPLE_OS) += vbe_simple_os.o + +obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_ANDROID) += bootmeth_android.o diff --git a/boot/bootmeth_android.c b/boot/bootmeth_android.c new file mode 100644 index 000000000000..6e8d3e615db0 --- /dev/null +++ b/boot/bootmeth_android.c @@ -0,0 +1,553 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Bootmeth for Android + * + * Copyright (C) 2024 BayLibre, SAS + * Written by Mattijs Korpershoek + */ +#define LOG_CATEGORY UCLASS_BOOTSTD + +#include +#include +#if CONFIG_IS_ENABLED(AVB_VERIFY) +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "bootmeth_android.h" + +#define BCB_FIELD_COMMAND_SZ 32 +#define BCB_PART_NAME "misc" +#define BOOT_PART_NAME "boot" +#define VENDOR_BOOT_PART_NAME "vendor_boot" + +/** + * struct android_priv - Private data + * + * This is read from the disk and recorded for use when the full Android + * kernel must be loaded and booted + * + * @boot_mode: Requested boot mode (normal, recovery, bootloader) + * @slot: Nul-terminated partition slot suffix read from BCB ("a\0" or "b\0") + * @header_version: Android boot image header version + */ +struct android_priv { + enum android_boot_mode boot_mode; + char slot[2]; + u32 header_version; +}; + +static int android_check(struct udevice *dev, struct bootflow_iter *iter) +{ + /* This only works on mmc devices */ + if (bootflow_iter_check_mmc(iter)) + return log_msg_ret("mmc", -ENOTSUPP); + + /* + * This only works on whole devices, as multiple + * partitions are needed to boot Android + */ + if (iter->part != 0) + return log_msg_ret("mmc part", -ENOTSUPP); + + return 0; +} + +static int scan_boot_part(struct udevice *blk, struct android_priv *priv) +{ + struct blk_desc *desc = dev_get_uclass_plat(blk); + struct disk_partition partition; + char partname[PART_NAME_LEN]; + ulong num_blks, bufsz; + char *buf; + int ret; + + sprintf(partname, BOOT_PART_NAME "_%s", priv->slot); + ret = part_get_info_by_name(desc, partname, &partition); + if (ret < 0) + return log_msg_ret("part info", ret); + + num_blks = DIV_ROUND_UP(sizeof(struct andr_boot_img_hdr_v0), desc->blksz); + bufsz = num_blks * desc->blksz; + buf = malloc(bufsz); + if (!buf) + return log_msg_ret("buf", -ENOMEM); + + ret = blk_read(blk, partition.start, num_blks, buf); + if (ret != num_blks) { + free(buf); + return log_msg_ret("part read", -EIO); + } + + if (!is_android_boot_image_header(buf)) { + free(buf); + return log_msg_ret("header", -ENOENT); + } + + priv->header_version = ((struct andr_boot_img_hdr_v0 *)buf)->header_version; + free(buf); + + return 0; +} + +static int scan_vendor_boot_part(struct udevice *blk, struct android_priv *priv) +{ + struct blk_desc *desc = dev_get_uclass_plat(blk); + struct disk_partition partition; + char partname[PART_NAME_LEN]; + ulong num_blks, bufsz; + char *buf; + int ret; + + sprintf(partname, VENDOR_BOOT_PART_NAME "_%s", priv->slot); + ret = part_get_info_by_name(desc, partname, &partition); + if (ret < 0) + return log_msg_ret("part info", ret); + + num_blks = DIV_ROUND_UP(sizeof(struct andr_vnd_boot_img_hdr), desc->blksz); + bufsz = num_blks * desc->blksz; + buf = malloc(bufsz); + if (!buf) + return log_msg_ret("buf", -ENOMEM); + + ret = blk_read(blk, partition.start, num_blks, buf); + if (ret != num_blks) { + free(buf); + return log_msg_ret("part read", -EIO); + } + + if (!is_android_vendor_boot_image_header(buf)) { + free(buf); + return log_msg_ret("header", -ENOENT); + } + free(buf); + + return 0; +} + +static int android_read_slot_from_bcb(struct bootflow *bflow, bool decrement) +{ + struct blk_desc *desc = dev_get_uclass_plat(bflow->blk); + struct android_priv *priv = bflow->bootmeth_priv; + struct disk_partition misc; + char slot_suffix[3]; + int ret; + + ret = part_get_info_by_name(desc, BCB_PART_NAME, &misc); + if (ret < 0) + return log_msg_ret("part", ret); + + ret = ab_select_slot(desc, &misc, decrement); + if (ret < 0) + return log_msg_ret("slot", ret); + + priv->slot[0] = BOOT_SLOT_NAME(ret); + priv->slot[1] = '\0'; + + sprintf(slot_suffix, "_%s", priv->slot); + ret = bootflow_cmdline_set_arg(bflow, "androidboot.slot_suffix", + slot_suffix, false); + if (ret < 0) + return log_msg_ret("cmdl", ret); + + return 0; +} + +static int configure_serialno(struct bootflow *bflow) +{ + char *serialno = env_get("serial#"); + + if (!serialno) + return log_msg_ret("serial", -ENOENT); + + return bootflow_cmdline_set_arg(bflow, "androidboot.serialno", serialno, false); +} + +static int android_read_bootflow(struct udevice *dev, struct bootflow *bflow) +{ + struct blk_desc *desc = dev_get_uclass_plat(bflow->blk); + struct disk_partition misc; + struct android_priv *priv; + char command[BCB_FIELD_COMMAND_SZ]; + int ret; + + bflow->state = BOOTFLOWST_MEDIA; + + /* + * bcb_find_partition_and_load() will print errors to stdout + * if BCB_PART_NAME is not found. To avoid that, check if the + * partition exists first. + */ + ret = part_get_info_by_name(desc, BCB_PART_NAME, &misc); + if (ret < 0) + return log_msg_ret("part", ret); + + ret = bcb_find_partition_and_load("mmc", desc->devnum, BCB_PART_NAME); + if (ret < 0) + return log_msg_ret("bcb load", ret); + + ret = bcb_get(BCB_FIELD_COMMAND, command, sizeof(command)); + if (ret < 0) + return log_msg_ret("bcb read", ret); + + priv = malloc(sizeof(struct android_priv)); + if (!priv) + return log_msg_ret("buf", -ENOMEM); + + if (!strcmp("bootonce-bootloader", command)) { + priv->boot_mode = ANDROID_BOOT_MODE_BOOTLOADER; + bflow->os_name = strdup("Android (bootloader)"); + } else if (!strcmp("boot-fastboot", command)) { + priv->boot_mode = ANDROID_BOOT_MODE_RECOVERY; + bflow->os_name = strdup("Android (fastbootd)"); + } else if (!strcmp("boot-recovery", command)) { + priv->boot_mode = ANDROID_BOOT_MODE_RECOVERY; + bflow->os_name = strdup("Android (recovery)"); + } else { + priv->boot_mode = ANDROID_BOOT_MODE_NORMAL; + bflow->os_name = strdup("Android"); + } + if (!bflow->os_name) + return log_msg_ret("os", -ENOMEM); + + if (priv->boot_mode == ANDROID_BOOT_MODE_BOOTLOADER) { + /* Clear BCB */ + memset(command, 0, sizeof(command)); + ret = bcb_set(BCB_FIELD_COMMAND, command); + if (ret < 0) { + free(priv); + return log_msg_ret("bcb set", ret); + } + ret = bcb_store(); + if (ret < 0) { + free(priv); + return log_msg_ret("bcb store", ret); + } + + bflow->bootmeth_priv = priv; + bflow->state = BOOTFLOWST_READY; + return 0; + } + + bflow->bootmeth_priv = priv; + + /* For recovery and normal boot, we need to scan the partitions */ + ret = android_read_slot_from_bcb(bflow, false); + if (ret < 0) { + log_err("read slot: %d", ret); + goto free_priv; + } + + ret = scan_boot_part(bflow->blk, priv); + if (ret < 0) { + log_debug("scan boot failed: err=%d\n", ret); + goto free_priv; + } + + if (priv->header_version != 4) { + log_debug("only boot.img v4 is supported %u\n", priv->header_version); + ret = -EINVAL; + goto free_priv; + } + + ret = scan_vendor_boot_part(bflow->blk, priv); + if (ret < 0) { + log_debug("scan vendor_boot failed: err=%d\n", ret); + goto free_priv; + } + + /* Ignoring return code: setting serial number is not mandatory for booting */ + configure_serialno(bflow); + + if (priv->boot_mode == ANDROID_BOOT_MODE_NORMAL) { + ret = bootflow_cmdline_set_arg(bflow, "androidboot.force_normal_boot", + "1", false); + if (ret < 0) { + log_debug("normal_boot %d", ret); + goto free_priv; + } + } + + bflow->state = BOOTFLOWST_READY; + + return 0; + + free_priv: + free(priv); + bflow->bootmeth_priv = NULL; + return ret; +} + +static int android_read_file(struct udevice *dev, struct bootflow *bflow, + const char *file_path, ulong addr, ulong *sizep) +{ + /* + * Reading individual files is not supported since we only + * operate on whole mmc devices (because we require multiple partitions) + */ + return log_msg_ret("Unsupported", -ENOSYS); +} + +/** + * read_slotted_partition() - Read a partition by appending a slot suffix + * + * Most modern Android devices use Seamless Updates, where each partition + * is duplicated. For example, the boot partition has boot_a and boot_b. + * For more information, see: + * https://source.android.com/docs/core/ota/ab + * https://source.android.com/docs/core/ota/ab/ab_implement + * + * @blk: Block device to read + * @name: Partition name to read + * @slot: Nul-terminated slot suffixed to partition name ("a\0" or "b\0") + * @addr: Address where the partition content is loaded into + * Return: 0 if OK, negative errno on failure. + */ +static int read_slotted_partition(struct blk_desc *desc, const char *const name, + const char slot[2], ulong addr) +{ + struct disk_partition partition; + char partname[PART_NAME_LEN]; + int ret; + u32 n; + + /* Ensure name fits in partname it should be: _\0 */ + if (strlen(name) > (PART_NAME_LEN - 2 - 1)) + return log_msg_ret("name too long", -EINVAL); + + sprintf(partname, "%s_%s", name, slot); + ret = part_get_info_by_name(desc, partname, &partition); + if (ret < 0) + return log_msg_ret("part", ret); + + n = blk_dread(desc, partition.start, partition.size, map_sysmem(addr, 0)); + if (n < partition.size) + return log_msg_ret("part read", -EIO); + + return 0; +} + +#if CONFIG_IS_ENABLED(AVB_VERIFY) +static int avb_append_commandline_arg(struct bootflow *bflow, char *arg) +{ + char *key = strsep(&arg, "="); + char *value = arg; + int ret; + + ret = bootflow_cmdline_set_arg(bflow, key, value, false); + if (ret < 0) + return log_msg_ret("avb cmdline", ret); + + return 0; +} + +static int avb_append_commandline(struct bootflow *bflow, char *cmdline) +{ + char *arg = strsep(&cmdline, " "); + int ret; + + while (arg) { + ret = avb_append_commandline_arg(bflow, arg); + if (ret < 0) + return ret; + + arg = strsep(&cmdline, " "); + } + + return 0; +} + +static int run_avb_verification(struct bootflow *bflow) +{ + struct blk_desc *desc = dev_get_uclass_plat(bflow->blk); + struct android_priv *priv = bflow->bootmeth_priv; + const char * const requested_partitions[] = {"boot", "vendor_boot"}; + struct AvbOps *avb_ops; + AvbSlotVerifyResult result; + AvbSlotVerifyData *out_data; + enum avb_boot_state boot_state; + char *extra_args; + char slot_suffix[3]; + bool unlocked = false; + int ret; + + avb_ops = avb_ops_alloc(desc->devnum); + if (!avb_ops) + return log_msg_ret("avb ops", -ENOMEM); + + sprintf(slot_suffix, "_%s", priv->slot); + + ret = avb_ops->read_is_device_unlocked(avb_ops, &unlocked); + if (ret != AVB_IO_RESULT_OK) + return log_msg_ret("avb lock", -EIO); + + result = avb_slot_verify(avb_ops, + requested_partitions, + slot_suffix, + unlocked, + AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE, + &out_data); + + if (result != AVB_SLOT_VERIFY_RESULT_OK) { + printf("Verification failed, reason: %s\n", + str_avb_slot_error(result)); + avb_slot_verify_data_free(out_data); + return log_msg_ret("avb verify", -EIO); + } + + if (unlocked) + boot_state = AVB_ORANGE; + else + boot_state = AVB_GREEN; + + extra_args = avb_set_state(avb_ops, boot_state); + if (extra_args) { + /* extra_args will be modified after this. This is fine */ + ret = avb_append_commandline_arg(bflow, extra_args); + if (ret < 0) + goto free_out_data; + } + + ret = avb_append_commandline(bflow, out_data->cmdline); + if (ret < 0) + goto free_out_data; + + return 0; + + free_out_data: + if (out_data) + avb_slot_verify_data_free(out_data); + + return log_msg_ret("avb cmdline", ret); +} +#else +static int run_avb_verification(struct bootflow *bflow) +{ + int ret; + + /* When AVB is unsupported, pass ORANGE state */ + ret = bootflow_cmdline_set_arg(bflow, + "androidboot.verifiedbootstate", + "orange", false); + if (ret < 0) + return log_msg_ret("avb cmdline", ret); + + return 0; +} +#endif /* AVB_VERIFY */ + +static int boot_android_normal(struct bootflow *bflow) +{ + struct blk_desc *desc = dev_get_uclass_plat(bflow->blk); + struct android_priv *priv = bflow->bootmeth_priv; + int ret; + ulong loadaddr = env_get_hex("loadaddr", 0); + ulong vloadaddr = env_get_hex("vendor_boot_comp_addr_r", 0); + + ret = run_avb_verification(bflow); + if (ret < 0) + return log_msg_ret("avb", ret); + + /* Read slot once more to decrement counter from BCB */ + ret = android_read_slot_from_bcb(bflow, true); + if (ret < 0) + return log_msg_ret("read slot", ret); + + ret = read_slotted_partition(desc, "boot", priv->slot, loadaddr); + if (ret < 0) + return log_msg_ret("read boot", ret); + + ret = read_slotted_partition(desc, "vendor_boot", priv->slot, vloadaddr); + if (ret < 0) + return log_msg_ret("read vendor_boot", ret); + + set_abootimg_addr(loadaddr); + set_avendor_bootimg_addr(vloadaddr); + + ret = bootm_boot_start(loadaddr, bflow->cmdline); + + return log_msg_ret("boot", ret); +} + +static int boot_android_recovery(struct bootflow *bflow) +{ + int ret; + + ret = boot_android_normal(bflow); + + return log_msg_ret("boot", ret); +} + +static int boot_android_bootloader(struct bootflow *bflow) +{ + int ret; + + ret = run_command("fastboot usb 0", 0); + do_reset(NULL, 0, 0, NULL); + + return log_msg_ret("boot", ret); +} + +static int android_boot(struct udevice *dev, struct bootflow *bflow) +{ + struct android_priv *priv = bflow->bootmeth_priv; + int ret; + + switch (priv->boot_mode) { + case ANDROID_BOOT_MODE_NORMAL: + ret = boot_android_normal(bflow); + break; + case ANDROID_BOOT_MODE_RECOVERY: + ret = boot_android_recovery(bflow); + break; + case ANDROID_BOOT_MODE_BOOTLOADER: + ret = boot_android_bootloader(bflow); + break; + default: + printf("ANDROID: Unknown boot mode %d. Running fastboot...\n", + priv->boot_mode); + boot_android_bootloader(bflow); + /* Tell we failed to boot since boot mode is unknown */ + ret = -EFAULT; + } + + return ret; +} + +static int android_bootmeth_bind(struct udevice *dev) +{ + struct bootmeth_uc_plat *plat = dev_get_uclass_plat(dev); + + plat->desc = "Android boot"; + plat->flags = BOOTMETHF_ANY_PART; + + return 0; +} + +static struct bootmeth_ops android_bootmeth_ops = { + .check = android_check, + .read_bootflow = android_read_bootflow, + .read_file = android_read_file, + .boot = android_boot, +}; + +static const struct udevice_id android_bootmeth_ids[] = { + { .compatible = "u-boot,android" }, + { } +}; + +U_BOOT_DRIVER(bootmeth_android) = { + .name = "bootmeth_android", + .id = UCLASS_BOOTMETH, + .of_match = android_bootmeth_ids, + .ops = &android_bootmeth_ops, + .bind = android_bootmeth_bind, +}; diff --git a/boot/bootmeth_android.h b/boot/bootmeth_android.h new file mode 100644 index 000000000000..a57fad9f0113 --- /dev/null +++ b/boot/bootmeth_android.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Bootmethod for Android + * + * Copyright (C) 2024 BayLibre, SAS + * Written by Mattijs Korpershoek + */ + +enum android_boot_mode { + ANDROID_BOOT_MODE_NORMAL = 0, + + /* + * Android "recovery" is a special boot mode that uses another ramdisk. + * It can be used to "factory reset" a board or to flash logical partitions + * It operates in 2 modes: adb or fastbootd + * To enter recovery from Android, we can do: + * $ adb reboot recovery + * $ adb reboot fastboot + */ + ANDROID_BOOT_MODE_RECOVERY, + + /* + * Android "bootloader" is for accessing/reflashing physical partitions + * Typically, this will launch a fastboot process in U-Boot. + * To enter "bootloader" from Android, we can do: + * $ adb reboot bootloader + */ + ANDROID_BOOT_MODE_BOOTLOADER, +}; diff --git a/doc/develop/bootstd.rst b/doc/develop/bootstd.rst index a07a72581e7a..709fa9e64ff3 100644 --- a/doc/develop/bootstd.rst +++ b/doc/develop/bootstd.rst @@ -95,6 +95,7 @@ bootflows. Note: it is possible to have a bootmeth that uses a partition or a whole device directly, but it is more common to use a filesystem. +For example, the Android bootmeth uses a whole device. Note that some bootmeths are 'global', meaning that they select the bootdev themselves. Examples include VBE and EFI boot manager. In this case, they @@ -277,6 +278,9 @@ script_offset_f script_size_f Size of the script to load, e.g. 0x2000 +vendor_boot_comp_addr_r + Address to which to load the vendor_boot Android image, e.g. 0xe0000000 + Some variables are set by script bootmeth: devtype @@ -418,6 +422,7 @@ Bootmeth drivers are provided for: - EFI boot using bootefi from disk - VBE - EFI boot using boot manager + - Android bootflow (boot image v4) Command interface @@ -786,6 +791,7 @@ To do Some things that need to be done to completely replace the distro-boot scripts: - implement extensions (devicetree overlays with add-on boards) +- implement legacy (boot image v2) android boot flow Other ideas: From patchwork Thu Jun 13 10:13:12 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mattijs Korpershoek X-Patchwork-Id: 1947328 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.a=rsa-sha256 header.s=20230601 header.b=rR0Y5POf; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=patchwork.ozlabs.org) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4W0JDY6sjKz20Xd for ; Thu, 13 Jun 2024 20:14:37 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 96978888FB; Thu, 13 Jun 2024 12:13:42 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b="rR0Y5POf"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 3B710888FE; Thu, 13 Jun 2024 12:13:40 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-wr1-x42e.google.com (mail-wr1-x42e.google.com [IPv6:2a00:1450:4864:20::42e]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 87F84883D3 for ; Thu, 13 Jun 2024 12:13:37 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=mkorpershoek@baylibre.com Received: by mail-wr1-x42e.google.com with SMTP id ffacd0b85a97d-35f1bc63981so1210175f8f.1 for ; Thu, 13 Jun 2024 03:13:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1718273617; x=1718878417; darn=lists.denx.de; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=MtGCv03v1Ot/KGRp10yzrIFQKwURzdvZZs4I/hmMfWs=; b=rR0Y5POfQBDnos7kImAZkNuP4k109jKfaiUlEMacy70JSgfk//c24lHKCsjB5IrgAm 4+lThMmLF4fOO+fYr6ZybIZSf0fF5l+GQ9MhEsNznaITahzsZlKvlUQc1mRsnw7eOerm XC3OLVxd7PJpsDOsBXtqi0BXbRQjnpwvmjcx8wH4tU9RKatyd2a20HdR1qYptRgAhy5j 5P0jcNQJ3EmUZavf0b3ulf1gdOz2PsEd+AfYsweytgttOTiAEr2isasOSeYAORcOITXZ unrfD2WyOgVS75XQR1cCC9oM0QLG9eIWaVggJukOBwkXo6eXpfAhnw87AchTqggoE9Nl 56kw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1718273617; x=1718878417; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=MtGCv03v1Ot/KGRp10yzrIFQKwURzdvZZs4I/hmMfWs=; b=oKjCWtm0J+067mKmtUZWbBS0c+ZHkHh6sODxQk/xgB1UOUZYKjnvU2a5T+1MelRus+ ChGcD5a8hpf/WWmdqpdAwD96K9MirXVa607Sr8PqcKBZMjHitGCnIdC3tvMUAOtx1/wq DJsnIdca+sb4Ho7iu/KdwZeklI0U0ViQBqN/Mk+MqvbfrCAf3QFlJ2kZZhdTYptsx/Lz xADNgUQiksg1J399346TnOtWVJ+qN6Y4ETwWX36ww0qjp9WOZQUFJWAVQwbJNPe17ICH gdh5wcLPpjLEtmy9m2gQDF7NoQtc4g12KnRqwaQjuY9eeXue35XqLsLVszGIW/OMhxjt 20xQ== X-Forwarded-Encrypted: i=1; AJvYcCUAZB17qRF7bbr88odqgVH7CTYwK9IeU0Tdqk/mYwODoq7AK7NIPO0cotlJW2K7ViG02P+t+UHuRHtVm5d5x4B6wN0PdQ== X-Gm-Message-State: AOJu0Yz2/fEmrh6WUvRGWRjSgsDD+TDXymK6Sk2JGoRgGmfO5frNc9OS ds76rJU4nPKw940V47duABsO/rgBOL2yQnThx+kRF68KMFSg3me0bbYdewlq7U8Y30dW5scEpCL loPs= X-Google-Smtp-Source: AGHT+IFnZrfH3v/8IU7Bl12XjRwbCrgp/sQil/ogqX/UxGjejf4xCVp2YR1lxnczLWX/PafadNOXCA== X-Received: by 2002:a5d:6e8c:0:b0:360:7761:e304 with SMTP id ffacd0b85a97d-3607761e376mr970874f8f.1.1718273616924; Thu, 13 Jun 2024 03:13:36 -0700 (PDT) Received: from groot.home ([2a01:cb19:95ba:5000:d6dd:417f:52ac:335b]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-360750f2295sm1251573f8f.82.2024.06.13.03.13.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 13 Jun 2024 03:13:36 -0700 (PDT) From: Mattijs Korpershoek Date: Thu, 13 Jun 2024 12:13:12 +0200 Subject: [PATCH v2 5/5] bootstd: Add test for bootmeth_android MIME-Version: 1.0 Message-Id: <20240613-bootmeth-android-v2-5-397f6e66eb29@baylibre.com> References: <20240613-bootmeth-android-v2-0-397f6e66eb29@baylibre.com> In-Reply-To: <20240613-bootmeth-android-v2-0-397f6e66eb29@baylibre.com> To: Simon Glass Cc: Julien Masson , Guillaume La Roque , Dmitrii Merkurev , Roman Stratiienko , Igor Opaniuk , u-boot@lists.denx.de, Mattijs Korpershoek X-Mailer: b4 0.14-dev-d4707 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 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" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean Add a unit test for testing the Android bootmethod. This requires another mmc image (mmc7) to contain the following partitions: - misc: contains the Bootloader Control Block (BCB) - boot_a: contains a fake generic kernel image - vendor_boot_a: contains a fake vendor_boot image Also add BOOTMETH_ANDROID as a dependency on sandbox so that we can test this with: $ ./test/py/test.py --bd sandbox --build -k test_abootimg # build bootv4.img $ ./test/py/test.py --bd sandbox --build -k test_ut # build the mmc7.img $ ./test/py/test.py --bd sandbox --build -k bootflow_android Reviewed-by: Simon Glass Signed-off-by: Mattijs Korpershoek Reviewed-by: Julien Masson Reviewed-by: Guillaume La Roque --- arch/sandbox/dts/test.dts | 8 +++++ configs/sandbox_defconfig | 2 +- test/boot/bootflow.c | 65 ++++++++++++++++++++++++++++++++++++++-- test/py/tests/test_ut.py | 76 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 147 insertions(+), 4 deletions(-) diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index a012f5c4c9ba..5fb5eac862ec 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -43,6 +43,7 @@ mmc4 = "/mmc4"; mmc5 = "/mmc5"; mmc6 = "/mmc6"; + mmc7 = "/mmc7"; pci0 = &pci0; pci1 = &pci1; pci2 = &pci2; @@ -1129,6 +1130,13 @@ filename = "mmc6.img"; }; + /* This is used for Android tests */ + mmc7 { + status = "disabled"; + compatible = "sandbox,mmc"; + filename = "mmc7.img"; + }; + pch { compatible = "sandbox,pch"; }; diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index 93b52f2de5cf..bc4398f101a7 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -15,6 +15,7 @@ CONFIG_FIT=y CONFIG_FIT_RSASSA_PSS=y CONFIG_FIT_CIPHER=y CONFIG_FIT_VERBOSE=y +CONFIG_BOOTMETH_ANDROID=y CONFIG_LEGACY_IMAGE_FORMAT=y CONFIG_MEASURED_BOOT=y CONFIG_BOOTSTAGE=y @@ -40,7 +41,6 @@ CONFIG_LOG_MAX_LEVEL=9 CONFIG_LOG_DEFAULT_LEVEL=6 CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_STACKPROTECTOR=y -CONFIG_ANDROID_AB=y CONFIG_CMD_CPU=y CONFIG_CMD_LICENSE=y CONFIG_CMD_SMBIOS=y diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c index 4511cfa7f9bf..934c4dcbad2b 100644 --- a/test/boot/bootflow.c +++ b/test/boot/bootflow.c @@ -27,6 +27,7 @@ DECLARE_GLOBAL_DATA_PTR; +extern U_BOOT_DRIVER(bootmeth_android); extern U_BOOT_DRIVER(bootmeth_cros); extern U_BOOT_DRIVER(bootmeth_2script); @@ -518,12 +519,12 @@ BOOTSTD_TEST(bootflow_cmd_boot, UT_TESTF_DM | UT_TESTF_SCAN_FDT); * @uts: Unit test state * @mmc_dev: MMC device to use, e.g. "mmc4". Note that this must remain valid * in the caller until - * @bind_cros: true to bind the ChromiumOS bootmeth + * @bind_cros: true to bind the ChromiumOS and Android bootmeths * @old_orderp: Returns the original bootdev order, which must be restored * Returns 0 on success, -ve on failure */ static int prep_mmc_bootdev(struct unit_test_state *uts, const char *mmc_dev, - bool bind_cros, const char ***old_orderp) + bool bind_cros_android, const char ***old_orderp) { static const char *order[] = {"mmc2", "mmc1", NULL, NULL}; struct udevice *dev, *bootstd; @@ -545,12 +546,19 @@ static int prep_mmc_bootdev(struct unit_test_state *uts, const char *mmc_dev, "bootmeth_script", 0, ofnode_null(), &dev)); /* Enable the cros bootmeth if needed */ - if (IS_ENABLED(CONFIG_BOOTMETH_CROS) && bind_cros) { + if (IS_ENABLED(CONFIG_BOOTMETH_CROS) && bind_cros_android) { ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd)); ut_assertok(device_bind(bootstd, DM_DRIVER_REF(bootmeth_cros), "cros", 0, ofnode_null(), &dev)); } + /* Enable the android bootmeths if needed */ + if (IS_ENABLED(CONFIG_BOOTMETH_ANDROID) && bind_cros_android) { + ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd)); + ut_assertok(device_bind(bootstd, DM_DRIVER_REF(bootmeth_android), + "android", 0, ofnode_null(), &dev)); + } + /* Change the order to include the device */ std = dev_get_priv(bootstd); old_order = std->bootdev_order; @@ -589,6 +597,37 @@ static int scan_mmc_bootdev(struct unit_test_state *uts, const char *mmc_dev, return 0; } +/** + * scan_mmc_android_bootdev() - Set up an mmc bootdev so we can access other + * distros. Android bootflow might print "ANDROID:*" while scanning + * + * @uts: Unit test state + * @mmc_dev: MMC device to use, e.g. "mmc4" + * Returns 0 on success, -ve on failure + */ +static int scan_mmc_android_bootdev(struct unit_test_state *uts, const char *mmc_dev) +{ + struct bootstd_priv *std; + struct udevice *bootstd; + const char **old_order; + + ut_assertok(prep_mmc_bootdev(uts, mmc_dev, true, &old_order)); + + console_record_reset_enable(); + ut_assertok(run_command("bootflow scan", 0)); + /* Android bootflow might print one or two 'ANDROID:*' logs */ + ut_check_skipline(uts); + ut_check_skipline(uts); + ut_assert_console_end(); + + /* Restore the order used by the device tree */ + ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd)); + std = dev_get_priv(bootstd); + std->bootdev_order = old_order; + + return 0; +} + /** * scan_mmc4_bootdev() - Set up the mmc4 bootdev so we can access a fake Armbian * @@ -1160,3 +1199,23 @@ static int bootflow_cros(struct unit_test_state *uts) return 0; } BOOTSTD_TEST(bootflow_cros, 0); + +/* Test Android bootmeth */ +static int bootflow_android(struct unit_test_state *uts) +{ + ut_assertok(scan_mmc_android_bootdev(uts, "mmc7")); + ut_assertok(run_command("bootflow list", 0)); + + ut_assert_nextlinen("Showing all"); + ut_assert_nextlinen("Seq"); + ut_assert_nextlinen("---"); + ut_assert_nextlinen(" 0 extlinux"); + ut_assert_nextlinen(" 1 android ready mmc 0 mmc7.bootdev.whole "); + ut_assert_nextlinen("---"); + ut_assert_skip_to_line("(2 bootflows, 2 valid)"); + + ut_assert_console_end(); + + return 0; +} +BOOTSTD_TEST(bootflow_android, 0); diff --git a/test/py/tests/test_ut.py b/test/py/tests/test_ut.py index c169c835e38a..39e1abe02a68 100644 --- a/test/py/tests/test_ut.py +++ b/test/py/tests/test_ut.py @@ -423,6 +423,81 @@ def setup_cros_image(cons): return fname +def setup_android_image(cons): + """Create a 20MB disk image with Android partitions""" + Partition = collections.namedtuple('part', 'start,size,name') + parts = {} + disk_data = None + + def set_part_data(partnum, data): + """Set the contents of a disk partition + + This updates disk_data by putting data in the right place + + Args: + partnum (int): Partition number to set + data (bytes): Data for that partition + """ + nonlocal disk_data + + start = parts[partnum].start * sect_size + disk_data = disk_data[:start] + data + disk_data[start + len(data):] + + mmc_dev = 7 + fname = os.path.join(cons.config.source_dir, f'mmc{mmc_dev}.img') + u_boot_utils.run_and_log(cons, 'qemu-img create %s 20M' % fname) + u_boot_utils.run_and_log(cons, f'cgpt create {fname}') + + ptr = 40 + + # Number of sectors in 1MB + sect_size = 512 + sect_1mb = (1 << 20) // sect_size + + required_parts = [ + {'num': 1, 'label':'misc', 'size': '1M'}, + {'num': 2, 'label':'boot_a', 'size': '4M'}, + {'num': 3, 'label':'boot_b', 'size': '4M'}, + {'num': 4, 'label':'vendor_boot_a', 'size': '4M'}, + {'num': 5, 'label':'vendor_boot_b', 'size': '4M'}, + ] + + for part in required_parts: + size_str = part['size'] + if 'M' in size_str: + size = int(size_str[:-1]) * sect_1mb + else: + size = int(size_str) + u_boot_utils.run_and_log( + cons, + f"cgpt add -i {part['num']} -b {ptr} -s {size} -l {part['label']} -t basicdata {fname}") + ptr += size + + u_boot_utils.run_and_log(cons, f'cgpt boot -p {fname}') + out = u_boot_utils.run_and_log(cons, f'cgpt show -q {fname}') + + # Create a dict (indexed by partition number) containing the above info + for line in out.splitlines(): + start, size, num, name = line.split(maxsplit=3) + parts[int(num)] = Partition(int(start), int(size), name) + + with open(fname, 'rb') as inf: + disk_data = inf.read() + + boot_img = os.path.join(cons.config.result_dir, 'bootv4.img') + with open(boot_img, 'rb') as inf: + set_part_data(2, inf.read()) + + vendor_boot_img = os.path.join(cons.config.result_dir, 'vendor_boot.img') + with open(vendor_boot_img, 'rb') as inf: + set_part_data(4, inf.read()) + + with open(fname, 'wb') as outf: + outf.write(disk_data) + + print('wrote to {}'.format(fname)) + + return fname def setup_cedit_file(cons): infname = os.path.join(cons.config.source_dir, @@ -477,6 +552,7 @@ def test_ut_dm_init_bootstd(u_boot_console): setup_bootmenu_image(u_boot_console) setup_cedit_file(u_boot_console) setup_cros_image(u_boot_console) + setup_android_image(u_boot_console) # Restart so that the new mmc1.img is picked up u_boot_console.restart_uboot()