From patchwork Mon Jul 15 13:54:33 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?UmFmYcWCIE1pxYJlY2tp?= X-Patchwork-Id: 13733566 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 11664C3DA4B for ; Mon, 15 Jul 2024 13:57:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: Content-Type:MIME-Version:Message-Id:Date:Subject:Cc:To:From:Reply-To: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References:List-Owner; bh=zJEofbM7JJv/OPvTziaKTUDT40OBgVWW/o2FBZFQ/8c=; b=sS8epuZvObERaqsTQxmU4yk96P LOEWO0zXnZo6ulNsK672HXcwF9PkJAVaOl9au4xBU1X6XAFpXoilUDjX0qsLBD5SDL4OqUeqsxDOd fzWGiAq4ckRMqFAJGaJAFIWj9ZLoLclWZ/6AJXBUWWNmh7VCNeuRjHX0gmnQCj1jVmLsfV6ZEgfwA Lz4sHQwoH3bVaHJGkmHVjRxqGWrYUmSYogp1siyLktoRIBeLu7lYkyFKdjPT/Rzsbaeg4t0enMEcM SR7QViz8k80CQTqPTio13YoxjeMyx56rHy3Xqlsk4gnJS6lYCmLClUoEvefhj1oHzh2WvQKMHQoLj uU6S1Rxg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1sTMCA-00000007HnK-2RzS; Mon, 15 Jul 2024 13:56:50 +0000 Received: from mail-ej1-x62f.google.com ([2a00:1450:4864:20::62f]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1sTMBb-00000007HZT-3Tyt; Mon, 15 Jul 2024 13:56:17 +0000 Received: by mail-ej1-x62f.google.com with SMTP id a640c23a62f3a-a77e6dd7f72so522649466b.3; Mon, 15 Jul 2024 06:56:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1721051773; x=1721656573; darn=lists.infradead.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=zJEofbM7JJv/OPvTziaKTUDT40OBgVWW/o2FBZFQ/8c=; b=iz70JgaIpypbydmFQVRUa4njdx+9s3PRg9D7Pgm6qAyZ65AQW22GiVKhST6G0keU0k 3cp09cgPuy0eCQ+XUn8sL7qCjhOM6BhrUxBw+iGjZJEw8o8RvBvj26CqTykuISUky38z otFm7ki6gmRdNxxG3iUrXCZ4Ksg1fylfpT0jqDlq3YuqG0Je+SVNMM5hFTc6rKpskNOR suCWRMQwNQaPYySAOuujwmzqZcroXroYgILiMX6SmE26xSWiIkEJq/MNbJUI61EK4su7 ++THJcQDwL2A3naoMO6lPoYGcaaLaGvTHu/ykfg96w8hG1ieI8Q49juSZk2IUdDi4jYb o9Ug== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1721051773; x=1721656573; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=zJEofbM7JJv/OPvTziaKTUDT40OBgVWW/o2FBZFQ/8c=; b=Yv9PLitHSQr9y5Qt4rYQZCyy8A9vBVD436ZNfjWia0GIE+SAbH3Q+vVpSEvdM57fjo vD/ay67dmxCS8HkWBczbW7DrW47pTHy1smqH78hRy8irqW/lG7+RNtAipEg4OrEfUHJW sSSbECHbG/6UrmOVMs1gr7PDdELBymgKRAFvqn3VCdmaXPpn41q9RJXofR7ejOwekbdj D0A29UzPbql+EDG1sIN8TdwwjpwcBEMK+lBcBhzpmm/DrxqKO97KdlQLzbl+fSPLP9Oy m5ubMPwWXz6wzc2fb7e40tgwyNQuf5eEKJ1Doyih2KfWgh1W6WgydTGAG+0nJIwi4Lhu V20Q== X-Forwarded-Encrypted: i=1; AJvYcCX11tbLcngjCXewrGZh78iWAwDG8lAz6TB6t/tdXaDvXvSs4X585153RsjIhEc2VWpLuKn08jJJOdrh+fpGeIm+CwLiIiJOa3Ufv9+AKWPtKQj12xaxeTqAC86Y5Z3zyy3YwRrN1i8es9WvUVReCFsx3hqu X-Gm-Message-State: AOJu0Yy8IluJpz1fyuSUlMq88vvz9ms8/N4saBxQmdX0lKFKIBrOeJfK t8S8PfQNrZEdnQzMhoJ5kxcTAOIAkHjwRZhO5Hs6C5B/9N1xNtHR X-Google-Smtp-Source: AGHT+IGFwyv96gykRh2WQAFospTSXU2UQACz9q8YtryxBrJrikNX9BsuYSLrXYopy2ZsFmRYUjaEzg== X-Received: by 2002:a17:906:2797:b0:a77:c5e4:eebf with SMTP id a640c23a62f3a-a780b87ef50mr1185426566b.54.1721051773034; Mon, 15 Jul 2024 06:56:13 -0700 (PDT) Received: from localhost.lan (031011218106.poznan.vectranet.pl. [31.11.218.106]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-a79bc820fb5sm214152666b.212.2024.07.15.06.56.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 15 Jul 2024 06:56:12 -0700 (PDT) From: =?utf-8?b?UmFmYcWCIE1pxYJlY2tp?= To: Srinivas Kandagatla , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: Greg Kroah-Hartman , Michael Walle , Miquel Raynal , devicetree@vger.kernel.org, linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, u-boot@lists.denx.de, linux-kernel@vger.kernel.org, =?utf-8?b?UmFmYcWCIE1pxYJlY2tp?= Subject: [PATCH 1/2] dt-bindings: nvmem: convert U-Boot env to a layout Date: Mon, 15 Jul 2024 15:54:33 +0200 Message-Id: <20240715135434.24992-1-zajec5@gmail.com> X-Mailer: git-send-email 2.35.3 MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240715_065615_899054_5F49802E X-CRM114-Status: GOOD ( 15.25 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org From: Rafał Miłecki U-Boot environment variables can be stored in various data sources. MTD is just one of available options. Refactor DT binding into a layout so it can be used with UBI volumes and other NVMEM devices. Link: https://lore.kernel.org/all/20231221173421.13737-1-zajec5@gmail.com/ Signed-off-by: Rafał Miłecki Reviewed-by: Rob Herring (Arm) --- I'm resending this approved by Rob PATCH in a proper series .../bindings/nvmem/layouts/nvmem-layout.yaml | 1 + .../nvmem/{ => layouts}/u-boot,env.yaml | 39 ++++++++++++++++--- 2 files changed, 35 insertions(+), 5 deletions(-) rename Documentation/devicetree/bindings/nvmem/{ => layouts}/u-boot,env.yaml (75%) diff --git a/Documentation/devicetree/bindings/nvmem/layouts/nvmem-layout.yaml b/Documentation/devicetree/bindings/nvmem/layouts/nvmem-layout.yaml index 3b40f7880774..382507060651 100644 --- a/Documentation/devicetree/bindings/nvmem/layouts/nvmem-layout.yaml +++ b/Documentation/devicetree/bindings/nvmem/layouts/nvmem-layout.yaml @@ -21,6 +21,7 @@ oneOf: - $ref: fixed-layout.yaml - $ref: kontron,sl28-vpd.yaml - $ref: onie,tlv-layout.yaml + - $ref: u-boot,env.yaml properties: compatible: true diff --git a/Documentation/devicetree/bindings/nvmem/u-boot,env.yaml b/Documentation/devicetree/bindings/nvmem/layouts/u-boot,env.yaml similarity index 75% rename from Documentation/devicetree/bindings/nvmem/u-boot,env.yaml rename to Documentation/devicetree/bindings/nvmem/layouts/u-boot,env.yaml index 9c36afc7084b..56a8f55d4a09 100644 --- a/Documentation/devicetree/bindings/nvmem/u-boot,env.yaml +++ b/Documentation/devicetree/bindings/nvmem/layouts/u-boot,env.yaml @@ -1,10 +1,10 @@ # SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause %YAML 1.2 --- -$id: http://devicetree.org/schemas/nvmem/u-boot,env.yaml# +$id: http://devicetree.org/schemas/nvmem/layouts/u-boot,env.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: U-Boot environment variables +title: U-Boot environment variables layout description: | U-Boot uses environment variables to store device parameters and @@ -21,9 +21,6 @@ description: | This binding allows marking storage device (as containing env data) and specifying used format. - Right now only flash partition case is covered but it may be extended to e.g. - UBI volumes in the future. - Variables can be defined as NVMEM device subnodes. maintainers: @@ -42,6 +39,7 @@ properties: const: brcm,env reg: + description: Partition offset and size for env on top of MTD maxItems: 1 bootcmd: @@ -58,6 +56,17 @@ properties: description: The first argument is a MAC address offset. const: 1 +allOf: + - if: + properties: + $nodename: + not: + contains: + pattern: "^partition@[0-9a-f]+$" + then: + properties: + reg: false + additionalProperties: false examples: @@ -101,3 +110,23 @@ examples: }; }; }; + - | + partition@0 { + reg = <0x0 0x100000>; + label = "ubi"; + compatible = "linux,ubi"; + + volumes { + ubi-volume-u-boot-env { + volname = "env"; + + nvmem-layout { + compatible = "u-boot,env"; + + ethaddr { + #nvmem-cell-cells = <1>; + }; + }; + }; + }; + }; From patchwork Mon Jul 15 13:54:34 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?UmFmYcWCIE1pxYJlY2tp?= X-Patchwork-Id: 13733567 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 8DDCBC3DA4B for ; Mon, 15 Jul 2024 13:57:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: Content-Type:MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc: To:From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=/x83uhAgtPmXyFX07eC/O7WLqpmAACzSVrglNL9NB4Q=; b=UtNU4SbmN6P8cnPHw3S0xO+POB LEZQLw3pJRlOv7GKVGABHA0G430nn4dEW+y8VPZPZY2ebCzq3bhlazJP5VVMLTuKrWmtAd84JvzNp atXmTRA66uTzxKzZEsTUP593/dgUjnyliEUsYMuV4fw7ea5LU0+h+4kFjGxdB5Ke5IZcWuq2jZaSQ X7m/wzVKJQ2WK5Xtzt07kilsfnzbW9FPZhnnrujusVYcCbjQX4b1VBBAiJS/16cWsDbBFSJRbzJHF 6J4HSNP3FBpYYxjNKbCkfVwvK2vu/RKDCRwtv2MN5hquhLqivzxycXz6/sRSPKTXGyiYG6+nb0dqO Nd1sFUIQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1sTMCU-00000007HyH-30ZZ; Mon, 15 Jul 2024 13:57:11 +0000 Received: from mail-ed1-x529.google.com ([2a00:1450:4864:20::529]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1sTMBe-00000007HZy-0874; Mon, 15 Jul 2024 13:56:19 +0000 Received: by mail-ed1-x529.google.com with SMTP id 4fb4d7f45d1cf-58bac81f40bso5464958a12.1; Mon, 15 Jul 2024 06:56:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1721051776; x=1721656576; darn=lists.infradead.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=/x83uhAgtPmXyFX07eC/O7WLqpmAACzSVrglNL9NB4Q=; b=B9jjhexhrboSXRMKxQOFc8x+E/7Mg8Xk6HLcxwxWtJTrM6caz+18Z6zgEAGh8uXEtO VqISEW4xH0wRqCgrLvPQXT8rNzu3pMFfLVxlrD7MzCspENXjxHLZTEJMsLa0b9KDgaV5 ZyQ3PNkgwhjpvNOQUhapxIF6f9tDPvftBQHlcOPuRPp58of9EqC63eEN6RpdBI846JpU 9n3vPPbFcKbnu3AWBVJru9ESZXZb7V9vlXjfoVtQ2PyKosOxrnSOe4GpclR4JOVCVVs0 c7q9UjHxPinCap1jLRqTaP5nlsdsJdCiRhrLyIN/RMtD/Pg2MAyMtVgYxcMrEg8bPrlz q7vQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1721051776; x=1721656576; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=/x83uhAgtPmXyFX07eC/O7WLqpmAACzSVrglNL9NB4Q=; b=FE0Ky8qlQyv/5dlR5OHO0Yt5T42EeosWNZpKdXLfs841to5IRSpj0nBLoX7CSNSA6S s611mpqUmVpljWr0aqsN+AxE4sw1kACGj+INkJHXbFkWQ8MC+wfIv+na36ZgoC5xeRLk F84gHTBGvOzhp5TraF6sAwHxN1BocwgYxRVInYQt54MM+Pr7jDkNoLWRYHTYSG3qZbBc L26wcXTWQAokRpuH4DLCMz0D5IoDrZQqiyLn6rbjMcy5ieMAnMqVBfGey+QZ896ePOmO 5+u6zPMKm/jN93sPnJLVFDb/t31kzGUEYt6x6IzouGxT+wEwC2aHXYCNXP6Y4UMfGgMR ES9Q== X-Forwarded-Encrypted: i=1; AJvYcCUm4aQOT7fykhW8cdwD1zkSWwaX19uHWTCmZqd5h44rXAMwRPO+pSM1RgukjnCXjmeFRT5WJER11r3nbyZLUUwlVTnsGZH4vvBiCksDiaAgM3XeI0QobiE+8lUvqLHpMl/CntW0zS9ZljI7z+SqK7a7ufDh X-Gm-Message-State: AOJu0YxjS5dpWIWYzFk5qb0rnPVVNNQ0kEwkQ9X6pg98HFjaCtYeE3Lj bm0vD5qB6pXEBvrbMxCh4VPbUBHCIUb5ui7b07Vg4Wb3WnTD73sX X-Google-Smtp-Source: AGHT+IHPpD+P62FtzVEMDnMZgeFr1JSMF4gFq5zl6R2/HnDqhZRyMPOo8WRtL5f7veqS69z5F1pdXg== X-Received: by 2002:a17:907:7d8a:b0:a6f:59dc:4ece with SMTP id a640c23a62f3a-a780b68a9ecmr1482293066b.2.1721051775581; Mon, 15 Jul 2024 06:56:15 -0700 (PDT) Received: from localhost.lan (031011218106.poznan.vectranet.pl. [31.11.218.106]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-a79bc820fb5sm214152666b.212.2024.07.15.06.56.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 15 Jul 2024 06:56:15 -0700 (PDT) From: =?utf-8?b?UmFmYcWCIE1pxYJlY2tp?= To: Srinivas Kandagatla , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: Greg Kroah-Hartman , Michael Walle , Miquel Raynal , devicetree@vger.kernel.org, linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, u-boot@lists.denx.de, linux-kernel@vger.kernel.org, =?utf-8?b?UmFmYcWCIE1pxYJlY2tp?= Subject: [PATCH 2/2] nvmem: layouts: add U-Boot env layout Date: Mon, 15 Jul 2024 15:54:34 +0200 Message-Id: <20240715135434.24992-2-zajec5@gmail.com> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20240715135434.24992-1-zajec5@gmail.com> References: <20240715135434.24992-1-zajec5@gmail.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240715_065618_114006_2E49EA1B X-CRM114-Status: GOOD ( 30.99 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org From: Rafał Miłecki U-Boot environment variables are stored in a specific format. Actual data can be placed in various storage sources (MTD, UBI volume, EEPROM, NVRAM, etc.). Move all generic (NVMEM device independent) code from NVMEM device driver to an NVMEM layout driver. Then add a simple NVMEM layout code on top of it. This allows using NVMEM layout for parsing U-Boot env data stored in any kind of NVMEM device. The old NVMEM glue driver stays in place for handling bindings in the MTD context. To avoid code duplication it uses exported layout parsing function. Please note that handling MTD & NVMEM layout bindings may be refactored in the future. Signed-off-by: Rafał Miłecki Reviewed-by: Miquel Raynal --- This change was originally sent (and approved by Miquel) as a [PATCH V3 6/6] nvmem: layouts: add U-Boot env layout I just adjusted it to the approved binding and updated commit message. I kept Miquel's Reviewed-by tag due to minimal changes. I've successfully tested this code using it in both ways: as NVMEM device driver & NVMEM layout. MAINTAINERS | 1 + drivers/nvmem/Kconfig | 3 +- drivers/nvmem/layouts/Kconfig | 11 ++ drivers/nvmem/layouts/Makefile | 1 + drivers/nvmem/layouts/u-boot-env.c | 203 +++++++++++++++++++++++++++++ drivers/nvmem/layouts/u-boot-env.h | 15 +++ drivers/nvmem/u-boot-env.c | 158 +--------------------- 7 files changed, 234 insertions(+), 158 deletions(-) create mode 100644 drivers/nvmem/layouts/u-boot-env.c create mode 100644 drivers/nvmem/layouts/u-boot-env.h diff --git a/MAINTAINERS b/MAINTAINERS index 31fb0031a5e8..630d16c480dd 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -23331,6 +23331,7 @@ U-BOOT ENVIRONMENT VARIABLES M: Rafał Miłecki S: Maintained F: Documentation/devicetree/bindings/nvmem/u-boot,env.yaml +F: drivers/nvmem/layouts/u-boot-env.c F: drivers/nvmem/u-boot-env.c UACCE ACCELERATOR FRAMEWORK diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig index 283134498fbc..d2c384f58028 100644 --- a/drivers/nvmem/Kconfig +++ b/drivers/nvmem/Kconfig @@ -363,8 +363,7 @@ config NVMEM_SUNXI_SID config NVMEM_U_BOOT_ENV tristate "U-Boot environment variables support" depends on OF && MTD - select CRC32 - select GENERIC_NET_UTILS + select NVMEM_LAYOUT_U_BOOT_ENV help U-Boot stores its setup as environment variables. This driver adds support for verifying & exporting such data. It also exposes variables diff --git a/drivers/nvmem/layouts/Kconfig b/drivers/nvmem/layouts/Kconfig index 9c6e672fc350..5e586dfebe47 100644 --- a/drivers/nvmem/layouts/Kconfig +++ b/drivers/nvmem/layouts/Kconfig @@ -26,6 +26,17 @@ config NVMEM_LAYOUT_ONIE_TLV If unsure, say N. +config NVMEM_LAYOUT_U_BOOT_ENV + tristate "U-Boot environment variables layout" + select CRC32 + select GENERIC_NET_UTILS + help + U-Boot stores its setup as environment variables. This driver adds + support for verifying & exporting such data. It also exposes variables + as NVMEM cells so they can be referenced by other drivers. + + If unsure, say N. + endmenu endif diff --git a/drivers/nvmem/layouts/Makefile b/drivers/nvmem/layouts/Makefile index 2974bd7d33ed..4940c9db0665 100644 --- a/drivers/nvmem/layouts/Makefile +++ b/drivers/nvmem/layouts/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_NVMEM_LAYOUT_SL28_VPD) += sl28vpd.o obj-$(CONFIG_NVMEM_LAYOUT_ONIE_TLV) += onie-tlv.o +obj-$(CONFIG_NVMEM_LAYOUT_U_BOOT_ENV) += u-boot-env.o diff --git a/drivers/nvmem/layouts/u-boot-env.c b/drivers/nvmem/layouts/u-boot-env.c new file mode 100644 index 000000000000..5217dc4a52f8 --- /dev/null +++ b/drivers/nvmem/layouts/u-boot-env.c @@ -0,0 +1,203 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2022 - 2023 Rafał Miłecki + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "u-boot-env.h" + +struct u_boot_env_image_single { + __le32 crc32; + uint8_t data[]; +} __packed; + +struct u_boot_env_image_redundant { + __le32 crc32; + u8 mark; + uint8_t data[]; +} __packed; + +struct u_boot_env_image_broadcom { + __le32 magic; + __le32 len; + __le32 crc32; + DECLARE_FLEX_ARRAY(uint8_t, data); +} __packed; + +static int u_boot_env_read_post_process_ethaddr(void *context, const char *id, int index, + unsigned int offset, void *buf, size_t bytes) +{ + u8 mac[ETH_ALEN]; + + if (bytes != 3 * ETH_ALEN - 1) + return -EINVAL; + + if (!mac_pton(buf, mac)) + return -EINVAL; + + if (index) + eth_addr_add(mac, index); + + ether_addr_copy(buf, mac); + + return 0; +} + +static int u_boot_env_parse_cells(struct device *dev, struct nvmem_device *nvmem, uint8_t *buf, + size_t data_offset, size_t data_len) +{ + char *data = buf + data_offset; + char *var, *value, *eq; + + for (var = data; + var < data + data_len && *var; + var = value + strlen(value) + 1) { + struct nvmem_cell_info info = {}; + + eq = strchr(var, '='); + if (!eq) + break; + *eq = '\0'; + value = eq + 1; + + info.name = devm_kstrdup(dev, var, GFP_KERNEL); + if (!info.name) + return -ENOMEM; + info.offset = data_offset + value - data; + info.bytes = strlen(value); + info.np = of_get_child_by_name(dev->of_node, info.name); + if (!strcmp(var, "ethaddr")) { + info.raw_len = strlen(value); + info.bytes = ETH_ALEN; + info.read_post_process = u_boot_env_read_post_process_ethaddr; + } + + nvmem_add_one_cell(nvmem, &info); + } + + return 0; +} + +int u_boot_env_parse(struct device *dev, struct nvmem_device *nvmem, + enum u_boot_env_format format) +{ + size_t crc32_data_offset; + size_t crc32_data_len; + size_t crc32_offset; + __le32 *crc32_addr; + size_t data_offset; + size_t data_len; + size_t dev_size; + uint32_t crc32; + uint32_t calc; + uint8_t *buf; + int bytes; + int err; + + dev_size = nvmem_dev_size(nvmem); + + buf = kzalloc(dev_size, GFP_KERNEL); + if (!buf) { + err = -ENOMEM; + goto err_out; + } + + bytes = nvmem_device_read(nvmem, 0, dev_size, buf); + if (bytes < 0) { + err = bytes; + goto err_kfree; + } else if (bytes != dev_size) { + err = -EIO; + goto err_kfree; + } + + switch (format) { + case U_BOOT_FORMAT_SINGLE: + crc32_offset = offsetof(struct u_boot_env_image_single, crc32); + crc32_data_offset = offsetof(struct u_boot_env_image_single, data); + data_offset = offsetof(struct u_boot_env_image_single, data); + break; + case U_BOOT_FORMAT_REDUNDANT: + crc32_offset = offsetof(struct u_boot_env_image_redundant, crc32); + crc32_data_offset = offsetof(struct u_boot_env_image_redundant, data); + data_offset = offsetof(struct u_boot_env_image_redundant, data); + break; + case U_BOOT_FORMAT_BROADCOM: + crc32_offset = offsetof(struct u_boot_env_image_broadcom, crc32); + crc32_data_offset = offsetof(struct u_boot_env_image_broadcom, data); + data_offset = offsetof(struct u_boot_env_image_broadcom, data); + break; + } + crc32_addr = (__le32 *)(buf + crc32_offset); + crc32 = le32_to_cpu(*crc32_addr); + crc32_data_len = dev_size - crc32_data_offset; + data_len = dev_size - data_offset; + + calc = crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L; + if (calc != crc32) { + dev_err(dev, "Invalid calculated CRC32: 0x%08x (expected: 0x%08x)\n", calc, crc32); + err = -EINVAL; + goto err_kfree; + } + + buf[dev_size - 1] = '\0'; + err = u_boot_env_parse_cells(dev, nvmem, buf, data_offset, data_len); + +err_kfree: + kfree(buf); +err_out: + return err; +} +EXPORT_SYMBOL_GPL(u_boot_env_parse); + +static int u_boot_env_add_cells(struct nvmem_layout *layout) +{ + struct device *dev = &layout->dev; + enum u_boot_env_format format; + + format = (uintptr_t)device_get_match_data(dev); + + return u_boot_env_parse(dev, layout->nvmem, format); +} + +static int u_boot_env_probe(struct nvmem_layout *layout) +{ + layout->add_cells = u_boot_env_add_cells; + + return nvmem_layout_register(layout); +} + +static void u_boot_env_remove(struct nvmem_layout *layout) +{ + nvmem_layout_unregister(layout); +} + +static const struct of_device_id u_boot_env_of_match_table[] = { + { .compatible = "u-boot,env", .data = (void *)U_BOOT_FORMAT_SINGLE, }, + { .compatible = "u-boot,env-redundant-bool", .data = (void *)U_BOOT_FORMAT_REDUNDANT, }, + { .compatible = "u-boot,env-redundant-count", .data = (void *)U_BOOT_FORMAT_REDUNDANT, }, + { .compatible = "brcm,env", .data = (void *)U_BOOT_FORMAT_BROADCOM, }, + {}, +}; + +static struct nvmem_layout_driver u_boot_env_layout = { + .driver = { + .name = "u-boot-env-layout", + .of_match_table = u_boot_env_of_match_table, + }, + .probe = u_boot_env_probe, + .remove = u_boot_env_remove, +}; +module_nvmem_layout_driver(u_boot_env_layout); + +MODULE_AUTHOR("Rafał Miłecki"); +MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(of, u_boot_env_of_match_table); diff --git a/drivers/nvmem/layouts/u-boot-env.h b/drivers/nvmem/layouts/u-boot-env.h new file mode 100644 index 000000000000..dd5f280ac047 --- /dev/null +++ b/drivers/nvmem/layouts/u-boot-env.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _LINUX_NVMEM_LAYOUTS_U_BOOT_ENV_H +#define _LINUX_NVMEM_LAYOUTS_U_BOOT_ENV_H + +enum u_boot_env_format { + U_BOOT_FORMAT_SINGLE, + U_BOOT_FORMAT_REDUNDANT, + U_BOOT_FORMAT_BROADCOM, +}; + +int u_boot_env_parse(struct device *dev, struct nvmem_device *nvmem, + enum u_boot_env_format format); + +#endif /* ifndef _LINUX_NVMEM_LAYOUTS_U_BOOT_ENV_H */ diff --git a/drivers/nvmem/u-boot-env.c b/drivers/nvmem/u-boot-env.c index 936e39b20b38..ced414fc9e60 100644 --- a/drivers/nvmem/u-boot-env.c +++ b/drivers/nvmem/u-boot-env.c @@ -3,23 +3,15 @@ * Copyright (C) 2022 Rafał Miłecki */ -#include -#include -#include #include #include #include -#include #include #include #include #include -enum u_boot_env_format { - U_BOOT_FORMAT_SINGLE, - U_BOOT_FORMAT_REDUNDANT, - U_BOOT_FORMAT_BROADCOM, -}; +#include "layouts/u-boot-env.h" struct u_boot_env { struct device *dev; @@ -29,24 +21,6 @@ struct u_boot_env { struct mtd_info *mtd; }; -struct u_boot_env_image_single { - __le32 crc32; - uint8_t data[]; -} __packed; - -struct u_boot_env_image_redundant { - __le32 crc32; - u8 mark; - uint8_t data[]; -} __packed; - -struct u_boot_env_image_broadcom { - __le32 magic; - __le32 len; - __le32 crc32; - DECLARE_FLEX_ARRAY(uint8_t, data); -} __packed; - static int u_boot_env_read(void *context, unsigned int offset, void *val, size_t bytes) { @@ -69,134 +43,6 @@ static int u_boot_env_read(void *context, unsigned int offset, void *val, return 0; } -static int u_boot_env_read_post_process_ethaddr(void *context, const char *id, int index, - unsigned int offset, void *buf, size_t bytes) -{ - u8 mac[ETH_ALEN]; - - if (bytes != 3 * ETH_ALEN - 1) - return -EINVAL; - - if (!mac_pton(buf, mac)) - return -EINVAL; - - if (index) - eth_addr_add(mac, index); - - ether_addr_copy(buf, mac); - - return 0; -} - -static int u_boot_env_add_cells(struct u_boot_env *priv, uint8_t *buf, - size_t data_offset, size_t data_len) -{ - struct nvmem_device *nvmem = priv->nvmem; - struct device *dev = priv->dev; - char *data = buf + data_offset; - char *var, *value, *eq; - - for (var = data; - var < data + data_len && *var; - var = value + strlen(value) + 1) { - struct nvmem_cell_info info = {}; - - eq = strchr(var, '='); - if (!eq) - break; - *eq = '\0'; - value = eq + 1; - - info.name = devm_kstrdup(dev, var, GFP_KERNEL); - if (!info.name) - return -ENOMEM; - info.offset = data_offset + value - data; - info.bytes = strlen(value); - info.np = of_get_child_by_name(dev->of_node, info.name); - if (!strcmp(var, "ethaddr")) { - info.raw_len = strlen(value); - info.bytes = ETH_ALEN; - info.read_post_process = u_boot_env_read_post_process_ethaddr; - } - - nvmem_add_one_cell(nvmem, &info); - } - - return 0; -} - -static int u_boot_env_parse(struct u_boot_env *priv) -{ - struct nvmem_device *nvmem = priv->nvmem; - struct device *dev = priv->dev; - size_t crc32_data_offset; - size_t crc32_data_len; - size_t crc32_offset; - __le32 *crc32_addr; - size_t data_offset; - size_t data_len; - size_t dev_size; - uint32_t crc32; - uint32_t calc; - uint8_t *buf; - int bytes; - int err; - - dev_size = nvmem_dev_size(nvmem); - - buf = kzalloc(dev_size, GFP_KERNEL); - if (!buf) { - err = -ENOMEM; - goto err_out; - } - - bytes = nvmem_device_read(nvmem, 0, dev_size, buf); - if (bytes < 0) { - err = bytes; - goto err_kfree; - } else if (bytes != dev_size) { - err = -EIO; - goto err_kfree; - } - - switch (priv->format) { - case U_BOOT_FORMAT_SINGLE: - crc32_offset = offsetof(struct u_boot_env_image_single, crc32); - crc32_data_offset = offsetof(struct u_boot_env_image_single, data); - data_offset = offsetof(struct u_boot_env_image_single, data); - break; - case U_BOOT_FORMAT_REDUNDANT: - crc32_offset = offsetof(struct u_boot_env_image_redundant, crc32); - crc32_data_offset = offsetof(struct u_boot_env_image_redundant, data); - data_offset = offsetof(struct u_boot_env_image_redundant, data); - break; - case U_BOOT_FORMAT_BROADCOM: - crc32_offset = offsetof(struct u_boot_env_image_broadcom, crc32); - crc32_data_offset = offsetof(struct u_boot_env_image_broadcom, data); - data_offset = offsetof(struct u_boot_env_image_broadcom, data); - break; - } - crc32_addr = (__le32 *)(buf + crc32_offset); - crc32 = le32_to_cpu(*crc32_addr); - crc32_data_len = dev_size - crc32_data_offset; - data_len = dev_size - data_offset; - - calc = crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L; - if (calc != crc32) { - dev_err(dev, "Invalid calculated CRC32: 0x%08x (expected: 0x%08x)\n", calc, crc32); - err = -EINVAL; - goto err_kfree; - } - - buf[dev_size - 1] = '\0'; - err = u_boot_env_add_cells(priv, buf, data_offset, data_len); - -err_kfree: - kfree(buf); -err_out: - return err; -} - static int u_boot_env_probe(struct platform_device *pdev) { struct nvmem_config config = { @@ -228,7 +74,7 @@ static int u_boot_env_probe(struct platform_device *pdev) if (IS_ERR(priv->nvmem)) return PTR_ERR(priv->nvmem); - return u_boot_env_parse(priv); + return u_boot_env_parse(dev, priv->nvmem, priv->format); } static const struct of_device_id u_boot_env_of_match_table[] = {