Skip to content

Commit 8a11d16

Browse files
author
Matsievskiy S.V
committed
Refactor decoder functions
1 parent 5f65991 commit 8a11d16

File tree

7 files changed

+176
-149
lines changed

7 files changed

+176
-149
lines changed

CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ endfunction()
5353

5454
add_executable(frugen frugen.c)
5555
add_executable(frugen-static frugen.c)
56-
add_library(fru-static STATIC fru.c fru_reader.c)
57-
add_library(fru-shared SHARED fru.c fru_reader.c)
56+
add_library(fru-static STATIC fru.c)
57+
add_library(fru-shared SHARED fru.c)
5858
find_library(JSON_LIB json-c)
5959
SET_TARGET_PROPERTIES(fru-static PROPERTIES OUTPUT_NAME fru CLEAN_DIRECT_OUTPUT 1)
6060
SET_TARGET_PROPERTIES(fru-shared PROPERTIES OUTPUT_NAME fru CLEAN_DIRECT_OUTPUT 1)

fatal.h

Lines changed: 0 additions & 6 deletions
This file was deleted.

fru.c

Lines changed: 53 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -404,17 +404,9 @@ fru_field_t * fru_encode_data(int len, const uint8_t *data)
404404
return out;
405405
}
406406

407-
/**
408-
* Decode data from a buffer into another buffer.
409-
*
410-
* For binary data use FRU_FIELDDATALEN(field->typelen) to find
411-
* out the size of valid bytes in the returned buffer.
412-
*
413-
* Return false if there were errors during decoding and true otherwise.
414-
*/
415407
bool fru_decode_data(fru_field_t *field,
416-
typed_field_t *out, //< [out] buffer to decode into
417-
size_t out_len) // <[in] length of output buffer
408+
typed_field_t *out,
409+
size_t out_len)
418410
{
419411
if (!field) return false;
420412

@@ -1225,6 +1217,57 @@ fru_t * fru_create(fru_area_t area[FRU_MAX_AREAS], size_t *size)
12251217
return out;
12261218
}
12271219

1220+
fru_t *find_fru_header(uint8_t *buffer, size_t size) {
1221+
if (size < 8) {
1222+
errno = ENOBUFS;
1223+
return NULL;
1224+
}
1225+
fru_t *header = (fru_t *) buffer;
1226+
if ((header->ver != FRU_VER_1) || (header->rsvd != 0) || (header->pad != 0)) {
1227+
errno = EPROTO;
1228+
return NULL;
1229+
}
1230+
if (header->hchecksum != calc_checksum(header, sizeof(fru_t) - 1)) {
1231+
errno = EPROTO;
1232+
return NULL;
1233+
}
1234+
return header;
1235+
}
1236+
1237+
#define AREAS \
1238+
X(chassis) \
1239+
X(board) \
1240+
X(product)
1241+
#define X(AREA) \
1242+
fru_##AREA##_area_t *find_fru_##AREA##_area(uint8_t *buffer, size_t size) { \
1243+
fru_t *header = find_fru_header(buffer, size); \
1244+
if ((header == NULL) || (header->AREA == 0)) { \
1245+
return NULL; \
1246+
} \
1247+
if ((header->AREA + 3) > size) { \
1248+
errno = ENOBUFS; \
1249+
return NULL; \
1250+
} \
1251+
fru_##AREA##_area_t *area = \
1252+
(fru_##AREA##_area_t *)(buffer + FRU_BYTES(header->AREA)); \
1253+
if (area->ver != 1) { \
1254+
errno = EPROTO; \
1255+
return NULL; \
1256+
} \
1257+
if (FRU_BYTES(header->AREA) + FRU_BYTES(area->blocks) > size) { \
1258+
errno = ENOBUFS; \
1259+
return NULL; \
1260+
} \
1261+
if (*(((uint8_t *)area) + FRU_BYTES(area->blocks) - 1) != \
1262+
calc_checksum(((uint8_t *)area), FRU_BYTES(area->blocks) - 1)) { \
1263+
errno = EPROTO; \
1264+
return NULL; \
1265+
} \
1266+
return area; \
1267+
}
1268+
AREAS
1269+
#undef X
1270+
#undef AREAS
12281271

12291272
#ifdef __STANDALONE__
12301273

fru.h

Lines changed: 84 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -327,13 +327,93 @@ fru_mr_reclist_t * add_mr_reclist(fru_mr_reclist_t **reclist);
327327
fru_mr_area_t * fru_mr_area(fru_mr_reclist_t *reclist, size_t *total);
328328

