mirror of
https://github.com/LongSoft/UEFITool.git
synced 2024-11-22 16:08:23 +08:00
UEFIDump 0.1.0 for Windows
- Linux and OSX will be done in next commit
This commit is contained in:
parent
9045fc6cc0
commit
7bae8e040c
@ -11,8 +11,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
#include "uefidump.h"
|
#include "uefidump.h"
|
||||||
#include "../common/ffs.h"
|
#include "../common/ffs.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@ -20,16 +18,29 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
|
||||||
USTATUS UEFIDumper::dump(const UByteArray & buffer, const std::wstring & inPath, const std::wstring & guid)
|
#ifdef WIN32
|
||||||
{
|
#include <direct.h>
|
||||||
//TODO: rework to support relative paths
|
#include <sys/stat.h>
|
||||||
std::wstring path = std::wstring(inPath).append(L".dump2");
|
|
||||||
path = L"\\\\?\\" + path;
|
|
||||||
std::wstring reportPath = std::wstring(inPath).append(L".report2.txt");
|
|
||||||
reportPath = L"\\\\?\\" + reportPath;
|
|
||||||
std::wcout << L"Dump path: " << path << std::endl;
|
|
||||||
std::wcout << L"Report path: " << reportPath << std::endl;
|
|
||||||
|
|
||||||
|
bool isExistOnFs(const UString & path) {
|
||||||
|
struct _stat buf;
|
||||||
|
return (_stat((const char*)path.toLocal8Bit(), &buf) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool makeDirectory(const UString & dir) {
|
||||||
|
return (_mkdir((const char*)dir.toLocal8Bit()) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool changeDirectory(const UString & dir) {
|
||||||
|
return (_chdir((const char*)dir.toLocal8Bit()) == 0);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#endif
|
||||||
|
|
||||||
|
USTATUS UEFIDumper::dump(const UByteArray & buffer, const UString & inPath, const UString & guid)
|
||||||
|
{
|
||||||
|
UString path = UString(inPath) + UString(".dump");
|
||||||
|
UString reportPath = UString(inPath) + UString(".report.txt");
|
||||||
|
|
||||||
if (initialized) {
|
if (initialized) {
|
||||||
// Check if called with a different buffer as before
|
// Check if called with a different buffer as before
|
||||||
@ -99,8 +110,19 @@ USTATUS UEFIDumper::dump(const UByteArray & buffer, const std::wstring & inPath,
|
|||||||
initialized = true;
|
initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check for dump directory existence
|
||||||
|
if (isExistOnFs(path))
|
||||||
|
return U_DIR_ALREADY_EXIST;
|
||||||
|
|
||||||
|
// Create dump directory and cd to it
|
||||||
|
if (!makeDirectory(path))
|
||||||
|
return U_DIR_CREATE;
|
||||||
|
|
||||||
|
if (!changeDirectory(path))
|
||||||
|
return U_DIR_CHANGE;
|
||||||
|
|
||||||
dumped = false;
|
dumped = false;
|
||||||
UINT8 result = recursiveDump(model.index(0,0), path, guid);
|
UINT8 result = recursiveDump(model.index(0,0));
|
||||||
if (result)
|
if (result)
|
||||||
return result;
|
return result;
|
||||||
else if (!dumped)
|
else if (!dumped)
|
||||||
@ -109,77 +131,42 @@ USTATUS UEFIDumper::dump(const UByteArray & buffer, const std::wstring & inPath,
|
|||||||
return U_SUCCESS;
|
return U_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::wstring UEFIDumper::guidToWstring(const EFI_GUID & guid)
|
USTATUS UEFIDumper::recursiveDump(const UModelIndex & index)
|
||||||
{
|
|
||||||
std::wstringstream ws;
|
|
||||||
|
|
||||||
ws << std::hex << std::uppercase << std::setfill(L'0');
|
|
||||||
ws << std::setw(8) << *(const UINT32*)&guid.Data[0] << L"-";
|
|
||||||
ws << std::setw(4) << *(const UINT16*)&guid.Data[4] << L"-";
|
|
||||||
ws << std::setw(4) << *(const UINT16*)&guid.Data[6] << L"-";
|
|
||||||
ws << std::setw(2) << guid.Data[8];
|
|
||||||
ws << std::setw(2) << guid.Data[9] << L"-";
|
|
||||||
ws << std::setw(2) << guid.Data[10];
|
|
||||||
ws << std::setw(2) << guid.Data[11];
|
|
||||||
ws << std::setw(2) << guid.Data[12];
|
|
||||||
ws << std::setw(2) << guid.Data[13];
|
|
||||||
ws << std::setw(2) << guid.Data[14];
|
|
||||||
ws << std::setw(2) << guid.Data[15];
|
|
||||||
|
|
||||||
return ws.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool UEFIDumper::createFullPath(const std::wstring & path) {
|
|
||||||
|
|
||||||
// Break the path into parent\current, assuming the path is already full and converted into Windows native "\\?\" format
|
|
||||||
size_t pos = path.find_last_of(L'\\');
|
|
||||||
|
|
||||||
// Slash is not found, it's a bug
|
|
||||||
if (pos == path.npos)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
std::wstring parent = path.substr(0, pos);
|
|
||||||
std::wstring current = path.substr(pos + 1);
|
|
||||||
|
|
||||||
// Check if first exist, if so, create last and return true
|
|
||||||
UINT32 attributes = GetFileAttributesW(parent.c_str());
|
|
||||||
if ((attributes != INVALID_FILE_ATTRIBUTES) && (attributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
|
||||||
// first is already exist, just create last
|
|
||||||
return CreateDirectoryW(path.c_str(), NULL) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Perform recursive call
|
|
||||||
if (createFullPath(parent))
|
|
||||||
return CreateDirectoryW(path.c_str(), NULL) != 0;
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
USTATUS UEFIDumper::recursiveDump(const UModelIndex & index, const std::wstring & path, const std::wstring & guid)
|
|
||||||
{
|
{
|
||||||
if (!index.isValid())
|
if (!index.isValid())
|
||||||
return U_INVALID_PARAMETER;
|
return U_INVALID_PARAMETER;
|
||||||
|
|
||||||
UByteArray itemHeader = model.header(index);
|
//UByteArray itemHeader = model.header(index);
|
||||||
UByteArray fileHeader = model.header(model.findParentOfType(index, Types::File));
|
//UByteArray fileHeader = model.header(model.findParentOfType(index, Types::File));
|
||||||
|
|
||||||
if (guid.length() == 0 ||
|
//if (guid.length() == 0 ||
|
||||||
(itemHeader.size() >= sizeof (EFI_GUID) && guidToWstring(*(const EFI_GUID*)itemHeader.constData()) == guid) ||
|
// (itemHeader.size() >= sizeof (EFI_GUID) && guidToUString(*(const EFI_GUID*)itemHeader.constData()) == guid) ||
|
||||||
(fileHeader.size() >= sizeof(EFI_GUID) && guidToWstring(*(const EFI_GUID*)fileHeader.constData()) == guid)) {
|
// (fileHeader.size() >= sizeof(EFI_GUID) && guidToUString(*(const EFI_GUID*)fileHeader.constData()) == guid)) {
|
||||||
|
|
||||||
if (SetCurrentDirectoryW(path.c_str()))
|
// Construct file name
|
||||||
return U_DIR_ALREADY_EXIST;
|
UString orgName = uniqueItemName(index);
|
||||||
|
UString name = orgName;
|
||||||
|
bool nameFound = false;
|
||||||
|
for (int i = 0; i < 0x10000; ++i) {
|
||||||
|
if (isExistOnFs(name)) {
|
||||||
|
name = orgName + UString("_") + usprintf("%04X", i);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
nameFound = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!nameFound)
|
||||||
|
return U_INVALID_PARAMETER; //TODO: replace with proper errorCode
|
||||||
|
|
||||||
if (!createFullPath(path))
|
// Add header and body only for leaf sections
|
||||||
return U_DIR_CREATE;
|
if (model.rowCount(index) == 0) {
|
||||||
|
|
||||||
//if (model.rowCount(index) == 0) {
|
|
||||||
// Header
|
// Header
|
||||||
UByteArray data = model.header(index);
|
UByteArray data = model.header(index);
|
||||||
if (!data.isEmpty()) {
|
if (!data.isEmpty()) {
|
||||||
std::ofstream file;
|
std::ofstream file;
|
||||||
std::wstring name = path + std::wstring(L"\\header.bin");
|
std::string str = std::string((const char*)name) + std::string("_header.bin");
|
||||||
file.open(name, std::ios::out | std::ios::binary);
|
file.open(str, std::ios::out | std::ios::binary);
|
||||||
file.write(data.constData(), data.size());
|
file.write(data.constData(), data.size());
|
||||||
file.close();
|
file.close();
|
||||||
}
|
}
|
||||||
@ -188,12 +175,12 @@ USTATUS UEFIDumper::recursiveDump(const UModelIndex & index, const std::wstring
|
|||||||
data = model.body(index);
|
data = model.body(index);
|
||||||
if (!data.isEmpty()) {
|
if (!data.isEmpty()) {
|
||||||
std::ofstream file;
|
std::ofstream file;
|
||||||
std::wstring name = path + std::wstring(L"\\body.bin");
|
std::string str = std::string((const char*)name) + std::string("_body.bin");
|
||||||
file.open(name, std::ios::out | std::ios::binary);
|
file.open(str, std::ios::out | std::ios::binary);
|
||||||
file.write(data.constData(), data.size());
|
file.write(data.constData(), data.size());
|
||||||
file.close();
|
file.close();
|
||||||
}
|
}
|
||||||
//}
|
}
|
||||||
// Info
|
// Info
|
||||||
UString info = "Type: " + itemTypeToUString(model.type(index)) + "\n" +
|
UString info = "Type: " + itemTypeToUString(model.type(index)) + "\n" +
|
||||||
"Subtype: " + itemSubtypeToUString(model.type(index), model.subtype(index)) + "\n";
|
"Subtype: " + itemSubtypeToUString(model.type(index), model.subtype(index)) + "\n";
|
||||||
@ -202,30 +189,18 @@ USTATUS UEFIDumper::recursiveDump(const UModelIndex & index, const std::wstring
|
|||||||
info += model.info(index) + "\n";
|
info += model.info(index) + "\n";
|
||||||
|
|
||||||
std::ofstream file;
|
std::ofstream file;
|
||||||
std::wstring name = path + std::wstring(L"\\info.txt");
|
std::string str = std::string((const char*)name) + std::string("_info.txt");
|
||||||
file.open(name, std::ios::out);
|
file.open(str, std::ios::out);
|
||||||
file.write((const char*)info, info.length());
|
file.write((const char*)info, info.length());
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
dumped = true;
|
dumped = true;
|
||||||
}
|
//}
|
||||||
|
|
||||||
|
// Process child items
|
||||||
UINT8 result;
|
UINT8 result;
|
||||||
for (int i = 0; i < model.rowCount(index); i++) {
|
for (int i = 0; i < model.rowCount(index); i++) {
|
||||||
UModelIndex childIndex = index.child(i, 0);
|
result = recursiveDump(index.child(i, 0));
|
||||||
bool useText = false;
|
|
||||||
if (model.type(childIndex) != Types::Volume)
|
|
||||||
useText = (model.text(childIndex).length() > 0);
|
|
||||||
|
|
||||||
UString name = useText ? (const char *)model.text(childIndex) : (const char *)model.name(childIndex);
|
|
||||||
std::string sName = std::string((const char*)name, name.length());
|
|
||||||
std::wstring childPath = path + std::wstring(L"\\") + std::to_wstring(i) + std::wstring(L" ") + std::wstring(sName.begin(), sName.end());
|
|
||||||
|
|
||||||
// Workaround for paths with dot at the end, just add remove it
|
|
||||||
if (childPath.at(childPath.length() - 1) == L'.')
|
|
||||||
childPath.pop_back();
|
|
||||||
|
|
||||||
result = recursiveDump(childIndex, childPath, guid);
|
|
||||||
if (result)
|
if (result)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -14,8 +14,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||||||
#ifndef UEFIDUMP_H
|
#ifndef UEFIDUMP_H
|
||||||
#define UEFIDUMP_H
|
#define UEFIDUMP_H
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "../common/basetypes.h"
|
#include "../common/basetypes.h"
|
||||||
#include "../common/ustring.h"
|
#include "../common/ustring.h"
|
||||||
#include "../common/treemodel.h"
|
#include "../common/treemodel.h"
|
||||||
@ -30,12 +28,10 @@ public:
|
|||||||
explicit UEFIDumper() : model(), ffsParser(&model), ffsReport(&model), fitParser(&model), currentBuffer(), initialized(false), dumped(false) {}
|
explicit UEFIDumper() : model(), ffsParser(&model), ffsReport(&model), fitParser(&model), currentBuffer(), initialized(false), dumped(false) {}
|
||||||
~UEFIDumper() {}
|
~UEFIDumper() {}
|
||||||
|
|
||||||
USTATUS dump(const UByteArray & buffer, const std::wstring & path, const std::wstring & guid = std::wstring());
|
USTATUS dump(const UByteArray & buffer, const UString & path, const UString & guid = UString());
|
||||||
|
|
||||||
private:
|
private:
|
||||||
USTATUS recursiveDump(const UModelIndex & root, const std::wstring & path, const std::wstring & guid);
|
USTATUS recursiveDump(const UModelIndex & root);
|
||||||
std::wstring guidToWstring(const EFI_GUID & guid);
|
|
||||||
bool createFullPath(const std::wstring & path);
|
|
||||||
|
|
||||||
TreeModel model;
|
TreeModel model;
|
||||||
FfsParser ffsParser;
|
FfsParser ffsParser;
|
||||||
|
@ -15,7 +15,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||||||
|
|
||||||
#include "uefidump.h"
|
#include "uefidump.h"
|
||||||
|
|
||||||
int wmain(int argc, wchar_t *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
if (argc > 32) {
|
if (argc > 32) {
|
||||||
std::cout << "Too many arguments" << std::endl;
|
std::cout << "Too many arguments" << std::endl;
|
||||||
@ -30,12 +30,11 @@ int wmain(int argc, wchar_t *argv[])
|
|||||||
inputFile.close();
|
inputFile.close();
|
||||||
|
|
||||||
UEFIDumper uefidumper;
|
UEFIDumper uefidumper;
|
||||||
return (uefidumper.dump(buffer, std::wstring(argv[1])) != U_SUCCESS);
|
return (uefidumper.dump(buffer, UString(argv[1])) != U_SUCCESS);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
std::cout << "UEFIDump 0.1.0" << std::endl << std::endl
|
std::cout << "UEFIDump 0.1.0" << std::endl << std::endl
|
||||||
<< "Usage: UEFIExtract imagefile " << std::endl
|
<< "Usage: UEFIDump imagefile" << std::endl;
|
||||||
<< "Return value is a bit mask where 0 at position N means that file with GUID_N was found and unpacked, 1 otherwise" << std::endl;
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,7 +362,7 @@ struct CBString : public tagbstring {
|
|||||||
int read (bNread readPtr, void * parm);
|
int read (bNread readPtr, void * parm);
|
||||||
|
|
||||||
// QString compatibility methods
|
// QString compatibility methods
|
||||||
CBString toLocal8Bit() { return *this; }
|
CBString toLocal8Bit() const { return *this; }
|
||||||
bool isEmpty() const { return slen == 0; }
|
bool isEmpty() const { return slen == 0; }
|
||||||
void clear() { *this = ""; }
|
void clear() { *this = ""; }
|
||||||
CBString left(int len) const { return midstr(0, len); }
|
CBString left(int len) const { return midstr(0, len); }
|
||||||
|
@ -53,9 +53,10 @@ typedef uint8_t USTATUS;
|
|||||||
#define U_UNKNOWN_RELOCATION_TYPE 32
|
#define U_UNKNOWN_RELOCATION_TYPE 32
|
||||||
#define U_DIR_ALREADY_EXIST 33
|
#define U_DIR_ALREADY_EXIST 33
|
||||||
#define U_DIR_CREATE 34
|
#define U_DIR_CREATE 34
|
||||||
#define U_TRUNCATED_IMAGE 35
|
#define U_DIR_CHANGE 35
|
||||||
#define U_INVALID_CAPSULE 36
|
#define U_TRUNCATED_IMAGE 36
|
||||||
#define U_STORES_NOT_FOUND 37
|
#define U_INVALID_CAPSULE 37
|
||||||
|
#define U_STORES_NOT_FOUND 38
|
||||||
#define U_NOT_IMPLEMENTED 0xFF
|
#define U_NOT_IMPLEMENTED 0xFF
|
||||||
|
|
||||||
// UDK porting definitions
|
// UDK porting definitions
|
||||||
|
@ -44,6 +44,54 @@ UByteArray parsingDataToUByteArray(const PARSING_DATA & pdata)
|
|||||||
return UByteArray((const char*)&pdata, sizeof(PARSING_DATA));
|
return UByteArray((const char*)&pdata, sizeof(PARSING_DATA));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns unique name string based for tree item
|
||||||
|
UString uniqueItemName(const UModelIndex & index)
|
||||||
|
{
|
||||||
|
// Sanity check
|
||||||
|
if (!index.isValid())
|
||||||
|
return UString("Invalid index");
|
||||||
|
|
||||||
|
// Get model from index
|
||||||
|
const TreeModel* model = index.model();
|
||||||
|
|
||||||
|
// Get data from parsing data
|
||||||
|
PARSING_DATA pdata = parsingDataFromUModelIndex(index);
|
||||||
|
|
||||||
|
// Construct the name
|
||||||
|
UString itemName = model->name(index);
|
||||||
|
UString itemText = model->text(index);
|
||||||
|
|
||||||
|
// Default name
|
||||||
|
UString name = itemName;
|
||||||
|
switch (model->type(index)) {
|
||||||
|
case Types::Volume:
|
||||||
|
if (pdata.volume.hasExtendedHeader) name = guidToUString(pdata.volume.extendedHeaderGuid);
|
||||||
|
break;
|
||||||
|
case Types::NvarEntry:
|
||||||
|
case Types::VssEntry:
|
||||||
|
case Types::FsysEntry:
|
||||||
|
case Types::EvsaEntry:
|
||||||
|
case Types::FlashMapEntry:
|
||||||
|
case Types::File:
|
||||||
|
name = itemText.isEmpty() ? itemName : itemText;
|
||||||
|
break;
|
||||||
|
case Types::Section: {
|
||||||
|
// Get parent file name
|
||||||
|
UModelIndex fileIndex = model->findParentOfType(index, Types::File);
|
||||||
|
UString fileText = model->text(fileIndex);
|
||||||
|
name = fileText.isEmpty() ? model->name(fileIndex) : fileText;
|
||||||
|
// Append section subtype name
|
||||||
|
name += '_' + itemName;
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
|
||||||
|
name.findreplace(' ', '_');
|
||||||
|
name.findreplace('/', '_');
|
||||||
|
name.findreplace('-', '_');
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
// Returns text representation of error code
|
// Returns text representation of error code
|
||||||
UString errorCodeToUString(UINT8 errorCode)
|
UString errorCodeToUString(UINT8 errorCode)
|
||||||
{
|
{
|
||||||
@ -88,6 +136,7 @@ UString errorCodeToUString(UINT8 errorCode)
|
|||||||
case U_COMPLEX_BLOCK_MAP: return UString("Block map structure too complex for correct analysis");
|
case U_COMPLEX_BLOCK_MAP: return UString("Block map structure too complex for correct analysis");
|
||||||
case U_DIR_ALREADY_EXIST: return UString("Directory already exists");
|
case U_DIR_ALREADY_EXIST: return UString("Directory already exists");
|
||||||
case U_DIR_CREATE: return UString("Directory can't be created");
|
case U_DIR_CREATE: return UString("Directory can't be created");
|
||||||
|
case U_DIR_CHANGE: return UString("Change directory failed");
|
||||||
//case U_UNKNOWN_PATCH_TYPE: return UString("Unknown patch type");
|
//case U_UNKNOWN_PATCH_TYPE: return UString("Unknown patch type");
|
||||||
//case U_PATCH_OFFSET_OUT_OF_BOUNDS: return UString("Patch offset out of bounds");
|
//case U_PATCH_OFFSET_OUT_OF_BOUNDS: return UString("Patch offset out of bounds");
|
||||||
//case U_INVALID_SYMBOL: return UString("Invalid symbol");
|
//case U_INVALID_SYMBOL: return UString("Invalid symbol");
|
||||||
|
@ -25,22 +25,25 @@ PARSING_DATA parsingDataFromUModelIndex(const UModelIndex & index);
|
|||||||
// Converts parsing data to byte array
|
// Converts parsing data to byte array
|
||||||
UByteArray parsingDataToUByteArray(const PARSING_DATA & pdata);
|
UByteArray parsingDataToUByteArray(const PARSING_DATA & pdata);
|
||||||
|
|
||||||
|
// Returns unique name string based for tree item
|
||||||
|
UString uniqueItemName(const UModelIndex & index);
|
||||||
|
|
||||||
// Converts error code to UString
|
// Converts error code to UString
|
||||||
extern UString errorCodeToUString(UINT8 errorCode);
|
UString errorCodeToUString(UINT8 errorCode);
|
||||||
|
|
||||||
// Decompression routine
|
// Decompression routine
|
||||||
extern USTATUS decompress(const UByteArray & compressed, UINT8 & algorithm, UByteArray & decompressed, UByteArray & efiDecompressed);
|
USTATUS decompress(const UByteArray & compressed, UINT8 & algorithm, UByteArray & decompressed, UByteArray & efiDecompressed);
|
||||||
|
|
||||||
// Compression routine
|
// Compression routine
|
||||||
//USTATUS compress(const UByteArray & decompressed, UByteArray & compressed, const UINT8 & algorithm);
|
//USTATUS compress(const UByteArray & decompressed, UByteArray & compressed, const UINT8 & algorithm);
|
||||||
|
|
||||||
// CRC32 calculation routine
|
// CRC32 calculation routine
|
||||||
extern UINT32 crc32(UINT32 initial, const UINT8* buffer, const UINT32 length);
|
UINT32 crc32(UINT32 initial, const UINT8* buffer, const UINT32 length);
|
||||||
|
|
||||||
// 8bit checksum calculation routine
|
// 8bit checksum calculation routine
|
||||||
extern UINT8 calculateChecksum8(const UINT8* buffer, UINT32 bufferSize);
|
UINT8 calculateChecksum8(const UINT8* buffer, UINT32 bufferSize);
|
||||||
|
|
||||||
// 16bit checksum calculation routine
|
// 16bit checksum calculation routine
|
||||||
extern UINT16 calculateChecksum16(const UINT16* buffer, UINT32 bufferSize);
|
UINT16 calculateChecksum16(const UINT16* buffer, UINT32 bufferSize);
|
||||||
|
|
||||||
#endif // UTILITY_H
|
#endif // UTILITY_H
|
||||||
|
Loading…
Reference in New Issue
Block a user