162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Functions corresponding to sure start object type attributes under
462306a36Sopenharmony_ci * BIOS for use with hp-bioscfg driver
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Copyright (c) 2022 HP Development Company, L.P.
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include "bioscfg.h"
1062306a36Sopenharmony_ci#include <linux/types.h>
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci/* Maximum number of log entries supported when log entry size is 16
1362306a36Sopenharmony_ci * bytes. This value is calculated by dividing 4096 (page size) by
1462306a36Sopenharmony_ci * log entry size.
1562306a36Sopenharmony_ci */
1662306a36Sopenharmony_ci#define LOG_MAX_ENTRIES		254
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci/*
1962306a36Sopenharmony_ci * Current Log entry size. This value size will change in the
2062306a36Sopenharmony_ci * future. The driver reads a total of 128 bytes for each log entry
2162306a36Sopenharmony_ci * provided by BIOS but only the first 16 bytes are used/read.
2262306a36Sopenharmony_ci */
2362306a36Sopenharmony_ci#define LOG_ENTRY_SIZE		16
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci/*
2662306a36Sopenharmony_ci * audit_log_entry_count_show - Reports the number of
2762306a36Sopenharmony_ci *				existing audit log entries available
2862306a36Sopenharmony_ci *				to be read
2962306a36Sopenharmony_ci */
3062306a36Sopenharmony_cistatic ssize_t audit_log_entry_count_show(struct kobject *kobj,
3162306a36Sopenharmony_ci					  struct kobj_attribute *attr, char *buf)
3262306a36Sopenharmony_ci{
3362306a36Sopenharmony_ci	int ret;
3462306a36Sopenharmony_ci	u32 count = 0;
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci	ret = hp_wmi_perform_query(HPWMI_SURESTART_GET_LOG_COUNT,
3762306a36Sopenharmony_ci				   HPWMI_SURESTART,
3862306a36Sopenharmony_ci				   &count, 1, sizeof(count));
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci	if (ret < 0)
4162306a36Sopenharmony_ci		return ret;
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci	return sysfs_emit(buf, "%d,%d,%d\n", count, LOG_ENTRY_SIZE,
4462306a36Sopenharmony_ci			  LOG_MAX_ENTRIES);
4562306a36Sopenharmony_ci}
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci/*
4862306a36Sopenharmony_ci * audit_log_entries_show() - Return all entries found in log file
4962306a36Sopenharmony_ci */
5062306a36Sopenharmony_cistatic ssize_t audit_log_entries_show(struct kobject *kobj,
5162306a36Sopenharmony_ci				      struct kobj_attribute *attr, char *buf)
5262306a36Sopenharmony_ci{
5362306a36Sopenharmony_ci	int ret;
5462306a36Sopenharmony_ci	int i;
5562306a36Sopenharmony_ci	u32 count = 0;
5662306a36Sopenharmony_ci	u8 audit_log_buffer[128];
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	// Get the number of event logs
5962306a36Sopenharmony_ci	ret = hp_wmi_perform_query(HPWMI_SURESTART_GET_LOG_COUNT,
6062306a36Sopenharmony_ci				   HPWMI_SURESTART,
6162306a36Sopenharmony_ci				   &count, 1, sizeof(count));
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci	if (ret < 0)
6462306a36Sopenharmony_ci		return ret;
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci	/*
6762306a36Sopenharmony_ci	 * The show() api will not work if the audit logs ever go
6862306a36Sopenharmony_ci	 * beyond 4KB
6962306a36Sopenharmony_ci	 */
7062306a36Sopenharmony_ci	if (count * LOG_ENTRY_SIZE > PAGE_SIZE)
7162306a36Sopenharmony_ci		return -EIO;
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci	/*
7462306a36Sopenharmony_ci	 * We are guaranteed the buffer is 4KB so today all the event
7562306a36Sopenharmony_ci	 * logs will fit
7662306a36Sopenharmony_ci	 */
7762306a36Sopenharmony_ci	for (i = 0; i < count; i++) {
7862306a36Sopenharmony_ci		audit_log_buffer[0] = i + 1;
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci		/*
8162306a36Sopenharmony_ci		 * read audit log entry at a time. 'buf' input value
8262306a36Sopenharmony_ci		 * provides the audit log entry to be read. On
8362306a36Sopenharmony_ci		 * input, Byte 0 = Audit Log entry number from
8462306a36Sopenharmony_ci		 * beginning (1..254)
8562306a36Sopenharmony_ci		 * Entry number 1 is the newest entry whereas the
8662306a36Sopenharmony_ci		 * highest entry number (number of entries) is the
8762306a36Sopenharmony_ci		 * oldest entry.
8862306a36Sopenharmony_ci		 */
8962306a36Sopenharmony_ci		ret = hp_wmi_perform_query(HPWMI_SURESTART_GET_LOG,
9062306a36Sopenharmony_ci					   HPWMI_SURESTART,
9162306a36Sopenharmony_ci					   audit_log_buffer, 1, 128);
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci		if (ret < 0 || (LOG_ENTRY_SIZE * i) > PAGE_SIZE) {
9462306a36Sopenharmony_ci			/*
9562306a36Sopenharmony_ci			 * Encountered a failure while reading
9662306a36Sopenharmony_ci			 * individual logs. Only a partial list of
9762306a36Sopenharmony_ci			 * audit log will be returned.
9862306a36Sopenharmony_ci			 */
9962306a36Sopenharmony_ci			break;
10062306a36Sopenharmony_ci		} else {
10162306a36Sopenharmony_ci			memcpy(buf, audit_log_buffer, LOG_ENTRY_SIZE);
10262306a36Sopenharmony_ci			buf += LOG_ENTRY_SIZE;
10362306a36Sopenharmony_ci		}
10462306a36Sopenharmony_ci	}
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	return i * LOG_ENTRY_SIZE;
10762306a36Sopenharmony_ci}
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_cistatic struct kobj_attribute sure_start_audit_log_entry_count = __ATTR_RO(audit_log_entry_count);
11062306a36Sopenharmony_cistatic struct kobj_attribute sure_start_audit_log_entries = __ATTR_RO(audit_log_entries);
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_cistatic struct attribute *sure_start_attrs[] = {
11362306a36Sopenharmony_ci	&sure_start_audit_log_entry_count.attr,
11462306a36Sopenharmony_ci	&sure_start_audit_log_entries.attr,
11562306a36Sopenharmony_ci	NULL
11662306a36Sopenharmony_ci};
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_cistatic const struct attribute_group sure_start_attr_group = {
11962306a36Sopenharmony_ci	.attrs = sure_start_attrs,
12062306a36Sopenharmony_ci};
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_civoid hp_exit_sure_start_attributes(void)
12362306a36Sopenharmony_ci{
12462306a36Sopenharmony_ci	sysfs_remove_group(bioscfg_drv.sure_start_attr_kobj,
12562306a36Sopenharmony_ci			   &sure_start_attr_group);
12662306a36Sopenharmony_ci}
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ciint hp_populate_sure_start_data(struct kobject *attr_name_kobj)
12962306a36Sopenharmony_ci{
13062306a36Sopenharmony_ci	bioscfg_drv.sure_start_attr_kobj = attr_name_kobj;
13162306a36Sopenharmony_ci	return sysfs_create_group(attr_name_kobj, &sure_start_attr_group);
13262306a36Sopenharmony_ci}
133