-
Notifications
You must be signed in to change notification settings - Fork 17
How do I use restruct to deserialize these structs? #5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I've made a quick demonstration. It may not be 100% accurate, sorry if I messed anything up, I've only verified that it reads the header correctly. package main
import (
"encoding/binary"
"flag"
"fmt"
"io/ioutil"
"log"
restruct "gopkg.in/restruct.v1"
)
const (
AtomROMChecksumOffset = 0x21
AtomROMHeaderPtr = 0x48
)
type AtomCommonTableHeader struct {
StructureSize int16
TableFormatRevision byte
TableContentRevision byte
}
type AtomRomHeader struct {
Header AtomCommonTableHeader
FirmWareSignature uint32
BiosRuntimeSegmentAddress uint16
ProtectedModeInfoOffset uint16
ConfigFilenameOffset uint16
CRCBlockOffset uint16
BIOSBootupMessageOffset uint16
Int10Offset uint16
PciBusDevInitCode uint16
IoBaseAddress uint16
SubsystemVendorID uint16
SubsystemID uint16
PCIInfoOffset uint16
MasterCommandTableOffset uint16
MasterDataTableOffset uint16
ExtendedFunctionCode byte
_ byte
PSPDirTableOffset uint32
VendorID uint16
DeviceID uint16
}
type AtomDataTables struct {
Header AtomCommonTableHeader
UtilityPipeLine uint16
MultimediaCapabilityInfo uint16
MultimediaConfigInfo uint16
StandardVESATiming uint16
FirmwareInfo uint16
PaletteData uint16
LCDInfo uint16
DIGTransmitterInfo uint16
SMUInfo uint16
SupportedDevicesInfo uint16
GPIOI2CInfo uint16
VRAMUsageByFirmware uint16
GPIOPinLUT uint16
VESAToInternalModeLUT uint16
GFXInfo uint16
PowerPlayInfo uint16
GPUVirtualizationInfo uint16
SaveRestoreInfo uint16
PPLLSSInfo uint16
OemInfo uint16
XTMDSInfo uint16
MclkSSInfo uint16
ObjectHeader uint16
IndirectIOAccess uint16
MCInitParameter uint16
ASICVDDCInfo uint16
ASICInternalSSInfo uint16
TVVideoMode uint16
VRAMInfo uint16
MemoryTrainingInfo uint16
IntegratedSystemInfo uint16
ASICProfilingInfo uint16
VoltageObjectInfo uint16
PowerSourceInfo uint16
ServiceInfo uint16
}
type AtomPowerplayTable struct {
Header AtomCommonTableHeader
TableRevision byte
TableSize uint16
GoldenPPID uint32
GoldenRevision uint32
FormatID uint16
VoltageTime uint16
PlatformCaps uint32
MaxODEngineClock uint32
MaxODMemoryClock uint32
PowerControlLimit uint16
UlvVoltageOffset uint16
StateArrayOffset uint16
FanTableOffset uint16
ThermalControllerOffset uint16
_ uint16
MclkDependencyTableOffset uint16
SclkDependencyTableOffset uint16
VddcLookupTableOffset uint16
VddgfxLookupTableOffset uint16
MMDependencyTableOffset uint16
VCEStateTableOffset uint16
PPMTableOffset uint16
PowerTuneTableOffset uint16
HardLimitTableOffset uint16
PCIETableOffset uint16
GPIOTableOffset uint16
_ [6]uint16
}
type AtomMClkEntry struct {
VddcInd byte
Vddci uint16
VddgfxOffset uint16
Mvdd uint16
Mclk uint32
_ uint16
}
type AtomMClkTable struct {
RevID byte
NumEntries byte
Entries []AtomMClkEntry ``
}
type AtomSClkEntry struct {
VddInd byte
VddcOffset uint16
Sclk uint32
EdcCurrent uint16
ReliabilityTemperature byte
CKSVOffsetandDisable byte
SclkOffset uint32
// Polaris Only, remove for compatibility with Fiji
}
type AtomSClkTable struct {
RevID byte
NumEntries byte `struct:"sizeof=Entries"`
Entries []AtomSClkEntry
}
type AtomVoltageEntry struct {
Vdd uint16
CACLow uint16
CACMid uint16
CACHigh uint16
}
type AtomVoltageTable struct {
RevID byte
NumEntries byte `struct:"sizeof=Entries"`
Entries []AtomVoltageEntry
}
type AtomFanTable struct {
RevID byte
THyst byte
TMin uint16
TMed uint16
THigh uint16
PWMMin uint16
PWMMed uint16
PWMHigh uint16
TMax uint16
FanControlMode byte
FanPWMMax uint16
FanOutputSensitivity uint16
FanRPMMax uint16
MinFanSCLKAcousticLimit uint32
TargetTemperature byte
MinimumPWMLimit byte
FanGainEdge uint16
FanGainHotspot uint16
FanGainLiquid uint16
FanGainVrVddc uint16
FanGainVrMvdd uint16
FanGainPlx uint16
FanGainHbm uint16
_ uint16
}
type AtomPowertuneTable struct {
RevID byte
TDP uint16
ConfigurableTDP uint16
TDC uint16
BatteryPowerLimit uint16
SmallPowerLimit uint16
LowCACLeakage uint16
HighCACLeakage uint16
MaximumPowerDeliveryLimit uint16
TjMax uint16
PowerTuneDataSetID uint16
EDCLimit uint16
SoftwareShutdownTemp uint16
ClockStretchAmount uint16
TemperatureLimitHotspot uint16
TemperatureLimitLiquid1 uint16
TemperatureLimitLiquid2 uint16
TemperatureLimitVrVddc uint16
TemperatureLimitVrMvdd uint16
TemperatureLimitPlx uint16
Liquid1I2CAddress byte
Liquid2I2CAddress byte
LiquidI2CLine byte
VrI2CAddress byte
VrI2CLine byte
PlxI2CAddress byte
PlxI2CLine byte
_ uint16
}
type AtomVRAMTimingEntry struct {
ClkRange uint32
Latency [0x30]byte
}
type AtomVRAMEntry struct {
ChannelMapCfg uint32
ModuleSize uint16
McRAMCfg uint16
EnableChannels uint16
ExtMemoryID byte
MemoryType byte
ChannelNum byte
ChannelWidth byte
Density byte
BankCol byte
Misc byte
VREFI byte
_ uint16
MemorySize uint16
McTunningSetID byte
RowNum byte
EMRS2Value uint16
EMRS3Value uint16
MemoryVenderID byte
RefreshRateFactor byte
FIFODepth byte
CDRBandwidth byte
ChannelMapCfg1 uint32
BankMapCfg uint32
_ uint32
MemPNString [20]byte
}
type AtomVRAMInfo struct {
Header AtomCommonTableHeader
MemAdjustTblOffset uint16
MemClkPatchTblOffset uint16
McAdjustPerTileTblOffset uint16
McPhyInitTableOffset uint16
DramDataRemapTblOffset uint16
_ uint16
NumOfVRAMModule byte `struct:"sizeof=VramInfo"`
MemoryClkPatchTblVer byte
VramModuleVer byte
McPhyTileNum byte
VramInfo []AtomVRAMEntry
}
func main() {
flag.Parse()
if flag.NArg() != 1 {
log.Println("Usage: <ROM file>")
return
}
fn := flag.Arg(0)
data, err := ioutil.ReadFile(fn)
if err != nil {
log.Fatalln("Error reading ROM file:", err)
}
// Get offset to header
headerOffset := binary.LittleEndian.Uint16(data[AtomROMHeaderPtr : AtomROMHeaderPtr+2])
// Unpack header
header := AtomRomHeader{}
err = restruct.Unpack(data[headerOffset:], binary.LittleEndian, &header)
if err != nil {
log.Fatalln("Error unpacking ROM header:", err)
}
fmt.Printf("HEADER: %#v\n", header)
} Some useful notes:
I hope this will help you get started. I tested it with the RX480 BIOS and was able to get what looked like the header structure. Try it using the demo code above (throw the example into a file in an empty folder, Also, if you are doing so, please be careful when modding your BIOS :) Obviously, I can't provide any warranty as to the correct operation of Restruct, but I wish you the best of luck in your endeavors. |
Holy crap. This was like one of the best answers I've ever gotten on GitHub. You actually googled what I was trying to do and read in a BIOS haha :) You described everything as well! Let me try this out! Thanks so much! |
Why did you have to rename |
No problem. Of course if you find any bugs or other issues feel free to open those separately of this ticket. |
Oh sorry. No I was not forced, I just tried to make it as idiomatic as possible. You can restore those to Reserved if you want to be able to access them, the _ keyword in go is just convenient for when you don't care. |
Okay great, thanks so much again! This seems to be working :) This library really made it so much simpler. |
How would I handle deserializing this part?
|
Hmm... Mostly the same, but it is a little more challenging. We have to go through the chain of structs to get there. I decided to make another demo because it is a little harder than I expected. The worst part is determining the size of the VRAM info structure. I created a new ticket to cover making it simpler to get the binary size of a structure. FWIW, I can't verify that this is actually accurate, so you may want to try to compare this to what Polaris shows for the same ROM. package main
import (
"encoding/binary"
"flag"
"fmt"
"io/ioutil"
"log"
restruct "gopkg.in/restruct.v1"
)
const (
AtomROMChecksumOffset = 0x21
AtomROMHeaderPtr = 0x48
)
type AtomCommonTableHeader struct {
StructureSize int16
TableFormatRevision byte
TableContentRevision byte
}
type AtomRomHeader struct {
Header AtomCommonTableHeader
FirmWareSignature uint32
BiosRuntimeSegmentAddress uint16
ProtectedModeInfoOffset uint16
ConfigFilenameOffset uint16
CRCBlockOffset uint16
BIOSBootupMessageOffset uint16
Int10Offset uint16
PciBusDevInitCode uint16
IoBaseAddress uint16
SubsystemVendorID uint16
SubsystemID uint16
PCIInfoOffset uint16
MasterCommandTableOffset uint16
MasterDataTableOffset uint16
ExtendedFunctionCode byte
_ byte
PSPDirTableOffset uint32
VendorID uint16
DeviceID uint16
}
type AtomDataTables struct {
Header AtomCommonTableHeader
UtilityPipeLine uint16
MultimediaCapabilityInfo uint16
MultimediaConfigInfo uint16
StandardVESATiming uint16
FirmwareInfo uint16
PaletteData uint16
LCDInfo uint16
DIGTransmitterInfo uint16
SMUInfo uint16
SupportedDevicesInfo uint16
GPIOI2CInfo uint16
VRAMUsageByFirmware uint16
GPIOPinLUT uint16
VESAToInternalModeLUT uint16
GFXInfo uint16
PowerPlayInfo uint16
GPUVirtualizationInfo uint16
SaveRestoreInfo uint16
PPLLSSInfo uint16
OemInfo uint16
XTMDSInfo uint16
MclkSSInfo uint16
ObjectHeader uint16
IndirectIOAccess uint16
MCInitParameter uint16
ASICVDDCInfo uint16
ASICInternalSSInfo uint16
TVVideoMode uint16
VRAMInfo uint16
MemoryTrainingInfo uint16
IntegratedSystemInfo uint16
ASICProfilingInfo uint16
VoltageObjectInfo uint16
PowerSourceInfo uint16
ServiceInfo uint16
}
type AtomPowerplayTable struct {
Header AtomCommonTableHeader
TableRevision byte
TableSize uint16
GoldenPPID uint32
GoldenRevision uint32
FormatID uint16
VoltageTime uint16
PlatformCaps uint32
MaxODEngineClock uint32
MaxODMemoryClock uint32
PowerControlLimit uint16
UlvVoltageOffset uint16
StateArrayOffset uint16
FanTableOffset uint16
ThermalControllerOffset uint16
_ uint16
MclkDependencyTableOffset uint16
SclkDependencyTableOffset uint16
VddcLookupTableOffset uint16
VddgfxLookupTableOffset uint16
MMDependencyTableOffset uint16
VCEStateTableOffset uint16
PPMTableOffset uint16
PowerTuneTableOffset uint16
HardLimitTableOffset uint16
PCIETableOffset uint16
GPIOTableOffset uint16
_ [6]uint16
}
type AtomMClkEntry struct {
VddcInd byte
Vddci uint16
VddgfxOffset uint16
Mvdd uint16
Mclk uint32
_ uint16
}
type AtomMClkTable struct {
RevID byte
NumEntries byte
Entries []AtomMClkEntry
}
type AtomSClkEntry struct {
VddInd byte
VddcOffset uint16
Sclk uint32
EdcCurrent uint16
ReliabilityTemperature byte
CKSVOffsetandDisable byte
SclkOffset uint32
// Polaris Only, remove for compatibility with Fiji
}
type AtomSClkTable struct {
RevID byte
NumEntries byte `struct:"sizeof=Entries"`
Entries []AtomSClkEntry
}
type AtomVoltageEntry struct {
Vdd uint16
CACLow uint16
CACMid uint16
CACHigh uint16
}
type AtomVoltageTable struct {
RevID byte
NumEntries byte `struct:"sizeof=Entries"`
Entries []AtomVoltageEntry
}
type AtomFanTable struct {
RevID byte
THyst byte
TMin uint16
TMed uint16
THigh uint16
PWMMin uint16
PWMMed uint16
PWMHigh uint16
TMax uint16
FanControlMode byte
FanPWMMax uint16
FanOutputSensitivity uint16
FanRPMMax uint16
MinFanSCLKAcousticLimit uint32
TargetTemperature byte
MinimumPWMLimit byte
FanGainEdge uint16
FanGainHotspot uint16
FanGainLiquid uint16
FanGainVrVddc uint16
FanGainVrMvdd uint16
FanGainPlx uint16
FanGainHbm uint16
_ uint16
}
type AtomPowertuneTable struct {
RevID byte
TDP uint16
ConfigurableTDP uint16
TDC uint16
BatteryPowerLimit uint16
SmallPowerLimit uint16
LowCACLeakage uint16
HighCACLeakage uint16
MaximumPowerDeliveryLimit uint16
TjMax uint16
PowerTuneDataSetID uint16
EDCLimit uint16
SoftwareShutdownTemp uint16
ClockStretchAmount uint16
TemperatureLimitHotspot uint16
TemperatureLimitLiquid1 uint16
TemperatureLimitLiquid2 uint16
TemperatureLimitVrVddc uint16
TemperatureLimitVrMvdd uint16
TemperatureLimitPlx uint16
Liquid1I2CAddress byte
Liquid2I2CAddress byte
LiquidI2CLine byte
|
Thanks so much for the help again! I think this is working however I've been trying to figure out how to decode some of the fields and I'm a bit stuck at this spot.
This is tripping me up:
|
That part (the Specifically, check this bit in MemPNString string `struct:"[20]byte"` To get just the first 10 characters, you'd simply do To do it without setting the type of the field to MemPNString [20]byte ...you should just be able to do this: |
Oh! That looks simple but I'm getting weird output.
|
Intersting. Looking at the RX480 BIOS with the previously posted example, i'm getting "K4G80325FB" which looks right to me. Could you possibly try my example with your ROM to make sure that the ROM layout isn't differing slightly somewhere? |
Yup! Just did, I pasted your example into my app and ran it instead of my code and it shows the same output for the for loop I pasted above. This ROM is for a RX580 BIOS but Polaris works on it and supports both so this should be working unless there's some offset I'm missing that Polaris is doing. |
Hmmm... this is interesting then. I'll get on my Windows computer later and see what Polaris is doing differently. I've probably made a mistake somewhere. |
I've pushed my more polished implementation of this up to GitHub :) FYI I'm running Polaris via Mono on a Mac, so Windows isn't required. It takes a loooong time to start the first time though. |
OK, thanks, that's actually quite helpful. I'll try to remember to take a look at this tomorrow, I didn't end up getting a look at this tonight. |
No problem! Thank you so very much for all the help :) |
Interesting! So I have 2 RX580 GPU kinds and there's 2 filesizes of ROM's for 580's. One is causing me this error one is not. The VBIOS with https://github.com/jaschaknack/PolarisBiosEditor/blob/master/PolarisBiosEditor.cs#L513 However I'm not sure how this alters reading data from the file. I must be missing an offset somewhere or something? |
I have a feeling the answer lies somewhere else. The way I would go about figuring this out is by instrumenting the Go and C# code with some printf statements that traces out the offsets as determined by each program, all the way up to the top. That way, you would be able to see where it is going awry. That being said, I've been too busy to actually do that. |
No problem! I'm outputting some offsets and there seems to be something off here. In PBE:
In Go code:
Perhaps that len trick isn't working. C#
Go
Aha! It's reporting the wrong size because you added this field to
|
Was that the problem? The C# code was manually decoding However, if it did, feel free to close the issue. I've been working on the deficiencies in the library that we saw here, especially the lack of a |
Uh oh!
There was an error while loading. Please reload this page.
I have these structs from C# that I want to port to Go. How would I handle these custom annotations with restruct?
The text was updated successfully, but these errors were encountered: