frugen icon indicating copy to clipboard operation
frugen copied to clipboard

Add support for reading from a raw fru dump

Open matsievskiysv opened this issue 3 years ago • 13 comments

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 avatar Nov 15 '22 07:11 matsievskiysv

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 avatar Nov 15 '22 11:11 matsievskiysv

Fixed time decoding:

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

matsievskiysv avatar Nov 15 '22 12:11 matsievskiysv

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

matsievskiysv avatar Nov 15 '22 12:11 matsievskiysv

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 avatar Nov 16 '22 07:11 matsievskiysv

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 avatar Nov 18 '22 10:11 matsievskiysv

Refactored decoder functions a bit for better library API

matsievskiysv avatar Nov 21 '22 09:11 matsievskiysv

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.

matsievskiysv avatar Nov 22 '22 17:11 matsievskiysv

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?

matsievskiysv avatar Jan 09 '23 07:01 matsievskiysv

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.

matsievskiysv avatar Jan 12 '23 12:01 matsievskiysv

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.

AlexanderAmelkin avatar Jan 12 '23 13:01 AlexanderAmelkin

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

matsievskiysv avatar Jan 13 '23 04:01 matsievskiysv

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.

AlexanderAmelkin avatar Jan 17 '23 10:01 AlexanderAmelkin

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

matsievskiysv avatar Jan 17 '23 14:01 matsievskiysv