Morse Micro IoT SDK  2.9.7
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.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, const char *type,
57 uint32_t expected_magic_number,
58 char *log_buf, size_t log_buf_len)
59{
60 uint32_t offset = 0;
61
62 unsigned num_tlvs;
63 for (num_tlvs = 0; num_tlvs < MAX_TLVS; num_tlvs++)
64 {
65 struct mmhal_robuf robuf = {0};
66 struct tlv_header hdr;
67 file_read_fn(offset, sizeof(hdr), &robuf);
68
69 if (robuf.len == 0)
70 {
71 TEST_LOG_APPEND(
72 "%s invalid or ended too soon (EOF marker not found)\n"
73 "Check that you have provided a valid %s file and review your implementation\n"
74 "of %s().\n", type, type, file_read_fn_name);
75 return TEST_FAILED_NON_CRITICAL;
76 }
77
78 if (robuf.buf == NULL)
79 {
80 TEST_LOG_APPEND("%s returned NULL buffer but non-zero length\n", file_read_fn_name);
81 TEST_LOG_APPEND("Review your implementation of %s().\n", file_read_fn_name);
82 return TEST_FAILED_NON_CRITICAL;
83 }
84
85 if (robuf.len < sizeof(hdr))
86 {
87 TEST_LOG_APPEND(
88 "The length of data returned by %s() was too short\n"
89 "%s() is required to return a minimum of "
90 "MMWLAN_FW_BCF_MIN_READ_LENGTH (%u) bytes.\n",
91 file_read_fn_name, file_read_fn_name, MMHAL_WLAN_FW_BCF_MIN_READ_LENGTH);
92 return TEST_FAILED_NON_CRITICAL;
93 }
94
95 memcpy(&hdr, (struct tlv_header *)robuf.buf, sizeof(hdr));
96
97 robuf_cleanup(&robuf);
98
99 if (num_tlvs == 0 && hdr.type != FIELD_TYPE_MAGIC)
100 {
101 TEST_LOG_APPEND(
102 "The firware was corrupt (did not start with a magic number). \n"
103 "Possible causes include using invalid (e.g., outdated) firmware, or a bug in\n"
104 "%s()\n", file_read_fn_name);
105 return TEST_FAILED_NON_CRITICAL;
106 }
107
108 if (hdr.type == FIELD_TYPE_EOF)
109 {
110 return TEST_PASSED;
111 }
112
113 offset += sizeof(hdr);
114
115 /* Read TLV data */
116 uint32_t remaining_len = hdr.len;
117 while (remaining_len > 0)
118 {
119 file_read_fn(offset, remaining_len, &robuf);
120 if (robuf.len == 0)
121 {
122 TEST_LOG_APPEND(
123 "%s ended too soon.\n"
124 "Check that you have provided a valid firmware file and review "
125 "your implementation of\n%s().\n", type, file_read_fn_name);
126 return TEST_FAILED_NON_CRITICAL;
127 }
128
129 if (robuf.len > remaining_len)
130 {
131 TEST_LOG_APPEND(
132 "The length of data returned by %s() was too great\n"
133 "%s() should not return more than `requested_len` bytes.\n",
134 file_read_fn_name, file_read_fn_name);
135 return TEST_FAILED_NON_CRITICAL;
136 }
137
138 if (num_tlvs == 0)
139 {
140 if (robuf.len < sizeof(uint32_t))
141 {
142 TEST_LOG_APPEND(
143 "The length of data returned by %s() was too short\n"
144 "%s() is required to return a minimum of "
145 "MMWLAN_FW_BCF_MIN_READ_LENGTH %u) bytes\n",
146 file_read_fn_name, file_read_fn_name, MMHAL_WLAN_FW_BCF_MIN_READ_LENGTH);
147 return TEST_FAILED_NON_CRITICAL;
148 }
149
150 uint32_t magic = (robuf.buf[0]) |
151 (robuf.buf[1] << 8) |
152 (robuf.buf[2] << 16) |
153 (robuf.buf[3] << 24);
154 if (magic != expected_magic_number)
155 {
156 TEST_LOG_APPEND(
157 "The %s was corrupt (did not contain the correct magic number -- "
158 "expect 0x%08lx, got 0x%08lx).\n"
159 "This is likey caused by using an invalid (e.g., outdated) version.\n",
160 type, expected_magic_number, magic);
161 return TEST_FAILED_NON_CRITICAL;
162 }
163 }
164
165 offset += robuf.len;
166 remaining_len -= robuf.len;
167 robuf_cleanup(&robuf);
168 }
169 }
170
171 TEST_LOG_APPEND(
172 "%s invalid or ended too soon (EOF marker not found after %u TLVs).\n"
173 "Check that you have provided a valid %s file and review your implementation\n"
174 "of %s().\n", type, num_tlvs, type, file_read_fn_name);
175 return TEST_FAILED_NON_CRITICAL;
176}
177
178TEST_STEP(test_step_mmhal_wlan_validate_fw, "Validate MM firmware")
179{
180 return execute_fw_bcf_test(mmhal_wlan_read_fw_file, "mmhal_wlan_read_fw_file", "Firmware",
181 MBIN_FW_MAGIC_NUMBER, log_buf, log_buf_len);
182}
183
184TEST_STEP(test_step_mmhal_wlan_validate_bcf, "Validate BCF")
185{
186 return execute_fw_bcf_test(mmhal_wlan_read_bcf_file, "mmhal_wlan_read_bcf_file", "BCF",
187 MBIN_BCF_MAGIC_NUMBER, log_buf, log_buf_len);
188}
#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:182
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:162
const uint8_t * buf
Pointer to the start of the read-only buffer.
Definition: mmhal_wlan.h:164
uint32_t len
Length of the buffer contents.
Definition: mmhal_wlan.h:166
void * free_arg
Optional argument to free_cb.
Definition: mmhal_wlan.h:177
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:175
TLV (type-length-value) header.
uint16_t len
Value length.
uint16_t type
Type code.