Skip to content

Add support for reading from a raw fru dump #28

Open
wants to merge 4 commits into
base: feature/fru-reader
Choose a base branch
from

Conversation

matsievskiysv
Copy link

@matsievskiysv matsievskiysv commented Nov 15, 2022

This is a squashed and rebased PR #9.
It works for the most part, except for custom fields, time and multi-records.

Source file:

{
	/* The internal use area, if specified, must list all the data as hex string,
	   the length is calculated automatically */
	"internal" : "010203040A0B0C0D",
	"chassis" : {
		"type": 10,
		"pn" : "CHAS-C00L-12",
		/* Fields may be given explicit types by setting to object with keys `type` and `data`*/
		/* Supported types are: "bcdplus", "6bitascii" and "text" */
		"serial": {
		    "type": "bcdplus",
		    "data": "45678"
		},
		"custom" : [
			{ "data" : "Auto-typed text custom field" },
			{ "type" : "binary", "data": "B14A87" },
			/* For explicit text types range is not checked, so be careful */
			{ "type" : "bcdplus", "data": "1234" },
			{ "type" : "6bitascii", "data": "1234" },
			{ "type" : "text", "data": "1234" }
		]
	},
	"board" : {
		/* The date, if not specified, will be taken automatically from
		 * the current system time. You may specify the `-u` option to
		 * `frugen` in order to leave the date 'Unspecified' */
		/* "date" : "1/10/2016 3:00:45",*/
		"mfg" : "Biggest International Corp.",
		"pname" : "Some Cool Product",
		"serial" : "123456",
		"pn" : "BRD-PN-345",
		"file" : "example1.json",
		"custom" : [
			{ "type" : "binary", "data" : "0123DEADBABE" },
			{ "type" : "auto",   "data" : "This is a text custom field" },
			{ "type" : "auto",   "data" : "This is test2" }
		]
	},
	"product" : {
		"lang": 1,
		"mfg" : "Super OEM Company",
		"pn" : "PRD-PN-1234",
		"pname" : "Label-engineered Super Product",
		"serial" : "OEM12345",
		"atag" : "Accounting Dept.",
		"ver" : "v1.1",
		"file" : "example2.json",
		"custom" : [
			{ "type" : "auto",   "data" : "Product Custom 1" },
			{ "type" : "auto",   "data" : "PRDCSTM" },
			{ "type" : "auto",   "data" : "PRDCSTM2" },
			{ "type" : "binary", "data" : "C001BEEF" }
		]
	},
	"multirecord" : [
		{ "type" : "management", "subtype" : "uuid", "uuid" : "9bd70799-ccf0-4915-a7f9-7ce7d64385cf" }
	]
}

Is converted using commands:

./build/frugen-static -j -z example.json example.bin
./build/frugen-static -r -z example.bin

Output:

Chassis
        type: 10
        pn(sixbitascii): CHAS-C00L-12
        serial(bcdplus): 45678
        custom: Auto-typed text custom field
        custom:  J
        custom: 4
        custom:  4Q
        custom: 4
Product
        lang: 25
        mfg(text): Super OEM Company
        pname(text): Label-engineered Super Product
        serial(sixbitascii): OEM12345
        pn(sixbitascii): PRD-PN-1234
        ver(text): v1.1
        atag(text): Accounting Dept.
        file(text): example2.json
        custom: Product Custom 1
        custom:  L 3
        custom:  L 3 J
        custom:
Board
        lang: 25
        time: 13/55/2067 08:07:24
        mfg(text): Biggest International Corp.
        pname(text): Some Cool Product
        serial(bcdplus): 123456
        pn(sixbitascii): BRD-PN-345
        file(text): example1.json
        custom: #ޭ
        custom: This is a text custom field
        custom: This is test2
Multirecord

@matsievskiysv
Copy link
Author

Fixed custom fields:

