1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (C) 2024 PHYTEC Messtechnik GmbH
4  * Author: Daniel Schultz <d.schultz@phytec.de>
5  */
6 
7 #include <env.h>
8 #include <malloc.h>
9 #include <u-boot/crc.h>
10 #include <net.h>
11 #include <vsprintf.h>
12 
13 #include "phytec_som_detection_blocks.h"
14 
15 #if IS_ENABLED(CONFIG_PHYTEC_SOM_DETECTION_BLOCKS)
16 
17 struct phytec_api3_element *
phytec_blocks_init_mac(struct phytec_api3_block_header * header,uint8_t * payload)18 	phytec_blocks_init_mac(struct phytec_api3_block_header *header,
19 			       uint8_t *payload)
20 {
21 	struct phytec_api3_element *element;
22 	struct phytec_api3_block_mac *mac;
23 	unsigned int crc;
24 	unsigned int len = sizeof(struct phytec_api3_block_mac);
25 
26 	if (!header)
27 		return NULL;
28 	if (!payload)
29 		return NULL;
30 
31 	element = (struct phytec_api3_element *)
32 			calloc(8, PHYTEC_API3_ELEMENT_HEADER_SIZE + len);
33 	if (!element) {
34 		pr_err("%s: Unable to allocate memory\n", __func__);
35 		return NULL;
36 	}
37 	element->block_type = header->block_type;
38 	memcpy(&element->block.mac, payload, len);
39 	mac = &element->block.mac;
40 
41 	debug("%s: interface: %i\n", __func__, mac->interface);
42 	debug("%s: MAC %pM\n", __func__, mac->address);
43 
44 	crc = crc8(0, (const unsigned char *)mac, len);
45 	debug("%s: crc: %x\n", __func__, crc);
46 	if (crc) {
47 		pr_err("%s: CRC mismatch. API3 block payload is unusable\n",
48 		       __func__);
49 		return NULL;
50 	}
51 
52 	return element;
53 }
54 
55 int __maybe_unused
phytec_blocks_add_mac_to_env(struct phytec_api3_element * element)56 	phytec_blocks_add_mac_to_env(struct phytec_api3_element *element)
57 {
58 	char enetenv[9] = "ethaddr";
59 	char buf[ARP_HLEN_ASCII + 1];
60 	struct phytec_api3_block_mac *block = &element->block.mac;
61 	int ret;
62 
63 	if (!is_valid_ethaddr(block->address)) {
64 		pr_err("%s: Invalid MAC address in block.\n", __func__);
65 		return -1;
66 	}
67 
68 	if (block->interface > 0) {
69 		ret = sprintf(enetenv, "eth%iaddr", block->interface);
70 		if (ret != 8) {
71 			pr_err("%s: Unable to create env string\n", __func__);
72 			return -1;
73 		}
74 	}
75 
76 	ret = sprintf(buf, "%pM", block->address);
77 	if (ret != ARP_HLEN_ASCII) {
78 		pr_err("%s: Unable to convert MAC address\n", __func__);
79 		return -1;
80 	}
81 	ret = env_set(enetenv, buf);
82 	if (ret) {
83 		pr_err("%s: Failed to set MAC address to env.\n", __func__);
84 		return -1;
85 	}
86 
87 	debug("%s: Added %s to %s\n", __func__, buf, enetenv);
88 	return 0;
89 }
90 
91 #else
92 
93 inline struct phytec_api3_element *
phytec_api3_init_mac_block(struct phytec_api3_block_header * header,uint8_t * payload)94 	phytec_api3_init_mac_block(struct phytec_api3_block_header *header,
95 				   uint8_t *payload)
96 {
97 	return NULL;
98 }
99 
100 inline int __maybe_unused
phytec_blocks_add_mac_to_env(struct phytec_api3_element * element)101 	phytec_blocks_add_mac_to_env(struct phytec_api3_element *element)
102 {
103 	return -1;
104 }
105 
106 #endif
107