From patchwork Fri Apr 8 09:44:49 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 65366 Delivered-To: patch@linaro.org Received: by 10.112.43.237 with SMTP id z13csp569096lbl; Fri, 8 Apr 2016 02:45:25 -0700 (PDT) X-Received: by 10.98.42.150 with SMTP id q144mr11418871pfq.73.1460108724059; Fri, 08 Apr 2016 02:45:24 -0700 (PDT) Return-Path: Received: from ml01.01.org (ml01.01.org. [2001:19d0:306:5::1]) by mx.google.com with ESMTPS id yo8si8842pac.27.2016.04.08.02.45.23 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 08 Apr 2016 02:45:24 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of edk2-devel-bounces@lists.01.org designates 2001:19d0:306:5::1 as permitted sender) client-ip=2001:19d0:306:5::1; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org; spf=pass (google.com: best guess record for domain of edk2-devel-bounces@lists.01.org designates 2001:19d0:306:5::1 as permitted sender) smtp.mailfrom=edk2-devel-bounces@lists.01.org; dmarc=fail (p=NONE dis=NONE) header.from=linaro.org Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 98C691A1EF0; Fri, 8 Apr 2016 02:45:23 -0700 (PDT) X-Original-To: edk2-devel@lists.01.org Delivered-To: edk2-devel@lists.01.org Received: from mail-wm0-x234.google.com (mail-wm0-x234.google.com [IPv6:2a00:1450:400c:c09::234]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id A8D531A1EF0 for ; Fri, 8 Apr 2016 02:45:21 -0700 (PDT) Received: by mail-wm0-x234.google.com with SMTP id u206so15468822wme.1 for ; Fri, 08 Apr 2016 02:45:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=OAXFq/xTCm9ApIx/MML3RxO5UD3i5TFT7fSqCg8W8x4=; b=T3/Vxbb9roT+LrOWM5C97broV5vHbTHdt3iyxAhALV30M7LLRLaVZQEmtwMIeNEBv0 Y60QDveRRfvrk6fVHTZxRvVwrGIab7jS0X5WKqeGcFB/DaLlmwasRjHC6qZuFrQXPGUG OE234UwYzUEFR7bT2aRkfpkBic3AXDn6fZgLs= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=OAXFq/xTCm9ApIx/MML3RxO5UD3i5TFT7fSqCg8W8x4=; b=YnTuDzzlOYOI2KpdGS7a7BHiOW2hMvM+Pif8HiozY91nvsH+FpjzP+ggTvXqDsA9UC V3e/Dk4lSLTMnNLKoqUWgSlDPFRAHQFdqwIV5maK8Yn7MmGUrD7P8xv+5+UJNqZiy+el 9hW8FgqugkY9/6+Q78FJ4e/JUvupmsTsFK/nliiHLGmwuZqAFbu3M4JEa5tHA8VRMiiG ge2DVirhubpklX1khdWPRZvsfQgj9P+u/mzlH455XezlS5NC9M7GPO9mka5KaAMYR7xf FhMwmbyCTBfapKEf8hfKIuk8LFkz9HxWCDGXH/0vQ0pw0dUDk+5kazaNOlNRZFZMAS3D 7tXQ== X-Gm-Message-State: AD7BkJLouw0MDo5DgYkgUxyoqKHZ13d4t/wLTi1kUxzAAleGuTRU1WT3VcOFbS38+E9fmP1M X-Received: by 10.194.204.68 with SMTP id kw4mr8430597wjc.75.1460108720346; Fri, 08 Apr 2016 02:45:20 -0700 (PDT) Received: from localhost.localdomain ([195.55.142.58]) by smtp.gmail.com with ESMTPSA id s10sm9710681wjp.3.2016.04.08.02.45.18 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 08 Apr 2016 02:45:19 -0700 (PDT) From: Ard Biesheuvel To: edk2-devel@lists.01.org, lersek@redhat.com Date: Fri, 8 Apr 2016 11:44:49 +0200 Message-Id: <1460108711-12122-3-git-send-email-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 2.5.0 In-Reply-To: <1460108711-12122-1-git-send-email-ard.biesheuvel@linaro.org> References: <1460108711-12122-1-git-send-email-ard.biesheuvel@linaro.org> Subject: [edk2] [PATCH v2 02/24] ArmVirtPkg/FdtClientDxe: implement new driver X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Ard Biesheuvel MIME-Version: 1.0 Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" This implements a new DXE driver FdtClientDxe to produce the FDT client protocol based on a device tree image supplied by the virt host. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ard Biesheuvel --- ArmVirtPkg/FdtClientDxe/FdtClientDxe.c | 256 ++++++++++++++++++++ ArmVirtPkg/FdtClientDxe/FdtClientDxe.inf | 48 ++++ 2 files changed, 304 insertions(+) -- 2.5.0 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel Reviewed-by: Laszlo Ersek diff --git a/ArmVirtPkg/FdtClientDxe/FdtClientDxe.c b/ArmVirtPkg/FdtClientDxe/FdtClientDxe.c new file mode 100644 index 000000000000..9c589e620cb4 --- /dev/null +++ b/ArmVirtPkg/FdtClientDxe/FdtClientDxe.c @@ -0,0 +1,256 @@ +/** @file +* FDT client driver +* +* Copyright (c) 2016, Linaro Ltd. All rights reserved.
+* +* This program and the accompanying materials are +* licensed and made available under the terms and conditions of the BSD License +* which accompanies this distribution. The full text of the license may be found at +* http://opensource.org/licenses/bsd-license.php +* +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +* +**/ + +#include +#include +#include +#include +#include +#include + +#include + +#include + +STATIC VOID *mDeviceTreeBase; + +STATIC +EFI_STATUS +GetNodeProperty ( + IN FDT_CLIENT_PROTOCOL *This, + IN INT32 Node, + IN CONST CHAR8 *PropertyName, + OUT CONST VOID **Prop, + OUT UINT32 *PropSize OPTIONAL + ) +{ + INT32 Len; + + ASSERT (mDeviceTreeBase != NULL); + ASSERT (Prop != NULL); + + *Prop = fdt_getprop (mDeviceTreeBase, Node, PropertyName, &Len); + if (*Prop == NULL) { + return EFI_NOT_FOUND; + } + + if (PropSize != NULL) { + *PropSize = Len; + } + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +SetNodeProperty ( + IN FDT_CLIENT_PROTOCOL *This, + IN INT32 Node, + IN CONST CHAR8 *PropertyName, + IN CONST VOID *Prop, + IN UINT32 PropSize + ) +{ + INT32 Ret; + + ASSERT (mDeviceTreeBase != NULL); + + Ret = fdt_setprop (mDeviceTreeBase, Node, PropertyName, Prop, PropSize); + if (Ret != 0) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +FindNextCompatibleNode ( + IN FDT_CLIENT_PROTOCOL *This, + IN CONST CHAR8 *CompatibleString, + IN INT32 PrevNode, + OUT INT32 *Node + ) +{ + INT32 Prev, Next; + CONST CHAR8 *Type, *Compatible; + INT32 Len; + + ASSERT (mDeviceTreeBase != NULL); + ASSERT (Node != NULL); + + for (Prev = PrevNode;; Prev = Next) { + Next = fdt_next_node (mDeviceTreeBase, Prev, NULL); + if (Next < 0) { + break; + } + + Type = fdt_getprop (mDeviceTreeBase, Next, "compatible", &Len); + if (Type == NULL) { + continue; + } + + // + // A 'compatible' node may contain a sequence of NUL terminated + // compatible strings so check each one + // + for (Compatible = Type; Compatible < Type + Len && *Compatible; + Compatible += 1 + AsciiStrLen (Compatible)) { + if (AsciiStrCmp (CompatibleString, Compatible) == 0) { + *Node = Next; + return EFI_SUCCESS; + } + } + } + return EFI_NOT_FOUND; +} + +STATIC +EFI_STATUS +EFIAPI +FindCompatibleNode ( + IN FDT_CLIENT_PROTOCOL *This, + IN CONST CHAR8 *CompatibleString, + OUT INT32 *Node + ) +{ + return FindNextCompatibleNode (This, CompatibleString, 0, Node); +} + +STATIC +EFI_STATUS +EFIAPI +FindCompatibleNodeProperty ( + IN FDT_CLIENT_PROTOCOL *This, + IN CONST CHAR8 *CompatibleString, + IN CONST CHAR8 *PropertyName, + OUT CONST VOID **Prop, + OUT UINT32 *PropSize OPTIONAL + ) +{ + EFI_STATUS Status; + INT32 Node; + + Status = FindCompatibleNode (This, CompatibleString, &Node); + if (EFI_ERROR (Status)) { + return Status; + } + + return GetNodeProperty (This, Node, PropertyName, Prop, PropSize); +} + +STATIC +EFI_STATUS +EFIAPI +FindCompatibleNodeReg ( + IN FDT_CLIENT_PROTOCOL *This, + IN CONST CHAR8 *CompatibleString, + OUT CONST VOID **Reg, + OUT UINT32 *RegElemSize, + OUT UINT32 *RegSize + ) +{ + EFI_STATUS Status; + + ASSERT (RegSize != NULL); + + // + // Get the 'reg' property of this node. For now, we will assume + // 8 byte quantities for base and size, respectively. + // TODO use #cells root properties instead + // + Status = FindCompatibleNodeProperty (This, CompatibleString, "reg", Reg, + RegSize); + if (EFI_ERROR (Status)) { + return Status; + } + + if ((*RegSize % 8) != 0) { + DEBUG ((EFI_D_ERROR, + "%a: '%a' compatible node has invalid 'reg' property (size == 0x%x)\n", + __FUNCTION__, CompatibleString, *RegSize)); + return EFI_NOT_FOUND; + } + + *RegElemSize = 8; + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +GetOrInsertChosenNode ( + IN FDT_CLIENT_PROTOCOL *This, + OUT INT32 *Node + ) +{ + INT32 NewNode; + + ASSERT (mDeviceTreeBase != NULL); + ASSERT (Node != NULL); + + NewNode = fdt_path_offset (mDeviceTreeBase, "/chosen"); + if (NewNode < 0) { + NewNode = fdt_add_subnode (mDeviceTreeBase, 0, "/chosen"); + } + + if (NewNode < 0) { + return EFI_OUT_OF_RESOURCES; + } + + *Node = NewNode; + + return EFI_SUCCESS; +} + +STATIC FDT_CLIENT_PROTOCOL mFdtClientProtocol = { + GetNodeProperty, + SetNodeProperty, + FindCompatibleNode, + FindNextCompatibleNode, + FindCompatibleNodeProperty, + FindCompatibleNodeReg, + GetOrInsertChosenNode, +}; + +EFI_STATUS +EFIAPI +InitializeFdtClientDxe ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + VOID *Hob; + VOID *DeviceTreeBase; + + Hob = GetFirstGuidHob (&gFdtHobGuid); + if (Hob == NULL || GET_GUID_HOB_DATA_SIZE (Hob) != sizeof (UINT64)) { + return EFI_NOT_FOUND; + } + DeviceTreeBase = (VOID *)(UINTN)*(UINT64 *)GET_GUID_HOB_DATA (Hob); + + if (fdt_check_header (DeviceTreeBase) != 0) { + DEBUG ((EFI_D_ERROR, "%a: No DTB found @ 0x%p\n", __FUNCTION__, + DeviceTreeBase)); + return EFI_NOT_FOUND; + } + + mDeviceTreeBase = DeviceTreeBase; + + DEBUG ((EFI_D_INFO, "%a: DTB @ 0x%p\n", __FUNCTION__, mDeviceTreeBase)); + + return gBS->InstallProtocolInterface (&ImageHandle, &gFdtClientProtocolGuid, + EFI_NATIVE_INTERFACE, &mFdtClientProtocol); +} diff --git a/ArmVirtPkg/FdtClientDxe/FdtClientDxe.inf b/ArmVirtPkg/FdtClientDxe/FdtClientDxe.inf new file mode 100644 index 000000000000..3647d37b02d2 --- /dev/null +++ b/ArmVirtPkg/FdtClientDxe/FdtClientDxe.inf @@ -0,0 +1,48 @@ +## @file +# FDT client driver +# +# Copyright (c) 2016, Linaro Ltd. All rights reserved.
+# +# This program and the accompanying materials are +# licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = FdtClientDxe + FILE_GUID = 9A871B00-1C16-4F61-8D2C-93B6654B5AD6 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = InitializeFdtClientDxe + +[Sources] + FdtClientDxe.c + +[Packages] + ArmVirtPkg/ArmVirtPkg.dec + EmbeddedPkg/EmbeddedPkg.dec + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + DebugLib + FdtLib + HobLib + UefiBootServicesTableLib + UefiDriverEntryPoint + +[Protocols] + gFdtClientProtocolGuid ## PRODUCES + +[Guids] + gFdtHobGuid + +[Depex] + TRUE