329329
fru_chassis_area_t * fru_encode_chassis_info(const fru_exploded_chassis_t *chassis);
330-
bool fru_decode_chassis_info(const fru_chassis_area_t *area, fru_exploded_chassis_t *chassis_out);
331330
fru_board_area_t * fru_encode_board_info(const fru_exploded_board_t *board);
332-
bool fru_decode_board_info(const fru_board_area_t *area, fru_exploded_board_t *board_out);
333331
fru_product_area_t * fru_encode_product_info(const fru_exploded_product_t *product);
334-
bool fru_decode_product_info(const fru_product_area_t *area, fru_exploded_product_t *product_out);
335332
fru_field_t * fru_encode_data(int len, const uint8_t *data);
336-
bool fru_decode_data(fru_field_t *field, typed_field_t *out, size_t out_len);
337333
fru_t * fru_create(fru_area_t area[FRU_MAX_AREAS], size_t *size);
338334

335+
/**
336+
* @brief Find and validate FRU header in the byte buffer.
337+
*
338+
* @param[in] buffer Byte buffer.
339+
* @param[in] size Byte buffer size.
340+
* @return Pointer to the FRU header in the buffer.
341+
* @retval NULL FRU header not found.
342+
*/
343+
fru_t *find_fru_header(uint8_t *buffer, size_t size);
344+
345+
/**
346+
* @brief Find and validate FRU chassis area in the byte buffer.
347+
*
348+
* @param[in] buffer Byte buffer.
349+
* @param[in] size Byte buffer size.
350+
* @return Pointer to the FRU chassis area in the buffer.
351+
* @retval NULL FRU chassis area not found.
352+
*/
353+
fru_chassis_area_t *find_fru_chassis_area(uint8_t *buffer, size_t size);
354+
355+
/**
356+
* @brief Find and validate FRU board area in the byte buffer.
357+
*
358+
* @param[in] buffer Byte buffer.
359+
* @param[in] size Byte buffer size.
360+
* @return Pointer to the FRU board area in the buffer.
361+
* @retval NULL FRU board area not found.
362+
*/
363+
fru_board_area_t *find_fru_board_area(uint8_t *buffer, size_t size);
364+
365+
/**
366+
* @brief Find and validate FRU product area in the byte buffer.
367+
*
368+
* @param[in] buffer Byte buffer.
369+
* @param[in] size Byte buffer size.
370+
* @return Pointer to the FRU product area in the buffer.
371+
* @retval NULL FRU product area not found.
372+
*/
373+
fru_product_area_t *find_fru_product_area(uint8_t *buffer, size_t size);
374+
375+
/**
376+
* @brief Decode chassis area into \p fru_exploded_chassis_t.
377+
*
378+
* @param[in] area Encoded area.
379+
* @param[out] chassis_out Decoded structure.
380+
* @retval true Success.
381+
* @retval false Failure.
382+
*/
383+
bool fru_decode_chassis_info(const fru_chassis_area_t *area, fru_exploded_chassis_t *chassis_out);
384+
385+
/**
386+
* @brief Decode board area into \p fru_exploded_board_t.
387+
*
388+
* @param[in] area Encoded area.
389+
* @param[out] chassis_out Decoded structure.
390+
* @retval true Success.
391+
* @retval false Failure.
392+
*/
393+
bool fru_decode_board_info(const fru_board_area_t *area, fru_exploded_board_t *board_out);
394+
395+
/**
396+
* @brief Decode product area into \p fru_product_board_t.
397+
*
398+
* @param[in] area Encoded area.
399+
* @param[out] chassis_out Decoded structure.
400+
* @retval true Success.
401+
* @retval false Failure.
402+
*/
403+
bool fru_decode_product_info(const fru_product_area_t *area, fru_exploded_product_t *product_out);
404+
405+
/**
406+
* Decode data from a buffer into another buffer.
407+
*
408+
* For binary data use FRU_FIELDDATALEN(field->typelen) to find
409+
* out the size of valid bytes in the returned buffer.
410+
*
411+
* @param[in] field Encoded data field.
412+
* @param[out] out Decoded field.
413+
* @param[in] out_len Size of the decoded field region.
414+
* @retval true Success.
415+
* @retval false Failure.
416+
*/
417+
bool fru_decode_data(fru_field_t *field, typed_field_t *out, size_t out_len);
418+
339419
#endif // __FRULIB_FRU_H__