Chassis
	type: 10
	pn(sixbitascii): CHAS-C00L-12
	serial(bcdplus): 45678
	custom(text): Auto-typed text custom field
	custom(binary): b14a87
	custom(bcdplus): 1234
	custom(sixbitascii): 1234
	custom(text): 1234
Product
	lang: 25
	mfg(text): Super OEM Company
	pname(text): Label-engineered Super Product
	serial(sixbitascii): OEM12345
	pn(sixbitascii): PRD-PN-1234
	ver(text): v1.1
	atag(text): Accounting Dept.
	file(text): example2.json
	custom(text): Product Custom 1
	custom(sixbitascii): PRDCSTM
	custom(sixbitascii): PRDCSTM2
	custom(binary): c001beef
Board
	lang: 25
	time: 13/29/2067 10:07:24
	mfg(text): Biggest International Corp.
	pname(text): Some Cool Product
	serial(bcdplus): 123456
	pn(sixbitascii): BRD-PN-345
	file(text): example1.json
	custom(binary): 0123deadbabe
	custom(text): This is a text custom field
	custom(text): This is test2
Multirecord

@matsievskiysv
Copy link
Author

Fixed time decoding:

time: 15/11/2022 09:35:33

@matsievskiysv
Copy link
Author

matsievskiysv commented Nov 15, 2022

I think, the only thing left to do for now is JSON dump.

@matsievskiysv
Copy link
Author

I think, it's ready for review.

Basic command usage

  1. Generate FRU dump from example.json:
fugen-static -j -z example.json example.bin
  1. Parse FRU dump to jq or example2.json
frugen-static -r -z example.bin > example2.json
frugen-static -r -z example.bin | jq
  1. ...
  2. Profit!

More involved example: parse FRU dump, replace one of the fields and save to JSON file

frugen-static -r -z example.bin | jq '.board.file.data |= "otherexample.json"' > otherexample.json

Motivation

The motivation for this is to use ipmitool to dump the current fru contents and then modify/add fields before writing it back. (From #9)

As may be seen from the examples above, dumping parsed data to stdout is more flexible than just using FRU dump in new dump generation:

  • data can be examined
  • data can be easily modified

Further work

Internal area and multi-record parsers are not implemented yet.

@matsievskiysv
Copy link
Author

It's not very convenient to use functions defined in fru_reader.h as they work with file descriptor. It would be more flexible to expose functions that operate on a buffer (and maybe a set of helper functions for file descriptor and/or stream access).

@matsievskiysv
Copy link
Author

Refactored decoder functions a bit for better library API

Copy link
Collaborator

@AlexanderAmelkin AlexanderAmelkin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First of all, thank you for the effort! Then, there are some things I'd like to improve.

fru.c Outdated Show resolved Hide resolved
fru.c Outdated Show resolved Hide resolved
fru.c Show resolved Hide resolved
fru.c Outdated Show resolved Hide resolved
fru.c Outdated Show resolved Hide resolved
fru.h Show resolved Hide resolved
frugen.c Outdated Show resolved Hide resolved
frugen.c Outdated Show resolved Hide resolved
@@ -674,6 +748,55 @@ int main(int argc, char *argv[])
fatal("JSON support was disabled at compile time");
#endif
}
else if (use_binary) {
int fd = open(optarg, O_RDONLY);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this and the above json block need to be extracted into separate functions like load_binary() and load_json() respectively. With a separate commit, as a refactoring.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that these functions belong to fru library.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fair enough

frugen.c Show resolved Hide resolved
@matsievskiysv
Copy link
Author

I've pushed edits, resolving most of the notes. Later, I will squash commits and split changed into separate commits, but first, library API and CLI arguments need to be thought over.

fru.c Outdated Show resolved Hide resolved
fru.c Outdated Show resolved Hide resolved
fru.c Outdated
uint32_t val;
uint8_t arr[4];
} min_since_1996_big_endian;
min_since_1996_big_endian.val = 0;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could as well add = { 0 }; at the end of the declaration above.
I don't insist though.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you don't need to assign 0 to val after min_since_1996_big_endian = {0}, also please make it { 0 }.

