Morse Micro IoT SDK  2.10.4
test_wlan_fw_bcf.c
1/*
2 * Copyright 2023 Morse Micro
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7#include "porting_assistant.h"
8#include "mmhal_wlan.h"
9
10#ifndef PACKED
11#define PACKED __attribute__((packed))
12#endif
13
15enum fw_tlv_types
16{
17 FIELD_TYPE_MAGIC = 0x8000,
18 FIELD_TYPE_EOF = 0x8f00,
19};
20
22#define MBIN_FW_MAGIC_NUMBER (0x57464d4d)
24#define MBIN_BCF_MAGIC_NUMBER (0x43424d4d)
25
28{
30 uint16_t type;
32 uint16_t len;
33};
34
37#define MAX_TLVS (50)
38
40static void robuf_cleanup(struct mmhal_robuf *robuf)
41{
42 if (robuf != NULL)
43 {
44 /* Free the robuf buffer */
45 if (robuf->free_cb != NULL)
46 {
47 robuf->free_cb(robuf->free_arg);
48 }
49 memset(robuf, 0, sizeof(*robuf));
50 }
51}
52
53typedef void (*file_read_fn_t)(uint32_t offset, uint32_t requested_len, struct mmhal_robuf *robuf);
54
55static enum test_result execute_fw_bcf_test(file_read_fn_t file_read_fn,
56 const char *file_read_fn_name,
57 const char *type,
58 uint32_t expected_magic_number,
59 char *log_buf,
60 size_t log_buf_len)
61{
62 uint32_t offset = 0;
63
64 unsigned num_tlvs;
65 for (num_tlvs = 0; num_tlvs < MAX_TLVS; num_tlvs++)
66 {
67 struct mmhal_robuf robuf = { 0 };
68 struct tlv_header hdr;
69 file_read_fn(offset, sizeof(hdr), &robuf);
70
71 if (robuf.len == 0)
72 {
73 TEST_LOG_APPEND(
74 "%s invalid or ended too soon (EOF marker not found)\n"
75 "Check that you have provided a valid %s file and review your implementation\n"
76 "of %s().\n",
77 type,
78 type,
79 file_read_fn_name);
80 return TEST_FAILED_NON_CRITICAL;
81 }
82
83 if (robuf.buf == NULL)
84 {
85 TEST_LOG_APPEND("%s returned NULL buffer but non-zero length\n", file_read_fn_name);
86 TEST_LOG_APPEND("Review your implementation of %s().\n", file_read_fn_name);
87 return TEST_FAILED_NON_CRITICAL;
88 }
89
90 if (robuf.len < sizeof(hdr))
91 {
92 TEST_LOG_APPEND("The length of data returned by %s() was too short\n"
93 "%s() is required to return a minimum of "
94 "MMWLAN_FW_BCF_MIN_READ_LENGTH (%u) bytes.\n",
95 file_read_fn_name,
96 file_read_fn_name,
98 return TEST_FAILED_NON_CRITICAL;
99 }
100
101 memcpy(&hdr, (struct tlv_header *)robuf.buf, sizeof(hdr));
102
103 robuf_cleanup(&robuf);
104
105 if (num_tlvs == 0 && hdr.type != FIELD_TYPE_MAGIC)
106 {
107 TEST_LOG_APPEND(
108 "The firware was corrupt (did not start with a magic number). \n"
109 "Possible causes include using invalid (e.g., outdated) firmware, or a bug in\n"
110 "%s()\n",
111 file_read_fn_name);
112 return TEST_FAILED_NON_CRITICAL;
113 }
114
115 if (hdr.type == FIELD_TYPE_EOF)
116 {
117 return TEST_PASSED;
118 }
119
120 offset += sizeof(hdr);
121
122 /* Read TLV data */
123 uint32_t remaining_len = hdr.len;
124 while (remaining_len > 0)
125 {
126 file_read_fn(offset, remaining_len, &robuf);
127 if (robuf.len == 0)
128 {
129 TEST_LOG_APPEND("%s ended too soon.\n"
130 "Check that you have provided a valid firmware file and review "
131 "your implementation of\n%s().\n",
132 type,
133 file_read_fn_name);
134 return TEST_FAILED_NON_CRITICAL;
135 }
136
137 if (robuf.len > remaining_len)
138 {
139 TEST_LOG_APPEND("The length of data returned by %s() was too great\n"
140 "%s() should not return more than `requested_len` bytes.\n",
141 file_read_fn_name,
142 file_read_fn_name);
143 return TEST_FAILED_NON_CRITICAL;
144 }
145
146 if (num_tlvs == 0)
147 {
148 if (robuf.len < sizeof(uint32_t))
149 {
150 TEST_LOG_APPEND("The length of data returned by %s() was too short\n"
151 "%s() is required to return a minimum of "
152 "MMWLAN_FW_BCF_MIN_READ_LENGTH %u) bytes\n",
153 file_read_fn_name,
154 file_read_fn_name,
156 return TEST_FAILED_NON_CRITICAL;
157 }
158
159 uint32_t magic = (robuf.buf[0]) |
160 (robuf.buf[1] << 8) |
161 (robuf.buf[2] << 16) |
162 (robuf.buf[3] << 24);
163 if (magic != expected_magic_number)
164 {
165 TEST_LOG_APPEND(
166 "The %s was corrupt (did not contain the correct magic number -- "
167 "expect 0x%08lx, got 0x%08lx).\n"
168 "This is likey caused by using an invalid (e.g., outdated) version.\n",
169 type,
170 expected_magic_number,
171 magic);
172 return TEST_FAILED_NON_CRITICAL;
173 }
174 }
175
176 offset += robuf.len;
177 remaining_len -= robuf.len;
178 robuf_cleanup(&robuf);
179 }
180 }
181
182 TEST_LOG_APPEND("%s invalid or ended too soon (EOF marker not found after %u TLVs).\n"
183 "Check that you have provided a valid %s file and review your implementation\n"
184 "of %s().\n",
185 type,
186 num_tlvs,
187 type,
188 file_read_fn_name);
189 return TEST_FAILED_NON_CRITICAL;
190}
191
192TEST_STEP(test_step_mmhal_wlan_validate_fw, "Validate MM firmware")
193{
194 return execute_fw_bcf_test(mmhal_wlan_read_fw_file,
195 "mmhal_wlan_read_fw_file",
196 "Firmware",
198 log_buf,
199 log_buf_len);
200}
201
202TEST_STEP(test_step_mmhal_wlan_validate_bcf, "Validate BCF")
203{
204 return execute_fw_bcf_test(mmhal_wlan_read_bcf_file,
205 "mmhal_wlan_read_bcf_file",
206 "BCF",
208 log_buf,
209 log_buf_len);
210}
#define MBIN_FW_MAGIC_NUMBER
Expected value of the magic field for a firmware image MMFW.
Definition: mbin.h:78
#define PACKED
Macro for the compiler packed attribute.
Definition: mbin.h:19
#define MBIN_BCF_MAGIC_NUMBER
Expected value of the magic field for a BCF MMBC.
Definition: mbin.h:80
#define MMHAL_WLAN_FW_BCF_MIN_READ_LENGTH
Minimum length of data to be returned by mmhal_wlan_read_bcf_file() and mmhal_wlan_read_fw_file().
Definition: mmhal_wlan.h:199
void mmhal_wlan_read_bcf_file(uint32_t offset, uint32_t requested_len, struct mmhal_robuf *robuf)
Retrieves the content of the Morse Micro Board Configuration File and places it into the given buffer...
void mmhal_wlan_read_fw_file(uint32_t offset, uint32_t requested_len, struct mmhal_robuf *robuf)
Retrieves the content of the Morse Micro Chip Firmware and places it into the given buffer.
const struct test_step test_step_mmhal_wlan_validate_bcf
Test definition.
const struct test_step test_step_mmhal_wlan_validate_fw
Test definition.
Read-only buffer data structure.
Definition: mmhal_wlan.h:179
const uint8_t * buf
Pointer to the start of the read-only buffer.
Definition: mmhal_wlan.h:181
uint32_t len
Length of the buffer contents.
Definition: mmhal_wlan.h:183
void * free_arg
Optional argument to free_cb.
Definition: mmhal_wlan.h:194
void(* free_cb)(void *arg)
Optional callback to be invoked by the consumer to release the buffer when it is no longer required.
Definition: mmhal_wlan.h:192
TLV (type-length-value) header.
uint16_t len
Value length.
uint16_t type
Type code.