cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

as102_fw.c (5176B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Abilis Systems Single DVB-T Receiver
      4 * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com>
      5 * Copyright (C) 2010 Devin Heitmueller <dheitmueller@kernellabs.com>
      6 */
      7#include <linux/kernel.h>
      8#include <linux/errno.h>
      9#include <linux/ctype.h>
     10#include <linux/delay.h>
     11#include <linux/firmware.h>
     12
     13#include "as102_drv.h"
     14#include "as102_fw.h"
     15
     16static const char as102_st_fw1[] = "as102_data1_st.hex";
     17static const char as102_st_fw2[] = "as102_data2_st.hex";
     18static const char as102_dt_fw1[] = "as102_data1_dt.hex";
     19static const char as102_dt_fw2[] = "as102_data2_dt.hex";
     20
     21static unsigned char atohx(unsigned char *dst, char *src)
     22{
     23	unsigned char value = 0;
     24
     25	char msb = tolower(*src) - '0';
     26	char lsb = tolower(*(src + 1)) - '0';
     27
     28	if (msb > 9)
     29		msb -= 7;
     30	if (lsb > 9)
     31		lsb -= 7;
     32
     33	*dst = value = ((msb & 0xF) << 4) | (lsb & 0xF);
     34	return value;
     35}
     36
     37/*
     38 * Parse INTEL HEX firmware file to extract address and data.
     39 */
     40static int parse_hex_line(unsigned char *fw_data, unsigned char *addr,
     41			  unsigned char *data, int *dataLength,
     42			  unsigned char *addr_has_changed) {
     43
     44	int count = 0;
     45	unsigned char *src, dst;
     46
     47	if (*fw_data++ != ':') {
     48		pr_err("invalid firmware file\n");
     49		return -EFAULT;
     50	}
     51
     52	/* locate end of line */
     53	for (src = fw_data; *src != '\n'; src += 2) {
     54		atohx(&dst, src);
     55		/* parse line to split addr / data */
     56		switch (count) {
     57		case 0:
     58			*dataLength = dst;
     59			break;
     60		case 1:
     61			addr[2] = dst;
     62			break;
     63		case 2:
     64			addr[3] = dst;
     65			break;
     66		case 3:
     67			/* check if data is an address */
     68			if (dst == 0x04)
     69				*addr_has_changed = 1;
     70			else
     71				*addr_has_changed = 0;
     72			break;
     73		case  4:
     74		case  5:
     75			if (*addr_has_changed)
     76				addr[(count - 4)] = dst;
     77			else
     78				data[(count - 4)] = dst;
     79			break;
     80		default:
     81			data[(count - 4)] = dst;
     82			break;
     83		}
     84		count++;
     85	}
     86
     87	/* return read value + ':' + '\n' */
     88	return (count * 2) + 2;
     89}
     90
     91static int as102_firmware_upload(struct as10x_bus_adapter_t *bus_adap,
     92				 unsigned char *cmd,
     93				 const struct firmware *firmware) {
     94
     95	struct as10x_fw_pkt_t *fw_pkt;
     96	int total_read_bytes = 0, errno = 0;
     97	unsigned char addr_has_changed = 0;
     98
     99	fw_pkt = kmalloc(sizeof(*fw_pkt), GFP_KERNEL);
    100	if (!fw_pkt)
    101		return -ENOMEM;
    102
    103
    104	for (total_read_bytes = 0; total_read_bytes < firmware->size; ) {
    105		int read_bytes = 0, data_len = 0;
    106
    107		/* parse intel hex line */
    108		read_bytes = parse_hex_line(
    109				(u8 *) (firmware->data + total_read_bytes),
    110				fw_pkt->raw.address,
    111				fw_pkt->raw.data,
    112				&data_len,
    113				&addr_has_changed);
    114
    115		if (read_bytes <= 0)
    116			goto error;
    117
    118		/* detect the end of file */
    119		total_read_bytes += read_bytes;
    120		if (total_read_bytes == firmware->size) {
    121			fw_pkt->u.request[0] = 0x00;
    122			fw_pkt->u.request[1] = 0x03;
    123
    124			/* send EOF command */
    125			errno = bus_adap->ops->upload_fw_pkt(bus_adap,
    126							     (uint8_t *)
    127							     fw_pkt, 2, 0);
    128			if (errno < 0)
    129				goto error;
    130		} else {
    131			if (!addr_has_changed) {
    132				/* prepare command to send */
    133				fw_pkt->u.request[0] = 0x00;
    134				fw_pkt->u.request[1] = 0x01;
    135
    136				data_len += sizeof(fw_pkt->u.request);
    137				data_len += sizeof(fw_pkt->raw.address);
    138
    139				/* send cmd to device */
    140				errno = bus_adap->ops->upload_fw_pkt(bus_adap,
    141								     (uint8_t *)
    142								     fw_pkt,
    143								     data_len,
    144								     0);
    145				if (errno < 0)
    146					goto error;
    147			}
    148		}
    149	}
    150error:
    151	kfree(fw_pkt);
    152	return (errno == 0) ? total_read_bytes : errno;
    153}
    154
    155int as102_fw_upload(struct as10x_bus_adapter_t *bus_adap)
    156{
    157	int errno = -EFAULT;
    158	const struct firmware *firmware = NULL;
    159	unsigned char *cmd_buf = NULL;
    160	const char *fw1, *fw2;
    161	struct usb_device *dev = bus_adap->usb_dev;
    162
    163	/* select fw file to upload */
    164	if (dual_tuner) {
    165		fw1 = as102_dt_fw1;
    166		fw2 = as102_dt_fw2;
    167	} else {
    168		fw1 = as102_st_fw1;
    169		fw2 = as102_st_fw2;
    170	}
    171
    172	/* allocate buffer to store firmware upload command and data */
    173	cmd_buf = kzalloc(MAX_FW_PKT_SIZE, GFP_KERNEL);
    174	if (cmd_buf == NULL) {
    175		errno = -ENOMEM;
    176		goto error;
    177	}
    178
    179	/* request kernel to locate firmware file: part1 */
    180	errno = request_firmware(&firmware, fw1, &dev->dev);
    181	if (errno < 0) {
    182		pr_err("%s: unable to locate firmware file: %s\n",
    183		       DRIVER_NAME, fw1);
    184		goto error;
    185	}
    186
    187	/* initiate firmware upload */
    188	errno = as102_firmware_upload(bus_adap, cmd_buf, firmware);
    189	if (errno < 0) {
    190		pr_err("%s: error during firmware upload part1\n",
    191		       DRIVER_NAME);
    192		goto error;
    193	}
    194
    195	pr_info("%s: firmware: %s loaded with success\n",
    196		DRIVER_NAME, fw1);
    197	release_firmware(firmware);
    198	firmware = NULL;
    199
    200	/* wait for boot to complete */
    201	mdelay(100);
    202
    203	/* request kernel to locate firmware file: part2 */
    204	errno = request_firmware(&firmware, fw2, &dev->dev);
    205	if (errno < 0) {
    206		pr_err("%s: unable to locate firmware file: %s\n",
    207		       DRIVER_NAME, fw2);
    208		goto error;
    209	}
    210
    211	/* initiate firmware upload */
    212	errno = as102_firmware_upload(bus_adap, cmd_buf, firmware);
    213	if (errno < 0) {
    214		pr_err("%s: error during firmware upload part2\n",
    215		       DRIVER_NAME);
    216		goto error;
    217	}
    218
    219	pr_info("%s: firmware: %s loaded with success\n",
    220		DRIVER_NAME, fw2);
    221error:
    222	kfree(cmd_buf);
    223	release_firmware(firmware);
    224
    225	return errno;
    226}