frugen.c Show resolved Hide resolved
frugen.c Outdated Show resolved Hide resolved
frugen.c Show resolved Hide resolved
@matsievskiysv
Copy link
Author

frugen is coupled too tight to the fru library, moving parsing functions from frugen to fru requires a lot of changes. This adds to an already big patch. @AlexanderAmelkin, maybe you could create a new branch for the reader feature, so these things could be added one PR at a time?

fru.c Outdated Show resolved Hide resolved
fru.c Outdated Show resolved Hide resolved
fru.c Outdated Show resolved Hide resolved
fru.c Outdated Show resolved Hide resolved
fru.c Outdated Show resolved Hide resolved
fru.c Outdated
uint32_t val;
uint8_t arr[4];
} min_since_1996_big_endian;
min_since_1996_big_endian.val = 0;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you don't need to assign 0 to val after min_since_1996_big_endian = {0}, also please make it { 0 }.

fru.c Outdated

field = (fru_field_t*)data;
if (!fru_decode_data(field, &product_out->mfg,
sizeof(product_out->mfg.val)))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this second line aligned to? I don't see it.
If this is not an alignment, then please use tabs.
When mixing indentation with alignment (like here), please use tabs for indentation and spaces for alignment. That way it wont visually break in editors that use a different tab size:

	if (!fru_decode_data(field, &product_out->mfg,
	                     sizeof(product_out->mfg.val)))

This applies to the below cases as well.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, what you did is not exactly what I meant by 'tabs for indentation, spaces for alignment'.
If you change tab size, this is still going to break.
This is 1 level on indent, hence it must be just 1 tab. The rest must be spaces.

There are lots of other places like this too.

fru.c Outdated Show resolved Hide resolved
frugen.c Outdated
}

free(buffer);
}
else {
fatal("The requested input file format is not supported");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now it looks more like "Please specify the input file format"

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You didn't actually resolve this, did you?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, this edit got lost during the commit split

frugen.c Show resolved Hide resolved
@matsievskiysv
Copy link
Author

I've updated the code according to your comments and split it into separate commits.
The following remains for the following PRs:

  1. Extract JSON and raw reader logic into separate function. This requires a lot of changes because of statically allocated data in the main function. It would be easier to navigate in diff in separate PR.
  2. Change CLI behaviour (from the table in previous messages). It makes sense to do this together with the previous task.

I propose to leave these improvements for the separate PR.

frugen.c Outdated
}

free(buffer);
}
else {
fatal("The requested input file format is not supported");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You didn't actually resolve this, did you?

@AlexanderAmelkin
Copy link
Collaborator

I've updated the code according to your comments and split it into separate commits. The following remains for the following PRs:

  1. Extract JSON and raw reader logic into separate function. This requires a lot of changes because of statically allocated data in the main function. It would be easier to navigate in diff in separate PR.
  2. Change CLI behaviour (from the table in previous messages). It makes sense to do this together with the previous task.

I propose to leave these improvements for the separate PR.

I agree that those changes can go in separate PRs.

@matsievskiysv
Copy link
Author

Since there're a lot of indentation problems, maybe it would be better to add a formatting rules for clang-format or indent.
This is a clang-format file I use for my projects and It's close to the format of the project (drop the .txt extension):
.clang-format.txt

@AlexanderAmelkin
Copy link
Collaborator

Since there're a lot of indentation problems, maybe it would be better to add a formatting rules for clang-format or indent

As far as I'm aware, clang-format doesn't support the concept of 'tabs for indent, spaces for alignment', and I wouldn't like to use any less. If you know how to teach it that, please tell.

I will look into indent's capabilities.

@matsievskiysv
Copy link
Author

clang-format doesn't support the concept of 'tabs for indent, spaces for alignment'

I think it is using it: fru.c.txt

image
image

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants