brintos

brintos / linux-shallow public Read only

0
0
Text · 17.3 KiB · 9f51e0f Raw
678 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * dell_rbu.c4 * Bios Update driver for Dell systems5 * Author: Dell Inc6 *         Abhay Salunke <abhay_salunke@dell.com>7 *8 * Copyright (C) 2005 Dell Inc.9 *10 * Remote BIOS Update (rbu) driver is used for updating DELL BIOS by11 * creating entries in the /sys file systems on Linux 2.6 and higher12 * kernels. The driver supports two mechanism to update the BIOS namely13 * contiguous and packetized. Both these methods still require having some14 * application to set the CMOS bit indicating the BIOS to update itself15 * after a reboot.16 *17 * Contiguous method:18 * This driver writes the incoming data in a monolithic image by allocating19 * contiguous physical pages large enough to accommodate the incoming BIOS20 * image size.21 *22 * Packetized method:23 * The driver writes the incoming packet image by allocating a new packet24 * on every time the packet data is written. This driver requires an25 * application to break the BIOS image in to fixed sized packet chunks.26 *27 * See Documentation/admin-guide/dell_rbu.rst for more info.28 */29 30#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt31 32#include <linux/init.h>33#include <linux/module.h>34#include <linux/slab.h>35#include <linux/string.h>36#include <linux/errno.h>37#include <linux/blkdev.h>38#include <linux/platform_device.h>39#include <linux/spinlock.h>40#include <linux/moduleparam.h>41#include <linux/firmware.h>42#include <linux/dma-mapping.h>43#include <asm/set_memory.h>44 45MODULE_AUTHOR("Abhay Salunke <abhay_salunke@dell.com>");46MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems");47MODULE_LICENSE("GPL");48MODULE_VERSION("3.2");49 50#define BIOS_SCAN_LIMIT 0xffffffff51#define MAX_IMAGE_LENGTH 1652static struct _rbu_data {53	void *image_update_buffer;54	unsigned long image_update_buffer_size;55	unsigned long bios_image_size;56	int image_update_ordernum;57	spinlock_t lock;58	unsigned long packet_read_count;59	unsigned long num_packets;60	unsigned long packetsize;61	unsigned long imagesize;62	int entry_created;63} rbu_data;64 65static char image_type[MAX_IMAGE_LENGTH + 1] = "mono";66module_param_string(image_type, image_type, sizeof (image_type), 0);67MODULE_PARM_DESC(image_type, "BIOS image type. choose- mono or packet or init");68 69static unsigned long allocation_floor = 0x100000;70module_param(allocation_floor, ulong, 0644);71MODULE_PARM_DESC(allocation_floor, "Minimum address for allocations when using Packet mode");72 73struct packet_data {74	struct list_head list;75	size_t length;76	void *data;77	int ordernum;78};79 80static struct packet_data packet_data_head;81 82static struct platform_device *rbu_device;83static int context;84 85static void init_packet_head(void)86{87	INIT_LIST_HEAD(&packet_data_head.list);88	rbu_data.packet_read_count = 0;89	rbu_data.num_packets = 0;90	rbu_data.packetsize = 0;91	rbu_data.imagesize = 0;92}93 94static int create_packet(void *data, size_t length)95{96	struct packet_data *newpacket;97	int ordernum = 0;98	int retval = 0;99	unsigned int packet_array_size = 0;100	void **invalid_addr_packet_array = NULL;101	void *packet_data_temp_buf = NULL;102	unsigned int idx = 0;103 104	pr_debug("entry\n");105 106	if (!rbu_data.packetsize) {107		pr_debug("packetsize not specified\n");108		retval = -EINVAL;109		goto out_noalloc;110	}111 112	spin_unlock(&rbu_data.lock);113 114	newpacket = kzalloc(sizeof (struct packet_data), GFP_KERNEL);115 116	if (!newpacket) {117		pr_warn("failed to allocate new packet\n");118		retval = -ENOMEM;119		spin_lock(&rbu_data.lock);120		goto out_noalloc;121	}122 123	ordernum = get_order(length);124 125	/*126	 * BIOS errata mean we cannot allocate packets below 1MB or they will127	 * be overwritten by BIOS.128	 *129	 * array to temporarily hold packets130	 * that are below the allocation floor131	 *132	 * NOTE: very simplistic because we only need the floor to be at 1MB133	 *       due to BIOS errata. This shouldn't be used for higher floors134	 *       or you will run out of mem trying to allocate the array.135	 */136	packet_array_size = max_t(unsigned int, allocation_floor / rbu_data.packetsize, 1);137	invalid_addr_packet_array = kcalloc(packet_array_size, sizeof(void *),138						GFP_KERNEL);139 140	if (!invalid_addr_packet_array) {141		pr_warn("failed to allocate invalid_addr_packet_array\n");142		retval = -ENOMEM;143		spin_lock(&rbu_data.lock);144		goto out_alloc_packet;145	}146 147	while (!packet_data_temp_buf) {148		packet_data_temp_buf = (unsigned char *)149			__get_free_pages(GFP_KERNEL, ordernum);150		if (!packet_data_temp_buf) {151			pr_warn("failed to allocate new packet\n");152			retval = -ENOMEM;153			spin_lock(&rbu_data.lock);154			goto out_alloc_packet_array;155		}156 157		if ((unsigned long)virt_to_phys(packet_data_temp_buf)158				< allocation_floor) {159			pr_debug("packet 0x%lx below floor at 0x%lx\n",160					(unsigned long)virt_to_phys(161						packet_data_temp_buf),162					allocation_floor);163			invalid_addr_packet_array[idx++] = packet_data_temp_buf;164			packet_data_temp_buf = NULL;165		}166	}167	/*168	 * set to uncachable or it may never get written back before reboot169	 */170	set_memory_uc((unsigned long)packet_data_temp_buf, 1 << ordernum);171 172	spin_lock(&rbu_data.lock);173 174	newpacket->data = packet_data_temp_buf;175 176	pr_debug("newpacket at physical addr %lx\n",177		(unsigned long)virt_to_phys(newpacket->data));178 179	/* packets may not have fixed size */180	newpacket->length = length;181	newpacket->ordernum = ordernum;182	++rbu_data.num_packets;183 184	/* initialize the newly created packet headers */185	INIT_LIST_HEAD(&newpacket->list);186	list_add_tail(&newpacket->list, &packet_data_head.list);187 188	memcpy(newpacket->data, data, length);189 190	pr_debug("exit\n");191 192out_alloc_packet_array:193	/* always free packet array */194	while (idx--) {195		pr_debug("freeing unused packet below floor 0x%lx\n",196			(unsigned long)virt_to_phys(invalid_addr_packet_array[idx]));197		free_pages((unsigned long)invalid_addr_packet_array[idx], ordernum);198	}199	kfree(invalid_addr_packet_array);200 201out_alloc_packet:202	/* if error, free data */203	if (retval)204		kfree(newpacket);205 206out_noalloc:207	return retval;208}209 210static int packetize_data(const u8 *data, size_t length)211{212	int rc = 0;213	int done = 0;214	int packet_length;215	u8 *temp;216	u8 *end = (u8 *) data + length;217	pr_debug("data length %zd\n", length);218	if (!rbu_data.packetsize) {219		pr_warn("packetsize not specified\n");220		return -EIO;221	}222 223	temp = (u8 *) data;224 225	/* packetize the hunk */226	while (!done) {227		if ((temp + rbu_data.packetsize) < end)228			packet_length = rbu_data.packetsize;229		else {230			/* this is the last packet */231			packet_length = end - temp;232			done = 1;233		}234 235		if ((rc = create_packet(temp, packet_length)))236			return rc;237 238		pr_debug("%p:%td\n", temp, (end - temp));239		temp += packet_length;240	}241 242	rbu_data.imagesize = length;243 244	return rc;245}246 247static int do_packet_read(char *data, struct packet_data *newpacket,248	int length, int bytes_read, int *list_read_count)249{250	void *ptemp_buf;251	int bytes_copied = 0;252	int j = 0;253 254	*list_read_count += newpacket->length;255 256	if (*list_read_count > bytes_read) {257		/* point to the start of unread data */258		j = newpacket->length - (*list_read_count - bytes_read);259		/* point to the offset in the packet buffer */260		ptemp_buf = (u8 *) newpacket->data + j;261		/*262		 * check if there is enough room in263		 * * the incoming buffer264		 */265		if (length > (*list_read_count - bytes_read))266			/*267			 * copy what ever is there in this268			 * packet and move on269			 */270			bytes_copied = (*list_read_count - bytes_read);271		else272			/* copy the remaining */273			bytes_copied = length;274		memcpy(data, ptemp_buf, bytes_copied);275	}276	return bytes_copied;277}278 279static int packet_read_list(char *data, size_t * pread_length)280{281	struct packet_data *newpacket;282	int temp_count = 0;283	int bytes_copied = 0;284	int bytes_read = 0;285	int remaining_bytes = 0;286	char *pdest = data;287 288	/* check if we have any packets */289	if (0 == rbu_data.num_packets)290		return -ENOMEM;291 292	remaining_bytes = *pread_length;293	bytes_read = rbu_data.packet_read_count;294 295	list_for_each_entry(newpacket, (&packet_data_head.list)->next, list) {296		bytes_copied = do_packet_read(pdest, newpacket,297			remaining_bytes, bytes_read, &temp_count);298		remaining_bytes -= bytes_copied;299		bytes_read += bytes_copied;300		pdest += bytes_copied;301		/*302		 * check if we reached end of buffer before reaching the303		 * last packet304		 */305		if (remaining_bytes == 0)306			break;307	}308	/*finally set the bytes read */309	*pread_length = bytes_read - rbu_data.packet_read_count;310	rbu_data.packet_read_count = bytes_read;311	return 0;312}313 314static void packet_empty_list(void)315{316	struct packet_data *newpacket, *tmp;317 318	list_for_each_entry_safe(newpacket, tmp, (&packet_data_head.list)->next, list) {319		list_del(&newpacket->list);320 321		/*322		 * zero out the RBU packet memory before freeing323		 * to make sure there are no stale RBU packets left in memory324		 */325		memset(newpacket->data, 0, rbu_data.packetsize);326		set_memory_wb((unsigned long)newpacket->data,327			1 << newpacket->ordernum);328		free_pages((unsigned long) newpacket->data,329			newpacket->ordernum);330		kfree(newpacket);331	}332	rbu_data.packet_read_count = 0;333	rbu_data.num_packets = 0;334	rbu_data.imagesize = 0;335}336 337/*338 * img_update_free: Frees the buffer allocated for storing BIOS image339 * Always called with lock held and returned with lock held340 */341static void img_update_free(void)342{343	if (!rbu_data.image_update_buffer)344		return;345	/*346	 * zero out this buffer before freeing it to get rid of any stale347	 * BIOS image copied in memory.348	 */349	memset(rbu_data.image_update_buffer, 0,350		rbu_data.image_update_buffer_size);351	free_pages((unsigned long) rbu_data.image_update_buffer,352		rbu_data.image_update_ordernum);353 354	/*355	 * Re-initialize the rbu_data variables after a free356	 */357	rbu_data.image_update_ordernum = -1;358	rbu_data.image_update_buffer = NULL;359	rbu_data.image_update_buffer_size = 0;360	rbu_data.bios_image_size = 0;361}362 363/*364 * img_update_realloc: This function allocates the contiguous pages to365 * accommodate the requested size of data. The memory address and size366 * values are stored globally and on every call to this function the new367 * size is checked to see if more data is required than the existing size.368 * If true the previous memory is freed and new allocation is done to369 * accommodate the new size. If the incoming size is less then than the370 * already allocated size, then that memory is reused. This function is371 * called with lock held and returns with lock held.372 */373static int img_update_realloc(unsigned long size)374{375	unsigned char *image_update_buffer = NULL;376	unsigned long img_buf_phys_addr;377	int ordernum;378 379	/*380	 * check if the buffer of sufficient size has been381	 * already allocated382	 */383	if (rbu_data.image_update_buffer_size >= size) {384		/*385		 * check for corruption386		 */387		if ((size != 0) && (rbu_data.image_update_buffer == NULL)) {388			pr_err("corruption check failed\n");389			return -EINVAL;390		}391		/*392		 * we have a valid pre-allocated buffer with393		 * sufficient size394		 */395		return 0;396	}397 398	/*399	 * free any previously allocated buffer400	 */401	img_update_free();402 403	spin_unlock(&rbu_data.lock);404 405	ordernum = get_order(size);406	image_update_buffer =407		(unsigned char *)__get_free_pages(GFP_DMA32, ordernum);408	spin_lock(&rbu_data.lock);409	if (!image_update_buffer) {410		pr_debug("Not enough memory for image update: size = %ld\n", size);411		return -ENOMEM;412	}413 414	img_buf_phys_addr = (unsigned long)virt_to_phys(image_update_buffer);415	if (WARN_ON_ONCE(img_buf_phys_addr > BIOS_SCAN_LIMIT))416		return -EINVAL; /* can't happen per definition */417 418	rbu_data.image_update_buffer = image_update_buffer;419	rbu_data.image_update_buffer_size = size;420	rbu_data.bios_image_size = rbu_data.image_update_buffer_size;421	rbu_data.image_update_ordernum = ordernum;422	return 0;423}424 425static ssize_t read_packet_data(char *buffer, loff_t pos, size_t count)426{427	int retval;428	size_t bytes_left;429	size_t data_length;430	char *ptempBuf = buffer;431 432	/* check to see if we have something to return */433	if (rbu_data.num_packets == 0) {434		pr_debug("no packets written\n");435		retval = -ENOMEM;436		goto read_rbu_data_exit;437	}438 439	if (pos > rbu_data.imagesize) {440		retval = 0;441		pr_warn("data underrun\n");442		goto read_rbu_data_exit;443	}444 445	bytes_left = rbu_data.imagesize - pos;446	data_length = min(bytes_left, count);447 448	if ((retval = packet_read_list(ptempBuf, &data_length)) < 0)449		goto read_rbu_data_exit;450 451	if ((pos + count) > rbu_data.imagesize) {452		rbu_data.packet_read_count = 0;453		/* this was the last copy */454		retval = bytes_left;455	} else456		retval = count;457 458      read_rbu_data_exit:459	return retval;460}461 462static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count)463{464	/* check to see if we have something to return */465	if ((rbu_data.image_update_buffer == NULL) ||466		(rbu_data.bios_image_size == 0)) {467		pr_debug("image_update_buffer %p, bios_image_size %lu\n",468			rbu_data.image_update_buffer,469			rbu_data.bios_image_size);470		return -ENOMEM;471	}472 473	return memory_read_from_buffer(buffer, count, &pos,474			rbu_data.image_update_buffer, rbu_data.bios_image_size);475}476 477static ssize_t data_read(struct file *filp, struct kobject *kobj,478			 struct bin_attribute *bin_attr,479			 char *buffer, loff_t pos, size_t count)480{481	ssize_t ret_count = 0;482 483	spin_lock(&rbu_data.lock);484 485	if (!strcmp(image_type, "mono"))486		ret_count = read_rbu_mono_data(buffer, pos, count);487	else if (!strcmp(image_type, "packet"))488		ret_count = read_packet_data(buffer, pos, count);489	else490		pr_debug("invalid image type specified\n");491 492	spin_unlock(&rbu_data.lock);493	return ret_count;494}495static BIN_ATTR_RO(data, 0);496 497static void callbackfn_rbu(const struct firmware *fw, void *context)498{499	rbu_data.entry_created = 0;500 501	if (!fw)502		return;503 504	if (!fw->size)505		goto out;506 507	spin_lock(&rbu_data.lock);508	if (!strcmp(image_type, "mono")) {509		if (!img_update_realloc(fw->size))510			memcpy(rbu_data.image_update_buffer,511				fw->data, fw->size);512	} else if (!strcmp(image_type, "packet")) {513		/*514		 * we need to free previous packets if a515		 * new hunk of packets needs to be downloaded516		 */517		packet_empty_list();518		if (packetize_data(fw->data, fw->size))519			/* Incase something goes wrong when we are520			 * in middle of packetizing the data, we521			 * need to free up whatever packets might522			 * have been created before we quit.523			 */524			packet_empty_list();525	} else526		pr_debug("invalid image type specified\n");527	spin_unlock(&rbu_data.lock);528 out:529	release_firmware(fw);530}531 532static ssize_t image_type_read(struct file *filp, struct kobject *kobj,533			       struct bin_attribute *bin_attr,534			       char *buffer, loff_t pos, size_t count)535{536	int size = 0;537	if (!pos)538		size = scnprintf(buffer, count, "%s\n", image_type);539	return size;540}541 542static ssize_t image_type_write(struct file *filp, struct kobject *kobj,543				struct bin_attribute *bin_attr,544				char *buffer, loff_t pos, size_t count)545{546	int rc = count;547	int req_firm_rc = 0;548	int i;549	spin_lock(&rbu_data.lock);550	/*551	 * Find the first newline or space552	 */553	for (i = 0; i < count; ++i)554		if (buffer[i] == '\n' || buffer[i] == ' ') {555			buffer[i] = '\0';556			break;557		}558	if (i == count)559		buffer[count] = '\0';560 561	if (strstr(buffer, "mono"))562		strcpy(image_type, "mono");563	else if (strstr(buffer, "packet"))564		strcpy(image_type, "packet");565	else if (strstr(buffer, "init")) {566		/*567		 * If due to the user error the driver gets in a bad568		 * state where even though it is loaded , the569		 * /sys/class/firmware/dell_rbu entries are missing.570		 * to cover this situation the user can recreate entries571		 * by writing init to image_type.572		 */573		if (!rbu_data.entry_created) {574			spin_unlock(&rbu_data.lock);575			req_firm_rc = request_firmware_nowait(THIS_MODULE,576				FW_ACTION_NOUEVENT, "dell_rbu",577				&rbu_device->dev, GFP_KERNEL, &context,578				callbackfn_rbu);579			if (req_firm_rc) {580				pr_err("request_firmware_nowait failed %d\n", rc);581				rc = -EIO;582			} else583				rbu_data.entry_created = 1;584 585			spin_lock(&rbu_data.lock);586		}587	} else {588		pr_warn("image_type is invalid\n");589		spin_unlock(&rbu_data.lock);590		return -EINVAL;591	}592 593	/* we must free all previous allocations */594	packet_empty_list();595	img_update_free();596	spin_unlock(&rbu_data.lock);597 598	return rc;599}600static BIN_ATTR_RW(image_type, 0);601 602static ssize_t packet_size_read(struct file *filp, struct kobject *kobj,603				struct bin_attribute *bin_attr,604				char *buffer, loff_t pos, size_t count)605{606	int size = 0;607	if (!pos) {608		spin_lock(&rbu_data.lock);609		size = scnprintf(buffer, count, "%lu\n", rbu_data.packetsize);610		spin_unlock(&rbu_data.lock);611	}612	return size;613}614 615static ssize_t packet_size_write(struct file *filp, struct kobject *kobj,616				 struct bin_attribute *bin_attr,617				 char *buffer, loff_t pos, size_t count)618{619	unsigned long temp;620	spin_lock(&rbu_data.lock);621	packet_empty_list();622	sscanf(buffer, "%lu", &temp);623	if (temp < 0xffffffff)624		rbu_data.packetsize = temp;625 626	spin_unlock(&rbu_data.lock);627	return count;628}629static BIN_ATTR_RW(packet_size, 0);630 631static struct bin_attribute *rbu_bin_attrs[] = {632	&bin_attr_data,633	&bin_attr_image_type,634	&bin_attr_packet_size,635	NULL636};637 638static const struct attribute_group rbu_group = {639	.bin_attrs = rbu_bin_attrs,640};641 642static int __init dcdrbu_init(void)643{644	int rc;645	spin_lock_init(&rbu_data.lock);646 647	init_packet_head();648	rbu_device = platform_device_register_simple("dell_rbu", PLATFORM_DEVID_NONE, NULL, 0);649	if (IS_ERR(rbu_device)) {650		pr_err("platform_device_register_simple failed\n");651		return PTR_ERR(rbu_device);652	}653 654	rc = sysfs_create_group(&rbu_device->dev.kobj, &rbu_group);655	if (rc)656		goto out_devreg;657 658	rbu_data.entry_created = 0;659	return 0;660 661out_devreg:662	platform_device_unregister(rbu_device);663	return rc;664}665 666static __exit void dcdrbu_exit(void)667{668	spin_lock(&rbu_data.lock);669	packet_empty_list();670	img_update_free();671	spin_unlock(&rbu_data.lock);672	sysfs_remove_group(&rbu_device->dev.kobj, &rbu_group);673	platform_device_unregister(rbu_device);674}675 676module_exit(dcdrbu_exit);677module_init(dcdrbu_init);678