From patchwork Fri Apr 29 09:46:09 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Lombard X-Patchwork-Id: 1624088 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=ibm.com header.i=@ibm.com header.a=rsa-sha256 header.s=pp1 header.b=MrOE+fft; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ozlabs.org (client-ip=112.213.38.117; helo=lists.ozlabs.org; envelope-from=skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org; receiver=) Received: from lists.ozlabs.org (lists.ozlabs.org [112.213.38.117]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4KqSL51g6yz9sFN for ; Fri, 29 Apr 2022 19:46:20 +1000 (AEST) Received: from boromir.ozlabs.org (localhost [IPv6:::1]) by lists.ozlabs.org (Postfix) with ESMTP id 4KqSL43z56z3bd5 for ; Fri, 29 Apr 2022 19:46:20 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=ibm.com header.i=@ibm.com header.a=rsa-sha256 header.s=pp1 header.b=MrOE+fft; dkim-atps=neutral X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=none (no SPF record) smtp.mailfrom=linux.vnet.ibm.com (client-ip=148.163.156.1; helo=mx0a-001b2d01.pphosted.com; envelope-from=clombard@linux.vnet.ibm.com; receiver=) Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=ibm.com header.i=@ibm.com header.a=rsa-sha256 header.s=pp1 header.b=MrOE+fft; dkim-atps=neutral Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 4KqSL148Xbz3bWd for ; Fri, 29 Apr 2022 19:46:17 +1000 (AEST) Received: from pps.filterd (m0098404.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 23T7Whj4004259 for ; Fri, 29 Apr 2022 09:46:15 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=0cf4WhPfSh8lbONTXAlWEWBNwwbLRRap++ulNrKIMsA=; b=MrOE+fftmyskFG5wBtjdKPK6J6SBdykQZEeosy0bN531SLFEdBPQPOLfdCK1pUIxuxtM 5Colx4xF0/kFk1Qgh3W1V7yIPABXqoIXhVRI0z/DjsVdHe4Cr9jTxODBlKhMaDUVbrRI Txy70k1t8GpriYstx3LOv2ZPI8h+Es94YsfHFTCcsXX/XBWtWnsDFKnalEjNydQq4xBC BV3ds5VfepBq1WR1DU38dSKvwaub1v97NFsHxr03iD8JRrcvhlm4yD6jxyFUYuSArYL+ u8RfrWmZ49Y23RmVCIMkJCneYJ1rIV+C4/KU/+MRHx1qm5lJhhmZ2Y/hcS3lZy6cWbWp NQ== Received: from ppma03ams.nl.ibm.com (62.31.33a9.ip4.static.sl-reverse.com [169.51.49.98]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 3fqt9e82w2-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Fri, 29 Apr 2022 09:46:14 +0000 Received: from pps.filterd (ppma03ams.nl.ibm.com [127.0.0.1]) by ppma03ams.nl.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 23T9dKap000646 for ; Fri, 29 Apr 2022 09:46:12 GMT Received: from b06cxnps4074.portsmouth.uk.ibm.com (d06relay11.portsmouth.uk.ibm.com [9.149.109.196]) by ppma03ams.nl.ibm.com with ESMTP id 3fm9390vx3-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Fri, 29 Apr 2022 09:46:12 +0000 Received: from d06av25.portsmouth.uk.ibm.com (d06av25.portsmouth.uk.ibm.com [9.149.105.61]) by b06cxnps4074.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 23T9kASJ24510744 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Fri, 29 Apr 2022 09:46:10 GMT Received: from d06av25.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 71F2911C050 for ; Fri, 29 Apr 2022 09:46:10 +0000 (GMT) Received: from d06av25.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 4605511C054 for ; Fri, 29 Apr 2022 09:46:10 +0000 (GMT) Received: from li-ed209401-43e8-11cb-8043-c0c0b85d70f7.ibm.com.com (unknown [9.171.83.222]) by d06av25.portsmouth.uk.ibm.com (Postfix) with ESMTP for ; Fri, 29 Apr 2022 09:46:10 +0000 (GMT) From: Christophe Lombard To: skiboot@lists.ozlabs.org Date: Fri, 29 Apr 2022 11:46:09 +0200 Message-Id: <20220429094609.72733-3-clombard@linux.vnet.ibm.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220429094609.72733-1-clombard@linux.vnet.ibm.com> References: <20220429094609.72733-1-clombard@linux.vnet.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-GUID: 04_ej1hz5ybUD9sOwijoDVpKbyEgaUSW X-Proofpoint-ORIG-GUID: 04_ej1hz5ybUD9sOwijoDVpKbyEgaUSW X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.858,Hydra:6.0.486,FMLib:17.11.64.514 definitions=2022-04-29_05,2022-04-28_01,2022-02-23_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 phishscore=0 mlxscore=0 suspectscore=0 priorityscore=1501 spamscore=0 mlxlogscore=894 adultscore=0 lowpriorityscore=0 impostorscore=0 clxscore=1015 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2202240000 definitions=main-2204290054 Subject: [Skiboot] [PATCH V3 2/2] core/pldm: Register PLDM as a blocklevel device X-BeenThere: skiboot@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Mailing list for skiboot development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Skiboot" In the same way that ipmi-hiomap implements the PNOR access control protocol, this patch allows to "virtualize" the content of a BMC flash based on lid files. Previously, flash PNOR partitions were viewed this way: partitionXX=NAME, start address, end address, flags The content of each partition is now stored in a lid file. In order to continue to use the libflash library, we manually fill in the contents of a fake flash header when accessing offset 0. This reproduces the behavior via ipmi-hiomap of reading the flash header on the BMC. For the reading and writing of BMC lids files, we convert the virtual addresses of these 'fake' partitions by identifying: lid id. Signed-off-by: Christophe Lombard --- core/pldm/pldm-lid-files.c | 226 +++++++++++++++++++++++++++++++++++++ include/pldm.h | 5 + 2 files changed, 231 insertions(+) diff --git a/core/pldm/pldm-lid-files.c b/core/pldm/pldm-lid-files.c index 11e2f9e2..e8122268 100644 --- a/core/pldm/pldm-lid-files.c +++ b/core/pldm/pldm-lid-files.c @@ -25,6 +25,14 @@ struct pldm_lid { static LIST_HEAD(lid_files); +struct pldm_ctx_data { + /* Members protected by the blocklevel lock */ + struct blocklevel_device bl; + uint32_t total_size; + uint32_t erase_granule; + struct lock lock; +}; + #define MEGABYTE (1024*1024) /* @@ -34,6 +42,17 @@ static LIST_HEAD(lid_files); */ #define VMM_SIZE_RESERVED_PER_SECTION (16 * MEGABYTE) +/* The version of this partition implementation */ +#define FFS_VERSION_1 1 + +/* Magic number for the partition header (ASCII 'PART') */ +#define FFS_MAGIC 0x50415254 + +/* pid of logical partitions/containers */ +#define FFS_PID_TOPLEVEL 0xFFFFFFFF + +#define ERASE_GRANULE_DEF 0x1000 + /* * Print the attributes of lid files. */ @@ -143,8 +162,195 @@ out: return rc; } +static uint32_t checksum(void *data, size_t size) +{ + uint32_t i, csum = 0; + + for (i = csum = 0; i < (size/4); i++) + csum ^= ((uint32_t *)data)[i]; + return csum; +} + +/* Helper functions for typesafety and size safety */ +static uint32_t hdr_checksum(struct __ffs_hdr *hdr) +{ + return checksum(hdr, sizeof(struct __ffs_hdr)); +} + +static uint32_t entry_checksum(struct __ffs_entry *ent) +{ + return checksum(ent, sizeof(struct __ffs_entry)); +} + +/* + * Fill __ffs structures in order to return a 'fake' header flash + */ +static int lid_ids_to_header_flash(void *buf, uint64_t len) +{ + struct __ffs_entry *entry; + struct __ffs_hdr *raw_hdr; + struct pldm_lid *lid = NULL; + uint32_t count, part_id, i; + uint32_t block_size; + + /* number of lid files */ + count = get_lids_count(); + + /* last member of struct __ffs_hdr is a flexible array member */ + raw_hdr = zalloc(sizeof(struct __ffs_hdr) + (count * sizeof(struct __ffs_entry))); + + /* complete header flash */ + block_size = sizeof(struct __ffs_hdr) + (sizeof(struct __ffs_entry) * count); + block_size = ALIGN_UP(block_size, 1 << 13); + + raw_hdr->magic = cpu_to_be32(FFS_MAGIC); + raw_hdr->version = cpu_to_be32(FFS_VERSION_1); + raw_hdr->size = cpu_to_be32(0x1); + raw_hdr->entry_size = cpu_to_be32(sizeof(struct __ffs_entry)); + raw_hdr->entry_count = cpu_to_be32(count); + raw_hdr->block_size = cpu_to_be32(block_size); + raw_hdr->block_count = cpu_to_be32(0x4000); + raw_hdr->checksum = hdr_checksum(raw_hdr); + + lid = list_top(&lid_files, struct pldm_lid, list); + part_id = 1; + + for (i = 0; i < count; i++) { + entry = &raw_hdr->entries[i]; + + strcpy(entry->name, lid->name); + entry->base = cpu_to_be32(lid->start / block_size); + entry->size = cpu_to_be32(lid->length / block_size); + entry->pid = cpu_to_be32(FFS_PID_TOPLEVEL); + entry->id = cpu_to_be32(part_id); + entry->type = cpu_to_be32(0x1); + entry->flags = cpu_to_be32(0x0); + entry->actual = cpu_to_be32(lid->length); + entry->checksum = entry_checksum(entry); + + lid = list_next(&lid_files, lid, list); + part_id++; + } + + memcpy(buf, raw_hdr, len); + + return OPAL_SUCCESS; +} + +/* + * Search lid member from the virtual address. + */ +static struct pldm_lid *vaddr_to_lid_id(uint64_t pos) +{ + struct pldm_lid *lid = NULL; + + list_for_each(&lid_files, lid, list) + if ((pos >= lid->start) && (pos < lid->start + VMM_SIZE_RESERVED_PER_SECTION)) + break; + + return lid; +} + +static int lid_files_read(struct blocklevel_device *bl __unused, + uint64_t pos, void *buf, uint64_t len) +{ + struct pldm_lid *lid; + uint64_t offset; + int rc = 0; + + /* LPC is only 32bit */ + if (pos > UINT_MAX || len > UINT_MAX) + return FLASH_ERR_PARM_ERROR; + + prlog(PR_TRACE, "lid files read at 0x%llx for 0x%llx\n", pos, len); + + if (pos == 0) { + /* return a 'fake' header flash */ + rc = lid_ids_to_header_flash(buf, len); + } else { + /* convert offset to lid id */ + lid = vaddr_to_lid_id(pos); + if (!lid) + return OPAL_PARAMETER; + + /* read lid file */ + offset = pos - lid->start; + rc = pldm_file_io_read_file(lid->handle, lid->length, buf, offset, len); + } + + return rc; +} + +static int lid_files_write(struct blocklevel_device *bl __unused, + uint64_t pos, const void *buf, uint64_t len) +{ + struct pldm_lid *lid; + uint64_t offset; + + /* LPC is only 32bit */ + if (pos > UINT_MAX || len > UINT_MAX) + return FLASH_ERR_PARM_ERROR; + + prlog(PR_TRACE, "lid files write at 0x%llx for 0x%llx\n", pos, len); + + /* convert offset to lid id */ + lid = vaddr_to_lid_id(pos); + if (!lid) + return OPAL_PARAMETER; + + /* write lid file */ + offset = pos - lid->start; + return pldm_file_io_write_file(lid->handle, buf, offset, len); +} + +static int lid_files_erase(struct blocklevel_device *bl __unused, + uint64_t pos, uint64_t len) +{ + + prlog(PR_TRACE, "lid files erase at 0x%llx for 0x%llx\n", pos, len); + return OPAL_UNSUPPORTED; +} + +static int get_lid_files_info(struct blocklevel_device *bl, + const char **name, uint64_t *total_size, + uint32_t *erase_granule) +{ + struct pldm_ctx_data *ctx; + + ctx = container_of(bl, struct pldm_ctx_data, bl); + ctx->bl.erase_mask = ctx->erase_granule - 1; + + if (name) + *name = NULL; + if (total_size) + *total_size = ctx->total_size; + if (erase_granule) + *erase_granule = ctx->erase_granule; + + return OPAL_SUCCESS; +} + +bool pldm_lid_files_exit(struct blocklevel_device *bl) +{ + struct pldm_ctx_data *ctx; + struct pldm_lid *lid; + bool status = true; + + if (bl) { + ctx = container_of(bl, struct pldm_ctx_data, bl); + free(ctx); + } + + /* free all lid entries */ + list_for_each(&lid_files, lid, list) + free(lid); + + return status; +} + int pldm_lid_files_init(struct blocklevel_device **bl) { + struct pldm_ctx_data *ctx; uint32_t lid_files_count; int rc; @@ -153,6 +359,18 @@ int pldm_lid_files_init(struct blocklevel_device **bl) *bl = NULL; + ctx = zalloc(sizeof(struct pldm_ctx_data)); + if (!ctx) + return FLASH_ERR_MALLOC_FAILED; + + init_lock(&ctx->lock); + + ctx->bl.read = &lid_files_read; + ctx->bl.write = &lid_files_write; + ctx->bl.erase = &lid_files_erase; + ctx->bl.get_info = &get_lid_files_info; + ctx->bl.exit = &pldm_lid_files_exit; + /* convert lid ids data to pnor structure */ rc = lid_ids_to_vaddr_mapping(); if (rc) @@ -163,8 +381,16 @@ int pldm_lid_files_init(struct blocklevel_device **bl) prlog(PR_NOTICE, "Number of lid files: %d\n", lid_files_count); print_lid_files_attr(); + ctx->total_size = lid_files_count * VMM_SIZE_RESERVED_PER_SECTION; + ctx->erase_granule = ERASE_GRANULE_DEF; + + ctx->bl.keep_alive = 0; + + *bl = &(ctx->bl); + return OPAL_SUCCESS; err: + free(ctx); return rc; } diff --git a/include/pldm.h b/include/pldm.h index 9735261d..5ad724af 100644 --- a/include/pldm.h +++ b/include/pldm.h @@ -37,4 +37,9 @@ int pldm_fru_dt_add_bmc_version(void); */ int pldm_lid_files_init(struct blocklevel_device **bl); +/** + * Remove lid ids data + */ +bool pldm_lid_files_exit(struct blocklevel_device *bl); + #endif /* __PLDM_H__ */