fru_reader.c

Lines changed: 0 additions & 84 deletions
This file was deleted.

fru_reader.h

Lines changed: 0 additions & 5 deletions
This file was deleted.

frugen.c

Lines changed: 37 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#endif
1010

1111
#define COPYRIGHT_YEARS "2016-2021"
12+
#define MAX_FILE_SIZE 1L * 1024L * 1024L
1213

1314
#define _GNU_SOURCE
1415
#include <getopt.h>
@@ -23,14 +24,18 @@
2324
#include <time.h>
2425
#include <errno.h>
2526
#include "fru.h"
26-
#include "fru_reader.h"
2727
#include "smbios.h"
28-
#include "fatal.h"
2928

3029
#ifdef __HAS_JSON__
3130
#include <json-c/json.h>
3231
#endif
3332

33+
#define fatal(fmt, args...) do { \
34+
fprintf(stderr, fmt, ##args); \
35+
fprintf(stderr, "\n"); \
36+
exit(1); \
37+
} while(0)
38+
3439
const char* type_names[] = {
3540
"auto",
3641
"binary",
@@ -749,54 +754,48 @@ int main(int argc, char *argv[])
749754
fatal("Failed to open file: %s", strerror(errno));
750755
}
751756

752-
fru_t *raw_fru = read_fru_header(fd);
753-
if (!raw_fru)
754-
fatal("Failed to read fru header");
757+
struct stat statbuf = {0};
758+
if (fstat(fd, &statbuf)) {
759+
fatal("Failed to get file properties: %s", strerror(errno));
760+
}
761+
if (statbuf.st_size > MAX_FILE_SIZE) {
762+
fatal("File too large");
763+
}
755764

756-
if (raw_fru->chassis != 0) {
757-
if (lseek(fd, 8 * raw_fru->chassis, SEEK_SET) < 0)
758-
fatal("Failed to seek");
765+
uint8_t *buffer = calloc(1, statbuf.st_size);
766+
if (buffer == NULL) {
767+
fatal("Cannot allocate buffer");
768+
}
759769

760-
fru_chassis_area_t *chassis_raw =
761-
read_fru_chassis_area(fd);
762-
bool success = fru_decode_chassis_info(
763-
chassis_raw, &chassis);
764-
if (!success)
765-
fatal("Failed to decode chassis");
770+
if (read(fd, buffer, statbuf.st_size) != statbuf.st_size) {
771+
fatal("Cannot read file");
772+
}
773+
close(fd);
766774

767-
free(chassis_raw);
775+
fru_chassis_area_t *chassis_area =
776+
find_fru_chassis_area(buffer, statbuf.st_size);
777+
if (chassis_area) {
778+
if (!fru_decode_chassis_info(chassis_area, &chassis))
779+
fatal("Failed to decode chassis");
768780
has_chassis = true;
769781
}
770-
if (raw_fru->board != 0) {
771-
if(lseek(fd, 8 * raw_fru->board, SEEK_SET) < 0)
772-
fatal("Failed to seek");
773-
774-
fru_board_area_t *board_raw = read_fru_board_area(fd);
775-
bool success = fru_decode_board_info(board_raw, &board);
776-
if (!success)
782+
fru_board_area_t *board_area =
783+
find_fru_board_area(buffer, statbuf.st_size);
784+
if (board_area) {
785+
if (!fru_decode_board_info(board_area, &board))
777786
fatal("Failed to decode board");
778-
779-
free(board_raw);
780787
has_board = true;
781-
has_bdate = true;
782788
}
783-
if (raw_fru->product != 0) {
784-
if (lseek(fd, 8 * raw_fru->product, SEEK_SET) < 0)
785-
fatal("Failed to seek");
786-
787-
fru_product_area_t *product_raw =
788-
read_fru_product_area(fd);
789-
bool success =
790-
fru_decode_product_info(product_raw, &product);
791-
if (!success)
792-
fatal("Failed to decode product");
793789

794-
free(product_raw);
790+
fru_product_area_t *product_area =
791+
find_fru_product_area(buffer, statbuf.st_size);
792+
if (product_area) {
793+
if (!fru_decode_product_info(product_area, &product))
794+
fatal("Failed to decode product");
795795
has_product = true;
796796
}
797797

798-
free(raw_fru);
799-
close(fd);
798+
free(buffer);
800799
}
801800
else {
802801
fatal("The requested input file format is not supported");

0 commit comments

Comments
 (0)