Received: by 10.223.176.46 with SMTP id f43csp1472266wra; Wed, 24 Jan 2018 17:44:16 -0800 (PST) X-Google-Smtp-Source: AH8x225ZL9XB2SYJEZwtV/zHToqvyUmTo7BMcMP7BQVoduM1B/XSa5o17PtIfELk7OJ8GTboWSmQ X-Received: by 10.98.63.214 with SMTP id z83mr14357740pfj.95.1516844656724; Wed, 24 Jan 2018 17:44:16 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1516844656; cv=none; d=google.com; s=arc-20160816; b=o6Q25R+q3S6yMCRPMg79PkWrPyrdqko16DUmWQu5E9Nx9HydklXrhrY43fbg7LT9k8 YG96MAh0B8Mru6eKcoo6/HttxGp88y+hNbfCBxocVGB/T9BZ3xOx8LtcNdrXvov7KT7S eTbgaednccmrmf9Ps2ZcILy2ngIAsuxmwt21V1oOM2NYGLRPb9ZZNCEibwPfVz5dRIWM gXMUDkJn3bRiEyQo6LyMB8IwnycvTFlk5i7/AMLlnPdu+LJlFQx9hZQIyVOuSp4g/PyK 6MkHA1Q0mOq2aGpS+kpvS5tbneFSx9/XszdfBulLejOYkHETdApjYpgCRcdvbQiW3/JS IOGQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:dkim-signature :arc-authentication-results; bh=P5MpKD9o5HrxhX+dbocMa481noUdOZgqgV28wOlesmc=; b=lGp2MNvYU9NEFRgeklZMI+P9bv7hsIoHtdLdN4sXU/L2M1ixGBPCZHHrKTCf+/ooFk fQNsCNcyi7hWpiZU4CqXzH4nX1DFOkcyYBI0LcGeEFd4qteUiqgIvJ8Pf3FE0BvBsxww Apn/dnegR3Eo3HTqkUUwDFf05uztvMIaG1kBVSNDLyav89kp/p4g9DELj//M2Rb4LsS4 klLH+M8dsCuuRh6Apxus37UQ2l2xmwlGHhJInJ02C3mmILI0jl4Y6+r8cHB5mwyhOTr/ 6jopuYI2XOTJRXIrKnAFqULelhgU4rOPAiSeoPbjcFEuCr/M5Zf6fKu+pS0yRwYzaSa9 3cMw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@sholland.org header.s=fm1 header.b=lEwvwyhN; dkim=pass header.i=@messagingengine.com header.s=fm1 header.b=WOQEg6py; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id k1-v6si645756pld.752.2018.01.24.17.44.02; Wed, 24 Jan 2018 17:44:16 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@sholland.org header.s=fm1 header.b=lEwvwyhN; dkim=pass header.i=@messagingengine.com header.s=fm1 header.b=WOQEg6py; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752784AbeAYBmr (ORCPT + 99 others); Wed, 24 Jan 2018 20:42:47 -0500 Received: from out3-smtp.messagingengine.com ([66.111.4.27]:50471 "EHLO out3-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751257AbeAYBlZ (ORCPT ); Wed, 24 Jan 2018 20:41:25 -0500 Received: from compute5.internal (compute5.nyi.internal [10.202.2.45]) by mailout.nyi.internal (Postfix) with ESMTP id C71D222724; Wed, 24 Jan 2018 20:41:24 -0500 (EST) Received: from frontend1 ([10.202.2.160]) by compute5.internal (MEProxy); Wed, 24 Jan 2018 20:41:24 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sholland.org; h= cc:date:from:in-reply-to:message-id:references:subject:to :x-me-sender:x-me-sender:x-sasl-enc; s=fm1; bh=P5MpKD9o5HrxhX+db ocMa481noUdOZgqgV28wOlesmc=; b=lEwvwyhNd96/fI5Y/P25Ej5Z12aznobeC pAqVrh3jZGAXbxBtIeOytEYFkkHmr/FtMA2UScBR2W4Y13a8vpggU24FjWB92x34 9fUOpw28G7m11IamRG3K8jVd3+kA8JlY3juqgCa6cPOCQrTE/oLvi6waTaAooST6 QDy9Wf6A3zmIjE0CVyUbGINIrrdyDCnRsoc1CuSrhvs0ynne0Cw6e9pIYKbTiY5w LitxVfGp7Ozn1xn9d5IupEKnLYSrLrKtgIo5zQ7ifIFaIvvvNwnuE/KMBh1GRKUm 3zWFhKKWLczoWCEvWcUfykxC+N4H6jPqMVOlztaHsEAGauzZIk4YA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:date:from:in-reply-to:message-id :references:subject:to:x-me-sender:x-me-sender:x-sasl-enc; s= fm1; bh=P5MpKD9o5HrxhX+dbocMa481noUdOZgqgV28wOlesmc=; b=WOQEg6py 62BvFr08BNCjgRmKCgXgL6FEIRzhz95NIVIZgKxYIg63MtklatspjOVvMfqotzUJ UvNnDqz48rKDfSHHBRpV5klN0Pq3LdimnZ1JKSfiPisOuC+dBM6ShgXU8lDY9Acu MAcz0Eb4wrQPhVEXzncIGJUkBeTWcY2OWFLngUiyiEI5ozBKSmEbxMdqVms7dNPU IZJyB/ZW/JZ8Y6r432pUiDeO/X2tRyP5k8rceuGpR8qIe6a8m9S6S8jTcc+7czv9 tRgwfnrOvUXM22I4Ql6otSiueCnbNONjQwQrh+ihiCjA+Y2ONCdXvc69CV1GzhoY aNjTLJfCy2nYUA== X-ME-Sender: Received: from indium.zzz.sholland.net (unknown [99.198.199.144]) by mail.messagingengine.com (Postfix) with ESMTPA id 9A55B7E448; Wed, 24 Jan 2018 20:41:23 -0500 (EST) From: Samuel Holland To: linux-kernel@vger.kernel.org, Greg Kroah-Hartman Cc: coreboot@coreboot.org, Thierry Escande , Wei-Ning Huang , Julius Werner , Dmitry Torokhov , Guenter Roeck , Samuel Holland Subject: [PATCH 1/5] firmware: coreboot: Expose the coreboot table as a bus Date: Wed, 24 Jan 2018 19:41:16 -0600 Message-Id: <20180125014120.20851-2-samuel@sholland.org> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180125014120.20851-1-samuel@sholland.org> References: <20180125014120.20851-1-samuel@sholland.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This simplifies creating device drivers for hardware or information described in the coreboot table. It also avoids needing to search through the table every time a driver is loaded. Signed-off-by: Samuel Holland --- drivers/firmware/google/coreboot_table-acpi.c | 2 +- drivers/firmware/google/coreboot_table-of.c | 2 +- drivers/firmware/google/coreboot_table.c | 121 ++++++++++++++++++++++++-- drivers/firmware/google/coreboot_table.h | 49 +++++++++-- 4 files changed, 156 insertions(+), 18 deletions(-) diff --git a/drivers/firmware/google/coreboot_table-acpi.c b/drivers/firmware/google/coreboot_table-acpi.c index fb98db2d20e2..77197fe3d42f 100644 --- a/drivers/firmware/google/coreboot_table-acpi.c +++ b/drivers/firmware/google/coreboot_table-acpi.c @@ -53,7 +53,7 @@ static int coreboot_table_acpi_probe(struct platform_device *pdev) if (!ptr) return -ENOMEM; - return coreboot_table_init(ptr); + return coreboot_table_init(&pdev->dev, ptr); } static int coreboot_table_acpi_remove(struct platform_device *pdev) diff --git a/drivers/firmware/google/coreboot_table-of.c b/drivers/firmware/google/coreboot_table-of.c index 727acdc83e83..f15bf404c579 100644 --- a/drivers/firmware/google/coreboot_table-of.c +++ b/drivers/firmware/google/coreboot_table-of.c @@ -34,7 +34,7 @@ static int coreboot_table_of_probe(struct platform_device *pdev) if (!ptr) return -ENOMEM; - return coreboot_table_init(ptr); + return coreboot_table_init(&pdev->dev, ptr); } static int coreboot_table_of_remove(struct platform_device *pdev) diff --git a/drivers/firmware/google/coreboot_table.c b/drivers/firmware/google/coreboot_table.c index 0019d3ec18dd..04fc08e81744 100644 --- a/drivers/firmware/google/coreboot_table.c +++ b/drivers/firmware/google/coreboot_table.c @@ -4,6 +4,7 @@ * Module providing coreboot table access. * * Copyright 2017 Google Inc. + * Copyright 2017 Samuel Holland * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License v2.0 as published by @@ -15,21 +16,87 @@ * GNU General Public License for more details. */ +#include #include #include #include #include #include +#include #include "coreboot_table.h" -struct coreboot_table_entry { - u32 tag; - u32 size; -}; +#define CB_DEV(d) container_of(d, struct coreboot_device, dev) +#define CB_DRV(d) container_of(d, struct coreboot_driver, drv) static struct coreboot_table_header __iomem *ptr_header; +static int coreboot_bus_match(struct device *dev, struct device_driver *drv) +{ + struct coreboot_device *device = CB_DEV(dev); + struct coreboot_driver *driver = CB_DRV(drv); + + return device->entry.tag == driver->tag; +} + +static int coreboot_bus_probe(struct device *dev) +{ + int ret = -ENODEV; + struct coreboot_device *device = CB_DEV(dev); + struct coreboot_driver *driver = CB_DRV(dev->driver); + + if (driver->probe) + ret = driver->probe(device); + + return ret; +} + +static int coreboot_bus_remove(struct device *dev) +{ + int ret = 0; + struct coreboot_device *device = CB_DEV(dev); + struct coreboot_driver *driver = CB_DRV(dev->driver); + + if (driver->remove) + ret = driver->remove(device); + + return ret; +} + +static struct bus_type coreboot_bus_type = { + .name = "coreboot", + .match = coreboot_bus_match, + .probe = coreboot_bus_probe, + .remove = coreboot_bus_remove, +}; + +static int __init coreboot_bus_init(void) +{ + return bus_register(&coreboot_bus_type); +} +module_init(coreboot_bus_init); + +static void coreboot_device_release(struct device *dev) +{ + struct coreboot_device *device = CB_DEV(dev); + + kfree(device); +} + +int coreboot_driver_register(struct coreboot_driver *driver) +{ + driver->drv.bus = &coreboot_bus_type; + + return driver_register(&driver->drv); +} +EXPORT_SYMBOL(coreboot_driver_register); + +void coreboot_driver_unregister(struct coreboot_driver *driver) +{ + driver_unregister(&driver->drv); +} +EXPORT_SYMBOL(coreboot_driver_unregister); + /* * This function parses the coreboot table for an entry that contains the base * address of the given entry tag. The coreboot table consists of a header @@ -73,18 +140,58 @@ int coreboot_table_find(int tag, void *data, size_t data_size) } EXPORT_SYMBOL(coreboot_table_find); -int coreboot_table_init(void __iomem *ptr) +int coreboot_table_init(struct device *dev, void __iomem *ptr) { + int i, ret; + void *ptr_entry; + struct coreboot_device *device; + struct coreboot_table_entry entry; + struct coreboot_table_header header; + ptr_header = ptr; + memcpy_fromio(&header, ptr_header, sizeof(header)); - return 0; + if (strncmp(header.signature, "LBIO", sizeof(header.signature))) { + pr_warn("coreboot_table: coreboot table missing or corrupt!\n"); + return -ENODEV; + } + + ptr_entry = (void *)ptr_header + header.header_bytes; + for (i = 0; i < header.table_entries; i++) { + memcpy_fromio(&entry, ptr_entry, sizeof(entry)); + + device = kzalloc(sizeof(struct device) + entry.size, GFP_KERNEL); + if (!device) { + ret = -ENOMEM; + break; + } + + dev_set_name(&device->dev, "coreboot%d", i); + device->dev.parent = dev; + device->dev.bus = &coreboot_bus_type; + device->dev.release = coreboot_device_release; + memcpy_fromio(&device->entry, ptr_entry, entry.size); + + ret = device_register(&device->dev); + if (ret) { + put_device(&device->dev); + break; + } + + ptr_entry += entry.size; + } + + return ret; } EXPORT_SYMBOL(coreboot_table_init); int coreboot_table_exit(void) { - if (ptr_header) + if (ptr_header) { + bus_unregister(&coreboot_bus_type); iounmap(ptr_header); + ptr_header = NULL; + } return 0; } diff --git a/drivers/firmware/google/coreboot_table.h b/drivers/firmware/google/coreboot_table.h index 6eff1ae0c5d3..88e6a1c06028 100644 --- a/drivers/firmware/google/coreboot_table.h +++ b/drivers/firmware/google/coreboot_table.h @@ -4,6 +4,7 @@ * Internal header for coreboot table access. * * Copyright 2017 Google Inc. + * Copyright 2017 Samuel Holland * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License v2.0 as published by @@ -20,14 +21,6 @@ #include -/* List of coreboot entry structures that is used */ -struct lb_cbmem_ref { - uint32_t tag; - uint32_t size; - - uint64_t cbmem_addr; -}; - /* Coreboot table header structure */ struct coreboot_table_header { char signature[4]; @@ -38,11 +31,49 @@ struct coreboot_table_header { u32 table_entries; }; +/* List of coreboot entry structures that is used */ +/* Generic */ +struct coreboot_table_entry { + u32 tag; + u32 size; +}; + +/* Points to a CBMEM entry */ +struct lb_cbmem_ref { + u32 tag; + u32 size; + + u64 cbmem_addr; +}; + +/* A device, additionally with information from coreboot. */ +struct coreboot_device { + struct device dev; + union { + struct coreboot_table_entry entry; + struct lb_cbmem_ref cbmem_ref; + }; +}; + +/* A driver for handling devices described in coreboot tables. */ +struct coreboot_driver { + int (*probe)(struct coreboot_device *); + int (*remove)(struct coreboot_device *); + struct device_driver drv; + u32 tag; +}; + +/* Register a driver that uses the data from a coreboot table. */ +int coreboot_driver_register(struct coreboot_driver *driver); + +/* Unregister a driver that uses the data from a coreboot table. */ +void coreboot_driver_unregister(struct coreboot_driver *driver); + /* Retrieve coreboot table entry with tag *tag* and copy it to data */ int coreboot_table_find(int tag, void *data, size_t data_size); /* Initialize coreboot table module given a pointer to iomem */ -int coreboot_table_init(void __iomem *ptr); +int coreboot_table_init(struct device *dev, void __iomem *ptr); /* Cleanup coreboot table module */ int coreboot_table_exit(void); -- 2.13.6