mirror of
https://github.com/LongSoft/UEFITool.git
synced 2024-11-21 15:38:22 +08:00
Version 0.2.0
Initial public commit
This commit is contained in:
commit
4afe74850d
22
.gitattributes
vendored
Normal file
22
.gitattributes
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
# Auto detect text files and perform LF normalization
|
||||
* text=auto
|
||||
|
||||
# Custom for Visual Studio
|
||||
*.cs diff=csharp
|
||||
*.sln merge=union
|
||||
*.csproj merge=union
|
||||
*.vbproj merge=union
|
||||
*.fsproj merge=union
|
||||
*.dbproj merge=union
|
||||
|
||||
# Standard to msysgit
|
||||
*.doc diff=astextplain
|
||||
*.DOC diff=astextplain
|
||||
*.docx diff=astextplain
|
||||
*.DOCX diff=astextplain
|
||||
*.dot diff=astextplain
|
||||
*.DOT diff=astextplain
|
||||
*.pdf diff=astextplain
|
||||
*.PDF diff=astextplain
|
||||
*.rtf diff=astextplain
|
||||
*.RTF diff=astextplain
|
215
.gitignore
vendored
Normal file
215
.gitignore
vendored
Normal file
@ -0,0 +1,215 @@
|
||||
#################
|
||||
## Eclipse
|
||||
#################
|
||||
|
||||
*.pydevproject
|
||||
.project
|
||||
.metadata
|
||||
bin/
|
||||
tmp/
|
||||
*.tmp
|
||||
*.bak
|
||||
*.swp
|
||||
*~.nib
|
||||
local.properties
|
||||
.classpath
|
||||
.settings/
|
||||
.loadpath
|
||||
|
||||
# External tool builders
|
||||
.externalToolBuilders/
|
||||
|
||||
# Locally stored "Eclipse launch configurations"
|
||||
*.launch
|
||||
|
||||
# CDT-specific
|
||||
.cproject
|
||||
|
||||
# PDT-specific
|
||||
.buildpath
|
||||
|
||||
|
||||
#################
|
||||
## Visual Studio
|
||||
#################
|
||||
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
*.sln.docstates
|
||||
|
||||
# Build results
|
||||
|
||||
[Dd]ebug/
|
||||
[Rr]elease/
|
||||
x64/
|
||||
build/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
*_i.c
|
||||
*_p.c
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.log
|
||||
*.scc
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# NCrunch
|
||||
*.ncrunch*
|
||||
.*crunch*.local.xml
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.Publish.xml
|
||||
*.pubxml
|
||||
|
||||
# NuGet Packages Directory
|
||||
## TODO: If you have NuGet Package Restore enabled, uncomment the next line
|
||||
#packages/
|
||||
|
||||
# Windows Azure Build Output
|
||||
csx
|
||||
*.build.csdef
|
||||
|
||||
# Windows Store app package directory
|
||||
AppPackages/
|
||||
|
||||
# Others
|
||||
sql/
|
||||
*.Cache
|
||||
ClientBin/
|
||||
[Ss]tyle[Cc]op.*
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.[Pp]ublish.xml
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file to a newer
|
||||
# Visual Studio version. Backup files are not needed, because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
|
||||
# SQL Server files
|
||||
App_Data/*.mdf
|
||||
App_Data/*.ldf
|
||||
|
||||
#############
|
||||
## Windows detritus
|
||||
#############
|
||||
|
||||
# Windows image file caches
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
|
||||
# Folder config file
|
||||
Desktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Mac crap
|
||||
.DS_Store
|
||||
|
||||
|
||||
#############
|
||||
## Python
|
||||
#############
|
||||
|
||||
*.py[co]
|
||||
|
||||
# Packages
|
||||
*.egg
|
||||
*.egg-info
|
||||
dist/
|
||||
build/
|
||||
eggs/
|
||||
parts/
|
||||
var/
|
||||
sdist/
|
||||
develop-eggs/
|
||||
.installed.cfg
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
.coverage
|
||||
.tox
|
||||
|
||||
#Translations
|
||||
*.mo
|
||||
|
||||
#Mr Developer
|
||||
.mr.developer.cfg
|
BIN
LZMA/._LzmaCompress.c
Normal file
BIN
LZMA/._LzmaCompress.c
Normal file
Binary file not shown.
BIN
LZMA/._LzmaCompress.h
Normal file
BIN
LZMA/._LzmaCompress.h
Normal file
Binary file not shown.
110
LZMA/LzmaCompress.c
Normal file
110
LZMA/LzmaCompress.c
Normal file
@ -0,0 +1,110 @@
|
||||
/* LZMA Compress Implementation
|
||||
|
||||
Copyright (c) 2012, Nikolaj Schlej. All rights reserved.
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
*/
|
||||
|
||||
#include "LzmaCompress.h"
|
||||
#include "Sdk/C/7zVersion.h"
|
||||
#include "Sdk/C/LzmaEnc.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#define LZMA_HEADER_SIZE (LZMA_PROPS_SIZE + 8)
|
||||
|
||||
static void * AllocForLzma(void *p, size_t size) { return malloc(size); }
|
||||
static void FreeForLzma(void *p, void *address) { free(address); }
|
||||
static ISzAlloc SzAllocForLzma = { &AllocForLzma, &FreeForLzma };
|
||||
|
||||
SRes OnProgress(void *p, UInt64 inSize, UInt64 outSize)
|
||||
{
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
static ICompressProgress g_ProgressCallback = { &OnProgress };
|
||||
|
||||
STATIC
|
||||
UINT64
|
||||
EFIAPI
|
||||
RShiftU64 (
|
||||
UINT64 Operand,
|
||||
UINT32 Count
|
||||
)
|
||||
{
|
||||
return Operand >> Count;
|
||||
}
|
||||
|
||||
VOID
|
||||
SetEncodedSizeOfBuf(
|
||||
UINT64 EncodedSize,
|
||||
UINT8 *EncodedData
|
||||
)
|
||||
{
|
||||
INT32 Index;
|
||||
|
||||
EncodedData[LZMA_PROPS_SIZE] = EncodedSize & 0xFF;
|
||||
for (Index = LZMA_PROPS_SIZE+1; Index <= LZMA_PROPS_SIZE + 7; Index++)
|
||||
{
|
||||
EncodedSize = RShiftU64(EncodedSize, 8);
|
||||
EncodedData[Index] = EncodedSize & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
INT32
|
||||
EFIAPI
|
||||
LzmaCompress (
|
||||
CONST VOID *Source,
|
||||
SizeT SourceSize,
|
||||
VOID *Destination,
|
||||
SizeT *DestinationSize
|
||||
)
|
||||
{
|
||||
SRes LzmaResult;
|
||||
CLzmaEncProps props;
|
||||
SizeT propsSize = LZMA_PROPS_SIZE;
|
||||
SizeT destLen = SourceSize + SourceSize / 3 + 128;
|
||||
|
||||
if (*DestinationSize < destLen)
|
||||
{
|
||||
*DestinationSize = destLen;
|
||||
return ERR_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
LzmaEncProps_Init(&props);
|
||||
props.dictSize = LZMA_DICTIONARY_SIZE;
|
||||
props.level = 9;
|
||||
props.fb = 273;
|
||||
|
||||
LzmaResult = LzmaEncode(
|
||||
(Byte*)((UINT8*)Destination + LZMA_HEADER_SIZE),
|
||||
&destLen,
|
||||
Source,
|
||||
SourceSize,
|
||||
&props,
|
||||
(UINT8*)Destination,
|
||||
&propsSize,
|
||||
props.writeEndMark,
|
||||
&g_ProgressCallback,
|
||||
&SzAllocForLzma,
|
||||
&SzAllocForLzma);
|
||||
|
||||
*DestinationSize = destLen + LZMA_HEADER_SIZE;
|
||||
|
||||
SetEncodedSizeOfBuf((UINT64)SourceSize, Destination);
|
||||
|
||||
if (LzmaResult == SZ_OK) {
|
||||
return ERR_SUCCESS;
|
||||
} else {
|
||||
return ERR_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
39
LZMA/LzmaCompress.h
Normal file
39
LZMA/LzmaCompress.h
Normal file
@ -0,0 +1,39 @@
|
||||
/* LZMA Compress Header
|
||||
|
||||
Copyright (c) 2012, Nikolaj Schlej. All rights reserved.
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __LZMACOMPRESS_H__
|
||||
#define __LZMACOMPRESS_H__
|
||||
|
||||
#include "Sdk/C/Types.h"
|
||||
#include "../basetypes.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define LZMA_DICTIONARY_SIZE 0x800000
|
||||
#define _LZMA_SIZE_OPT
|
||||
|
||||
INT32
|
||||
EFIAPI
|
||||
LzmaCompress (
|
||||
const VOID *Source,
|
||||
SizeT SourceSize,
|
||||
VOID *Destination,
|
||||
SizeT *DestinationSize
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
159
LZMA/LzmaDecompress.c
Normal file
159
LZMA/LzmaDecompress.c
Normal file
@ -0,0 +1,159 @@
|
||||
/* LZMA Decompress Implementation
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
*/
|
||||
|
||||
#include "LzmaDecompress.h"
|
||||
#include "Sdk/C/Types.h"
|
||||
#include "Sdk/C/7zVersion.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
UINT64
|
||||
EFIAPI
|
||||
LShiftU64 (
|
||||
UINT64 Operand,
|
||||
UINT32 Count
|
||||
)
|
||||
{
|
||||
return Operand << Count;
|
||||
}
|
||||
|
||||
static void * AllocForLzma(void *p, size_t size) { return malloc(size); }
|
||||
static void FreeForLzma(void *p, void *address) { free(address); }
|
||||
static ISzAlloc SzAllocForLzma = { &AllocForLzma, &FreeForLzma };
|
||||
|
||||
/*
|
||||
Get the size of the uncompressed buffer by parsing EncodeData header.
|
||||
|
||||
@param EncodedData Pointer to the compressed data.
|
||||
|
||||
@return The size of the uncompressed buffer.
|
||||
*/
|
||||
UINT64
|
||||
GetDecodedSizeOfBuf(
|
||||
UINT8 *EncodedData
|
||||
)
|
||||
{
|
||||
UINT64 DecodedSize;
|
||||
INT32 Index;
|
||||
|
||||
// Parse header
|
||||
DecodedSize = 0;
|
||||
for (Index = LZMA_PROPS_SIZE + 7; Index >= LZMA_PROPS_SIZE; Index--)
|
||||
DecodedSize = LShiftU64(DecodedSize, 8) + EncodedData[Index];
|
||||
|
||||
return DecodedSize;
|
||||
}
|
||||
|
||||
//
|
||||
// LZMA functions and data as defined local LzmaDecompressLibInternal.h
|
||||
//
|
||||
|
||||
/*
|
||||
Given a Lzma compressed source buffer, this function retrieves the size of
|
||||
the uncompressed buffer and the size of the scratch buffer required
|
||||
to decompress the compressed source buffer.
|
||||
|
||||
Retrieves the size of the uncompressed buffer and the temporary scratch buffer
|
||||
required to decompress the buffer specified by Source and SourceSize.
|
||||
The size of the uncompressed buffer is returned DestinationSize,
|
||||
the size of the scratch buffer is returned ScratchSize, and RETURN_SUCCESS is returned.
|
||||
This function does not have scratch buffer available to perform a thorough
|
||||
checking of the validity of the source data. It just retrieves the "Original Size"
|
||||
field from the LZMA_HEADER_SIZE beginning bytes of the source data and output it as DestinationSize.
|
||||
And ScratchSize is specific to the decompression implementation.
|
||||
|
||||
If SourceSize is less than LZMA_HEADER_SIZE, then ASSERT().
|
||||
|
||||
@param Source The source buffer containing the compressed data.
|
||||
@param SourceSize The size, bytes, of the source buffer.
|
||||
@param DestinationSize A pointer to the size, bytes, of the uncompressed buffer
|
||||
that will be generated when the compressed buffer specified
|
||||
by Source and SourceSize is decompressed.
|
||||
|
||||
@retval EFI_SUCCESS The size of the uncompressed data was returned
|
||||
DestinationSize and the size of the scratch
|
||||
buffer was returned ScratchSize.
|
||||
|
||||
*/
|
||||
INT32
|
||||
EFIAPI
|
||||
LzmaGetInfo (
|
||||
CONST VOID *Source,
|
||||
UINT32 SourceSize,
|
||||
UINT32 *DestinationSize
|
||||
)
|
||||
{
|
||||
UInt64 DecodedSize;
|
||||
|
||||
ASSERT(SourceSize >= LZMA_HEADER_SIZE);
|
||||
|
||||
DecodedSize = GetDecodedSizeOfBuf((UINT8*)Source);
|
||||
|
||||
*DestinationSize = (UINT32)DecodedSize;
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
Decompresses a Lzma compressed source buffer.
|
||||
|
||||
Extracts decompressed data to its original form.
|
||||
If the compressed source data specified by Source is successfully decompressed
|
||||
into Destination, then RETURN_SUCCESS is returned. If the compressed source data
|
||||
specified by Source is not a valid compressed data format,
|
||||
then RETURN_INVALID_PARAMETER is returned.
|
||||
|
||||
@param Source The source buffer containing the compressed data.
|
||||
@param SourceSize The size of source buffer.
|
||||
@param Destination The destination buffer to store the decompressed data
|
||||
|
||||
@retval EFI_SUCCESS Decompression completed successfully, and
|
||||
the uncompressed buffer is returned Destination.
|
||||
@retval EFI_INVALID_PARAMETER
|
||||
The source buffer specified by Source is corrupted
|
||||
(not a valid compressed format).
|
||||
*/
|
||||
INT32
|
||||
EFIAPI
|
||||
LzmaDecompress (
|
||||
CONST VOID *Source,
|
||||
UINT32 SourceSize,
|
||||
VOID *Destination
|
||||
)
|
||||
{
|
||||
SRes LzmaResult;
|
||||
ELzmaStatus Status;
|
||||
SizeT DecodedBufSize;
|
||||
SizeT EncodedDataSize;
|
||||
|
||||
DecodedBufSize = (SizeT)GetDecodedSizeOfBuf((UINT8*)Source);
|
||||
EncodedDataSize = (SizeT) (SourceSize - LZMA_HEADER_SIZE);
|
||||
|
||||
LzmaResult = LzmaDecode(
|
||||
Destination,
|
||||
&DecodedBufSize,
|
||||
(Byte*)((UINT8*)Source + LZMA_HEADER_SIZE),
|
||||
&EncodedDataSize,
|
||||
Source,
|
||||
LZMA_PROPS_SIZE,
|
||||
LZMA_FINISH_END,
|
||||
&Status,
|
||||
&SzAllocForLzma
|
||||
);
|
||||
|
||||
if (LzmaResult == SZ_OK) {
|
||||
return ERR_SUCCESS;
|
||||
} else {
|
||||
return ERR_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
99
LZMA/LzmaDecompress.h
Normal file
99
LZMA/LzmaDecompress.h
Normal file
@ -0,0 +1,99 @@
|
||||
/* LZMA Decompress Header
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __LZMADECOMPRESS_H__
|
||||
#define __LZMADECOMPRESS_H__
|
||||
|
||||
#include "../basetypes.h"
|
||||
#include "Sdk/C/LzmaDec.h"
|
||||
|
||||
#define LZMA_HEADER_SIZE (LZMA_PROPS_SIZE + 8)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
UINT64
|
||||
EFIAPI
|
||||
LShiftU64 (
|
||||
UINT64 Operand,
|
||||
UINT32 Count
|
||||
);
|
||||
|
||||
/*
|
||||
Given a Lzma compressed source buffer, this function retrieves the size of
|
||||
the uncompressed buffer and the size of the scratch buffer required
|
||||
to decompress the compressed source buffer.
|
||||
|
||||
Retrieves the size of the uncompressed buffer and the temporary scratch buffer
|
||||
required to decompress the buffer specified by Source and SourceSize.
|
||||
The size of the uncompressed buffer is returned DestinationSize,
|
||||
the size of the scratch buffer is returned ScratchSize, and RETURN_SUCCESS is returned.
|
||||
This function does not have scratch buffer available to perform a thorough
|
||||
checking of the validity of the source data. It just retrieves the "Original Size"
|
||||
field from the LZMA_HEADER_SIZE beginning bytes of the source data and output it as DestinationSize.
|
||||
And ScratchSize is specific to the decompression implementation.
|
||||
|
||||
If SourceSize is less than LZMA_HEADER_SIZE, then ASSERT().
|
||||
|
||||
@param Source The source buffer containing the compressed data.
|
||||
@param SourceSize The size, bytes, of the source buffer.
|
||||
@param DestinationSize A pointer to the size, bytes, of the uncompressed buffer
|
||||
that will be generated when the compressed buffer specified
|
||||
by Source and SourceSize is decompressed.
|
||||
|
||||
@retval EFI_SUCCESS The size of the uncompressed data was returned
|
||||
DestinationSize and the size of the scratch
|
||||
buffer was returned ScratchSize.
|
||||
|
||||
*/
|
||||
INT32
|
||||
EFIAPI
|
||||
LzmaGetInfo (
|
||||
const VOID *Source,
|
||||
UINT32 SourceSize,
|
||||
UINT32 *DestinationSize
|
||||
);
|
||||
|
||||
/*
|
||||
Decompresses a Lzma compressed source buffer.
|
||||
|
||||
Extracts decompressed data to its original form.
|
||||
If the compressed source data specified by Source is successfully decompressed
|
||||
into Destination, then RETURN_SUCCESS is returned. If the compressed source data
|
||||
specified by Source is not a valid compressed data format,
|
||||
then RETURN_INVALID_PARAMETER is returned.
|
||||
|
||||
@param Source The source buffer containing the compressed data.
|
||||
@param SourceSize The size of source buffer.
|
||||
@param Destination The destination buffer to store the decompressed data
|
||||
|
||||
@retval EFI_SUCCESS Decompression completed successfully, and
|
||||
the uncompressed buffer is returned Destination.
|
||||
@retval EFI_INVALID_PARAMETER
|
||||
The source buffer specified by Source is corrupted
|
||||
(not a valid compressed format).
|
||||
*/
|
||||
INT32
|
||||
EFIAPI
|
||||
LzmaDecompress (
|
||||
const VOID *Source,
|
||||
UINT32 SourceSize,
|
||||
VOID *Destination
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
7
LZMA/SDK/C/7zVersion.h
Normal file
7
LZMA/SDK/C/7zVersion.h
Normal file
@ -0,0 +1,7 @@
|
||||
#define MY_VER_MAJOR 9
|
||||
#define MY_VER_MINOR 20
|
||||
#define MY_VER_BUILD 0
|
||||
#define MY_VERSION "9.20"
|
||||
#define MY_DATE "2010-11-18"
|
||||
#define MY_COPYRIGHT ": Igor Pavlov : Public domain"
|
||||
#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE
|
68
LZMA/SDK/C/Bra.h
Normal file
68
LZMA/SDK/C/Bra.h
Normal file
@ -0,0 +1,68 @@
|
||||
/* Bra.h -- Branch converters for executables
|
||||
2009-02-07 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __BRA_H
|
||||
#define __BRA_H
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
These functions convert relative addresses to absolute addresses
|
||||
in CALL instructions to increase the compression ratio.
|
||||
|
||||
In:
|
||||
data - data buffer
|
||||
size - size of data
|
||||
ip - current virtual Instruction Pinter (IP) value
|
||||
state - state variable for x86 converter
|
||||
encoding - 0 (for decoding), 1 (for encoding)
|
||||
|
||||
Out:
|
||||
state - state variable for x86 converter
|
||||
|
||||
Returns:
|
||||
The number of processed bytes. If you call these functions with multiple calls,
|
||||
you must start next call with first byte after block of processed bytes.
|
||||
|
||||
Type Endian Alignment LookAhead
|
||||
|
||||
x86 little 1 4
|
||||
ARMT little 2 2
|
||||
ARM little 4 0
|
||||
PPC big 4 0
|
||||
SPARC big 4 0
|
||||
IA64 little 16 0
|
||||
|
||||
size must be >= Alignment + LookAhead, if it's not last block.
|
||||
If (size < Alignment + LookAhead), converter returns 0.
|
||||
|
||||
Example:
|
||||
|
||||
UInt32 ip = 0;
|
||||
for ()
|
||||
{
|
||||
; size must be >= Alignment + LookAhead, if it's not last block
|
||||
SizeT processed = Convert(data, size, ip, 1);
|
||||
data += processed;
|
||||
size -= processed;
|
||||
ip += processed;
|
||||
}
|
||||
*/
|
||||
|
||||
#define x86_Convert_Init(state) { state = 0; }
|
||||
SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding);
|
||||
SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
|
||||
SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
|
||||
SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
|
||||
SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
|
||||
SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
85
LZMA/SDK/C/Bra86.c
Normal file
85
LZMA/SDK/C/Bra86.c
Normal file
@ -0,0 +1,85 @@
|
||||
/* Bra86.c -- Converter for x86 code (BCJ)
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Bra.h"
|
||||
|
||||
#define Test86MSByte(b) ((b) == 0 || (b) == 0xFF)
|
||||
|
||||
const Byte kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0};
|
||||
const Byte kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3};
|
||||
|
||||
SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding)
|
||||
{
|
||||
SizeT bufferPos = 0, prevPosT;
|
||||
UInt32 prevMask = *state & 0x7;
|
||||
if (size < 5)
|
||||
return 0;
|
||||
ip += 5;
|
||||
prevPosT = (SizeT)0 - 1;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
Byte *p = data + bufferPos;
|
||||
Byte *limit = data + size - 4;
|
||||
for (; p < limit; p++)
|
||||
if ((*p & 0xFE) == 0xE8)
|
||||
break;
|
||||
bufferPos = (SizeT)(p - data);
|
||||
if (p >= limit)
|
||||
break;
|
||||
prevPosT = bufferPos - prevPosT;
|
||||
if (prevPosT > 3)
|
||||
prevMask = 0;
|
||||
else
|
||||
{
|
||||
prevMask = (prevMask << ((int)prevPosT - 1)) & 0x7;
|
||||
if (prevMask != 0)
|
||||
{
|
||||
Byte b = p[4 - kMaskToBitNumber[prevMask]];
|
||||
if (!kMaskToAllowedStatus[prevMask] || Test86MSByte(b))
|
||||
{
|
||||
prevPosT = bufferPos;
|
||||
prevMask = ((prevMask << 1) & 0x7) | 1;
|
||||
bufferPos++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
prevPosT = bufferPos;
|
||||
|
||||
if (Test86MSByte(p[4]))
|
||||
{
|
||||
UInt32 src = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]);
|
||||
UInt32 dest;
|
||||
for (;;)
|
||||
{
|
||||
Byte b;
|
||||
int index;
|
||||
if (encoding)
|
||||
dest = (ip + (UInt32)bufferPos) + src;
|
||||
else
|
||||
dest = src - (ip + (UInt32)bufferPos);
|
||||
if (prevMask == 0)
|
||||
break;
|
||||
index = kMaskToBitNumber[prevMask] * 8;
|
||||
b = (Byte)(dest >> (24 - index));
|
||||
if (!Test86MSByte(b))
|
||||
break;
|
||||
src = dest ^ ((1 << (32 - index)) - 1);
|
||||
}
|
||||
p[4] = (Byte)(~(((dest >> 24) & 1) - 1));
|
||||
p[3] = (Byte)(dest >> 16);
|
||||
p[2] = (Byte)(dest >> 8);
|
||||
p[1] = (Byte)dest;
|
||||
bufferPos += 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
prevMask = ((prevMask << 1) & 0x7) | 1;
|
||||
bufferPos++;
|
||||
}
|
||||
}
|
||||
prevPosT = bufferPos - prevPosT;
|
||||
*state = ((prevPosT > 3) ? 0 : ((prevMask << ((int)prevPosT - 1)) & 0x7));
|
||||
return bufferPos;
|
||||
}
|
155
LZMA/SDK/C/CpuArch.h
Normal file
155
LZMA/SDK/C/CpuArch.h
Normal file
@ -0,0 +1,155 @@
|
||||
/* CpuArch.h -- CPU specific code
|
||||
2010-10-26: Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __CPU_ARCH_H
|
||||
#define __CPU_ARCH_H
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
/*
|
||||
MY_CPU_LE means that CPU is LITTLE ENDIAN.
|
||||
If MY_CPU_LE is not defined, we don't know about that property of platform (it can be LITTLE ENDIAN).
|
||||
|
||||
MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned memory accesses.
|
||||
If MY_CPU_LE_UNALIGN is not defined, we don't know about these properties of platform.
|
||||
*/
|
||||
|
||||
#if defined(_M_X64) || defined(_M_AMD64) || defined(__x86_64__)
|
||||
#define MY_CPU_AMD64
|
||||
#endif
|
||||
|
||||
#if defined(MY_CPU_AMD64) || defined(_M_IA64)
|
||||
#define MY_CPU_64BIT
|
||||
#endif
|
||||
|
||||
#if defined(_M_IX86) || defined(__i386__)
|
||||
#define MY_CPU_X86
|
||||
#endif
|
||||
|
||||
#if defined(MY_CPU_X86) || defined(MY_CPU_AMD64)
|
||||
#define MY_CPU_X86_OR_AMD64
|
||||
#endif
|
||||
|
||||
#if defined(MY_CPU_X86) || defined(_M_ARM)
|
||||
#define MY_CPU_32BIT
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && defined(_M_ARM)
|
||||
#define MY_CPU_ARM_LE
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && defined(_M_IA64)
|
||||
#define MY_CPU_IA64_LE
|
||||
#endif
|
||||
|
||||
#if defined(MY_CPU_X86_OR_AMD64)
|
||||
#define MY_CPU_LE_UNALIGN
|
||||
#endif
|
||||
|
||||
#if defined(MY_CPU_X86_OR_AMD64) || defined(MY_CPU_ARM_LE) || defined(MY_CPU_IA64_LE) || defined(__ARMEL__) || defined(__MIPSEL__) || defined(__LITTLE_ENDIAN__)
|
||||
#define MY_CPU_LE
|
||||
#endif
|
||||
|
||||
#if defined(__BIG_ENDIAN__)
|
||||
#define MY_CPU_BE
|
||||
#endif
|
||||
|
||||
#if defined(MY_CPU_LE) && defined(MY_CPU_BE)
|
||||
Stop_Compiling_Bad_Endian
|
||||
#endif
|
||||
|
||||
#ifdef MY_CPU_LE_UNALIGN
|
||||
|
||||
#define GetUi16(p) (*(const UInt16 *)(p))
|
||||
#define GetUi32(p) (*(const UInt32 *)(p))
|
||||
#define GetUi64(p) (*(const UInt64 *)(p))
|
||||
#define SetUi16(p, d) *(UInt16 *)(p) = (d);
|
||||
#define SetUi32(p, d) *(UInt32 *)(p) = (d);
|
||||
#define SetUi64(p, d) *(UInt64 *)(p) = (d);
|
||||
|
||||
#else
|
||||
|
||||
#define GetUi16(p) (((const Byte *)(p))[0] | ((UInt16)((const Byte *)(p))[1] << 8))
|
||||
|
||||
#define GetUi32(p) ( \
|
||||
((const Byte *)(p))[0] | \
|
||||
((UInt32)((const Byte *)(p))[1] << 8) | \
|
||||
((UInt32)((const Byte *)(p))[2] << 16) | \
|
||||
((UInt32)((const Byte *)(p))[3] << 24))
|
||||
|
||||
#define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32))
|
||||
|
||||
#define SetUi16(p, d) { UInt32 _x_ = (d); \
|
||||
((Byte *)(p))[0] = (Byte)_x_; \
|
||||
((Byte *)(p))[1] = (Byte)(_x_ >> 8); }
|
||||
|
||||
#define SetUi32(p, d) { UInt32 _x_ = (d); \
|
||||
((Byte *)(p))[0] = (Byte)_x_; \
|
||||
((Byte *)(p))[1] = (Byte)(_x_ >> 8); \
|
||||
((Byte *)(p))[2] = (Byte)(_x_ >> 16); \
|
||||
((Byte *)(p))[3] = (Byte)(_x_ >> 24); }
|
||||
|
||||
#define SetUi64(p, d) { UInt64 _x64_ = (d); \
|
||||
SetUi32(p, (UInt32)_x64_); \
|
||||
SetUi32(((Byte *)(p)) + 4, (UInt32)(_x64_ >> 32)); }
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(MY_CPU_LE_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300)
|
||||
|
||||
#pragma intrinsic(_byteswap_ulong)
|
||||
#pragma intrinsic(_byteswap_uint64)
|
||||
#define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p))
|
||||
#define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p))
|
||||
|
||||
#else
|
||||
|
||||
#define GetBe32(p) ( \
|
||||
((UInt32)((const Byte *)(p))[0] << 24) | \
|
||||
((UInt32)((const Byte *)(p))[1] << 16) | \
|
||||
((UInt32)((const Byte *)(p))[2] << 8) | \
|
||||
((const Byte *)(p))[3] )
|
||||
|
||||
#define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4))
|
||||
|
||||
#endif
|
||||
|
||||
#define GetBe16(p) (((UInt16)((const Byte *)(p))[0] << 8) | ((const Byte *)(p))[1])
|
||||
|
||||
|
||||
#ifdef MY_CPU_X86_OR_AMD64
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt32 maxFunc;
|
||||
UInt32 vendor[3];
|
||||
UInt32 ver;
|
||||
UInt32 b;
|
||||
UInt32 c;
|
||||
UInt32 d;
|
||||
} Cx86cpuid;
|
||||
|
||||
enum
|
||||
{
|
||||
CPU_FIRM_INTEL,
|
||||
CPU_FIRM_AMD,
|
||||
CPU_FIRM_VIA
|
||||
};
|
||||
|
||||
Bool x86cpuid_CheckAndRead(Cx86cpuid *p);
|
||||
int x86cpuid_GetFirm(const Cx86cpuid *p);
|
||||
|
||||
#define x86cpuid_GetFamily(p) (((p)->ver >> 8) & 0xFF00F)
|
||||
#define x86cpuid_GetModel(p) (((p)->ver >> 4) & 0xF00F)
|
||||
#define x86cpuid_GetStepping(p) ((p)->ver & 0xF)
|
||||
|
||||
Bool CPU_Is_InOrder();
|
||||
Bool CPU_Is_Aes_Supported();
|
||||
|
||||
#endif
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
761
LZMA/SDK/C/LzFind.c
Normal file
761
LZMA/SDK/C/LzFind.c
Normal file
@ -0,0 +1,761 @@
|
||||
/* LzFind.c -- Match finder for LZ algorithms
|
||||
2009-04-22 : Igor Pavlov : Public doma*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "LzFind.h"
|
||||
#include "LzHash.h"
|
||||
|
||||
#define kEmptyHashValue 0
|
||||
#define kMaxValForNormalize ((UInt32)0xFFFFFFFF)
|
||||
#define kNormalizeStepMin (1 << 10) /* it must be power of 2 */
|
||||
#define kNormalizeMask (~(kNormalizeStepMin - 1))
|
||||
#define kMaxHistorySize ((UInt32)3 << 30)
|
||||
|
||||
#define kStartMaxLen 3
|
||||
|
||||
static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc)
|
||||
{
|
||||
if (!p->directInput)
|
||||
{
|
||||
alloc->Free(alloc, p->bufferBase);
|
||||
p->bufferBase = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */
|
||||
|
||||
static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc)
|
||||
{
|
||||
UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv;
|
||||
if (p->directInput)
|
||||
{
|
||||
p->blockSize = blockSize;
|
||||
return 1;
|
||||
}
|
||||
if (p->bufferBase == 0 || p->blockSize != blockSize)
|
||||
{
|
||||
LzInWindow_Free(p, alloc);
|
||||
p->blockSize = blockSize;
|
||||
p->bufferBase = (Byte *)alloc->Alloc(alloc, (size_t)blockSize);
|
||||
}
|
||||
return (p->bufferBase != 0);
|
||||
}
|
||||
|
||||
Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; }
|
||||
Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; }
|
||||
|
||||
UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; }
|
||||
|
||||
void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue)
|
||||
{
|
||||
p->posLimit -= subValue;
|
||||
p->pos -= subValue;
|
||||
p->streamPos -= subValue;
|
||||
}
|
||||
|
||||
static void MatchFinder_ReadBlock(CMatchFinder *p)
|
||||
{
|
||||
if (p->streamEndWasReached || p->result != SZ_OK)
|
||||
return;
|
||||
if (p->directInput)
|
||||
{
|
||||
UInt32 curSize = 0xFFFFFFFF - p->streamPos;
|
||||
if (curSize > p->directInputRem)
|
||||
curSize = (UInt32)p->directInputRem;
|
||||
p->directInputRem -= curSize;
|
||||
p->streamPos += curSize;
|
||||
if (p->directInputRem == 0)
|
||||
p->streamEndWasReached = 1;
|
||||
return;
|
||||
}
|
||||
for (;;)
|
||||
{
|
||||
Byte *dest = p->buffer + (p->streamPos - p->pos);
|
||||
size_t size = (p->bufferBase + p->blockSize - dest);
|
||||
if (size == 0)
|
||||
return;
|
||||
p->result = p->stream->Read(p->stream, dest, &size);
|
||||
if (p->result != SZ_OK)
|
||||
return;
|
||||
if (size == 0)
|
||||
{
|
||||
p->streamEndWasReached = 1;
|
||||
return;
|
||||
}
|
||||
p->streamPos += (UInt32)size;
|
||||
if (p->streamPos - p->pos > p->keepSizeAfter)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void MatchFinder_MoveBlock(CMatchFinder *p)
|
||||
{
|
||||
memmove(p->bufferBase,
|
||||
p->buffer - p->keepSizeBefore,
|
||||
(size_t)(p->streamPos - p->pos + p->keepSizeBefore));
|
||||
p->buffer = p->bufferBase + p->keepSizeBefore;
|
||||
}
|
||||
|
||||
int MatchFinder_NeedMove(CMatchFinder *p)
|
||||
{
|
||||
if (p->directInput)
|
||||
return 0;
|
||||
/* if (p->streamEndWasReached) return 0; */
|
||||
return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter);
|
||||
}
|
||||
|
||||
void MatchFinder_ReadIfRequired(CMatchFinder *p)
|
||||
{
|
||||
if (p->streamEndWasReached)
|
||||
return;
|
||||
if (p->keepSizeAfter >= p->streamPos - p->pos)
|
||||
MatchFinder_ReadBlock(p);
|
||||
}
|
||||
|
||||
static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p)
|
||||
{
|
||||
if (MatchFinder_NeedMove(p))
|
||||
MatchFinder_MoveBlock(p);
|
||||
MatchFinder_ReadBlock(p);
|
||||
}
|
||||
|
||||
static void MatchFinder_SetDefaultSettings(CMatchFinder *p)
|
||||
{
|
||||
p->cutValue = 32;
|
||||
p->btMode = 1;
|
||||
p->numHashBytes = 4;
|
||||
p->bigHash = 0;
|
||||
}
|
||||
|
||||
#define kCrcPoly 0xEDB88320
|
||||
|
||||
void MatchFinder_Construct(CMatchFinder *p)
|
||||
{
|
||||
UInt32 i;
|
||||
p->bufferBase = 0;
|
||||
p->directInput = 0;
|
||||
p->hash = 0;
|
||||
MatchFinder_SetDefaultSettings(p);
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
UInt32 r = i;
|
||||
int j;
|
||||
for (j = 0; j < 8; j++)
|
||||
r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
|
||||
p->crc[i] = r;
|
||||
}
|
||||
}
|
||||
|
||||
static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc)
|
||||
{
|
||||
alloc->Free(alloc, p->hash);
|
||||
p->hash = 0;
|
||||
}
|
||||
|
||||
void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc)
|
||||
{
|
||||
MatchFinder_FreeThisClassMemory(p, alloc);
|
||||
LzInWindow_Free(p, alloc);
|
||||
}
|
||||
|
||||
static CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc)
|
||||
{
|
||||
size_t sizeInBytes = (size_t)num * sizeof(CLzRef);
|
||||
if (sizeInBytes / sizeof(CLzRef) != num)
|
||||
return 0;
|
||||
return (CLzRef *)alloc->Alloc(alloc, sizeInBytes);
|
||||
}
|
||||
|
||||
int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
|
||||
UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
|
||||
ISzAlloc *alloc)
|
||||
{
|
||||
UInt32 sizeReserv;
|
||||
if (historySize > kMaxHistorySize)
|
||||
{
|
||||
MatchFinder_Free(p, alloc);
|
||||
return 0;
|
||||
}
|
||||
sizeReserv = historySize >> 1;
|
||||
if (historySize > ((UInt32)2 << 30))
|
||||
sizeReserv = historySize >> 2;
|
||||
sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19);
|
||||
|
||||
p->keepSizeBefore = historySize + keepAddBufferBefore + 1;
|
||||
p->keepSizeAfter = matchMaxLen + keepAddBufferAfter;
|
||||
/* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */
|
||||
if (LzInWindow_Create(p, sizeReserv, alloc))
|
||||
{
|
||||
UInt32 newCyclicBufferSize = historySize + 1;
|
||||
UInt32 hs;
|
||||
p->matchMaxLen = matchMaxLen;
|
||||
{
|
||||
p->fixedHashSize = 0;
|
||||
if (p->numHashBytes == 2)
|
||||
hs = (1 << 16) - 1;
|
||||
else
|
||||
{
|
||||
hs = historySize - 1;
|
||||
hs |= (hs >> 1);
|
||||
hs |= (hs >> 2);
|
||||
hs |= (hs >> 4);
|
||||
hs |= (hs >> 8);
|
||||
hs >>= 1;
|
||||
hs |= 0xFFFF; /* don't change it! It's required for Deflate */
|
||||
if (hs > (1 << 24))
|
||||
{
|
||||
if (p->numHashBytes == 3)
|
||||
hs = (1 << 24) - 1;
|
||||
else
|
||||
hs >>= 1;
|
||||
}
|
||||
}
|
||||
p->hashMask = hs;
|
||||
hs++;
|
||||
if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size;
|
||||
if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size;
|
||||
if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size;
|
||||
hs += p->fixedHashSize;
|
||||
}
|
||||
|
||||
{
|
||||
UInt32 prevSize = p->hashSizeSum + p->numSons;
|
||||
UInt32 newSize;
|
||||
p->historySize = historySize;
|
||||
p->hashSizeSum = hs;
|
||||
p->cyclicBufferSize = newCyclicBufferSize;
|
||||
p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize);
|
||||
newSize = p->hashSizeSum + p->numSons;
|
||||
if (p->hash != 0 && prevSize == newSize)
|
||||
return 1;
|
||||
MatchFinder_FreeThisClassMemory(p, alloc);
|
||||
p->hash = AllocRefs(newSize, alloc);
|
||||
if (p->hash != 0)
|
||||
{
|
||||
p->son = p->hash + p->hashSizeSum;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
MatchFinder_Free(p, alloc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void MatchFinder_SetLimits(CMatchFinder *p)
|
||||
{
|
||||
UInt32 limit = kMaxValForNormalize - p->pos;
|
||||
UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos;
|
||||
if (limit2 < limit)
|
||||
limit = limit2;
|
||||
limit2 = p->streamPos - p->pos;
|
||||
if (limit2 <= p->keepSizeAfter)
|
||||
{
|
||||
if (limit2 > 0)
|
||||
limit2 = 1;
|
||||
}
|
||||
else
|
||||
limit2 -= p->keepSizeAfter;
|
||||
if (limit2 < limit)
|
||||
limit = limit2;
|
||||
{
|
||||
UInt32 lenLimit = p->streamPos - p->pos;
|
||||
if (lenLimit > p->matchMaxLen)
|
||||
lenLimit = p->matchMaxLen;
|
||||
p->lenLimit = lenLimit;
|
||||
}
|
||||
p->posLimit = p->pos + limit;
|
||||
}
|
||||
|
||||
void MatchFinder_Init(CMatchFinder *p)
|
||||
{
|
||||
UInt32 i;
|
||||
for (i = 0; i < p->hashSizeSum; i++)
|
||||
p->hash[i] = kEmptyHashValue;
|
||||
p->cyclicBufferPos = 0;
|
||||
p->buffer = p->bufferBase;
|
||||
p->pos = p->streamPos = p->cyclicBufferSize;
|
||||
p->result = SZ_OK;
|
||||
p->streamEndWasReached = 0;
|
||||
MatchFinder_ReadBlock(p);
|
||||
MatchFinder_SetLimits(p);
|
||||
}
|
||||
|
||||
static UInt32 MatchFinder_GetSubValue(CMatchFinder *p)
|
||||
{
|
||||
return (p->pos - p->historySize - 1) & kNormalizeMask;
|
||||
}
|
||||
|
||||
void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems)
|
||||
{
|
||||
UInt32 i;
|
||||
for (i = 0; i < numItems; i++)
|
||||
{
|
||||
UInt32 value = items[i];
|
||||
if (value <= subValue)
|
||||
value = kEmptyHashValue;
|
||||
else
|
||||
value -= subValue;
|
||||
items[i] = value;
|
||||
}
|
||||
}
|
||||
|
||||
static void MatchFinder_Normalize(CMatchFinder *p)
|
||||
{
|
||||
UInt32 subValue = MatchFinder_GetSubValue(p);
|
||||
MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons);
|
||||
MatchFinder_ReduceOffsets(p, subValue);
|
||||
}
|
||||
|
||||
static void MatchFinder_CheckLimits(CMatchFinder *p)
|
||||
{
|
||||
if (p->pos == kMaxValForNormalize)
|
||||
MatchFinder_Normalize(p);
|
||||
if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos)
|
||||
MatchFinder_CheckAndMoveAndRead(p);
|
||||
if (p->cyclicBufferPos == p->cyclicBufferSize)
|
||||
p->cyclicBufferPos = 0;
|
||||
MatchFinder_SetLimits(p);
|
||||
}
|
||||
|
||||
static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
|
||||
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
|
||||
UInt32 *distances, UInt32 maxLen)
|
||||
{
|
||||
son[_cyclicBufferPos] = curMatch;
|
||||
for (;;)
|
||||
{
|
||||
UInt32 delta = pos - curMatch;
|
||||
if (cutValue-- == 0 || delta >= _cyclicBufferSize)
|
||||
return distances;
|
||||
{
|
||||
const Byte *pb = cur - delta;
|
||||
curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)];
|
||||
if (pb[maxLen] == cur[maxLen] && *pb == *cur)
|
||||
{
|
||||
UInt32 len = 0;
|
||||
while (++len != lenLimit)
|
||||
if (pb[len] != cur[len])
|
||||
break;
|
||||
if (maxLen < len)
|
||||
{
|
||||
*distances++ = maxLen = len;
|
||||
*distances++ = delta - 1;
|
||||
if (len == lenLimit)
|
||||
return distances;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
|
||||
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
|
||||
UInt32 *distances, UInt32 maxLen)
|
||||
{
|
||||
CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
|
||||
CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
|
||||
UInt32 len0 = 0, len1 = 0;
|
||||
for (;;)
|
||||
{
|
||||
UInt32 delta = pos - curMatch;
|
||||
if (cutValue-- == 0 || delta >= _cyclicBufferSize)
|
||||
{
|
||||
*ptr0 = *ptr1 = kEmptyHashValue;
|
||||
return distances;
|
||||
}
|
||||
{
|
||||
CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
|
||||
const Byte *pb = cur - delta;
|
||||
UInt32 len = (len0 < len1 ? len0 : len1);
|
||||
if (pb[len] == cur[len])
|
||||
{
|
||||
if (++len != lenLimit && pb[len] == cur[len])
|
||||
while (++len != lenLimit)
|
||||
if (pb[len] != cur[len])
|
||||
break;
|
||||
if (maxLen < len)
|
||||
{
|
||||
*distances++ = maxLen = len;
|
||||
*distances++ = delta - 1;
|
||||
if (len == lenLimit)
|
||||
{
|
||||
*ptr1 = pair[0];
|
||||
*ptr0 = pair[1];
|
||||
return distances;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pb[len] < cur[len])
|
||||
{
|
||||
*ptr1 = curMatch;
|
||||
ptr1 = pair + 1;
|
||||
curMatch = *ptr1;
|
||||
len1 = len;
|
||||
}
|
||||
else
|
||||
{
|
||||
*ptr0 = curMatch;
|
||||
ptr0 = pair;
|
||||
curMatch = *ptr0;
|
||||
len0 = len;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
|
||||
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue)
|
||||
{
|
||||
CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
|
||||
CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
|
||||
UInt32 len0 = 0, len1 = 0;
|
||||
for (;;)
|
||||
{
|
||||
UInt32 delta = pos - curMatch;
|
||||
if (cutValue-- == 0 || delta >= _cyclicBufferSize)
|
||||
{
|
||||
*ptr0 = *ptr1 = kEmptyHashValue;
|
||||
return;
|
||||
}
|
||||
{
|
||||
CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
|
||||
const Byte *pb = cur - delta;
|
||||
UInt32 len = (len0 < len1 ? len0 : len1);
|
||||
if (pb[len] == cur[len])
|
||||
{
|
||||
while (++len != lenLimit)
|
||||
if (pb[len] != cur[len])
|
||||
break;
|
||||
{
|
||||
if (len == lenLimit)
|
||||
{
|
||||
*ptr1 = pair[0];
|
||||
*ptr0 = pair[1];
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pb[len] < cur[len])
|
||||
{
|
||||
*ptr1 = curMatch;
|
||||
ptr1 = pair + 1;
|
||||
curMatch = *ptr1;
|
||||
len1 = len;
|
||||
}
|
||||
else
|
||||
{
|
||||
*ptr0 = curMatch;
|
||||
ptr0 = pair;
|
||||
curMatch = *ptr0;
|
||||
len0 = len;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define MOVE_POS \
|
||||
++p->cyclicBufferPos; \
|
||||
p->buffer++; \
|
||||
if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p);
|
||||
|
||||
#define MOVE_POS_RET MOVE_POS return offset;
|
||||
|
||||
static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; }
|
||||
|
||||
#define GET_MATCHES_HEADER2(minLen, ret_op) \
|
||||
UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \
|
||||
lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \
|
||||
cur = p->buffer;
|
||||
|
||||
#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0)
|
||||
#define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue)
|
||||
|
||||
#define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue
|
||||
|
||||
#define GET_MATCHES_FOOTER(offset, maxLen) \
|
||||
offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \
|
||||
distances + offset, maxLen) - distances); MOVE_POS_RET;
|
||||
|
||||
#define SKIP_FOOTER \
|
||||
SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS;
|
||||
|
||||
static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
|
||||
{
|
||||
UInt32 offset;
|
||||
GET_MATCHES_HEADER(2)
|
||||
HASH2_CALC;
|
||||
curMatch = p->hash[hashValue];
|
||||
p->hash[hashValue] = p->pos;
|
||||
offset = 0;
|
||||
GET_MATCHES_FOOTER(offset, 1)
|
||||
}
|
||||
|
||||
UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
|
||||
{
|
||||
UInt32 offset;
|
||||
GET_MATCHES_HEADER(3)
|
||||
HASH_ZIP_CALC;
|
||||
curMatch = p->hash[hashValue];
|
||||
p->hash[hashValue] = p->pos;
|
||||
offset = 0;
|
||||
GET_MATCHES_FOOTER(offset, 2)
|
||||
}
|
||||
|
||||
static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
|
||||
{
|
||||
UInt32 hash2Value, delta2, maxLen, offset;
|
||||
GET_MATCHES_HEADER(3)
|
||||
|
||||
HASH3_CALC;
|
||||
|
||||
delta2 = p->pos - p->hash[hash2Value];
|
||||
curMatch = p->hash[kFix3HashSize + hashValue];
|
||||
|
||||
p->hash[hash2Value] =
|
||||
p->hash[kFix3HashSize + hashValue] = p->pos;
|
||||
|
||||
|
||||
maxLen = 2;
|
||||
offset = 0;
|
||||
if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
|
||||
{
|
||||
for (; maxLen != lenLimit; maxLen++)
|
||||
if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
|
||||
break;
|
||||
distances[0] = maxLen;
|
||||
distances[1] = delta2 - 1;
|
||||
offset = 2;
|
||||
if (maxLen == lenLimit)
|
||||
{
|
||||
SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
|
||||
MOVE_POS_RET;
|
||||
}
|
||||
}
|
||||
GET_MATCHES_FOOTER(offset, maxLen)
|
||||
}
|
||||
|
||||
static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
|
||||
{
|
||||
UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset;
|
||||
GET_MATCHES_HEADER(4)
|
||||
|
||||
HASH4_CALC;
|
||||
|
||||
delta2 = p->pos - p->hash[ hash2Value];
|
||||
delta3 = p->pos - p->hash[kFix3HashSize + hash3Value];
|
||||
curMatch = p->hash[kFix4HashSize + hashValue];
|
||||
|
||||
p->hash[ hash2Value] =
|
||||
p->hash[kFix3HashSize + hash3Value] =
|
||||
p->hash[kFix4HashSize + hashValue] = p->pos;
|
||||
|
||||
maxLen = 1;
|
||||
offset = 0;
|
||||
if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
|
||||
{
|
||||
distances[0] = maxLen = 2;
|
||||
distances[1] = delta2 - 1;
|
||||
offset = 2;
|
||||
}
|
||||
if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)
|
||||
{
|
||||
maxLen = 3;
|
||||
distances[offset + 1] = delta3 - 1;
|
||||
offset += 2;
|
||||
delta2 = delta3;
|
||||
}
|
||||
if (offset != 0)
|
||||
{
|
||||
for (; maxLen != lenLimit; maxLen++)
|
||||
if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
|
||||
break;
|
||||
distances[offset - 2] = maxLen;
|
||||
if (maxLen == lenLimit)
|
||||
{
|
||||
SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
|
||||
MOVE_POS_RET;
|
||||
}
|
||||
}
|
||||
if (maxLen < 3)
|
||||
maxLen = 3;
|
||||
GET_MATCHES_FOOTER(offset, maxLen)
|
||||
}
|
||||
|
||||
static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
|
||||
{
|
||||
UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset;
|
||||
GET_MATCHES_HEADER(4)
|
||||
|
||||
HASH4_CALC;
|
||||
|
||||
delta2 = p->pos - p->hash[ hash2Value];
|
||||
delta3 = p->pos - p->hash[kFix3HashSize + hash3Value];
|
||||
curMatch = p->hash[kFix4HashSize + hashValue];
|
||||
|
||||
p->hash[ hash2Value] =
|
||||
p->hash[kFix3HashSize + hash3Value] =
|
||||
p->hash[kFix4HashSize + hashValue] = p->pos;
|
||||
|
||||
maxLen = 1;
|
||||
offset = 0;
|
||||
if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
|
||||
{
|
||||
distances[0] = maxLen = 2;
|
||||
distances[1] = delta2 - 1;
|
||||
offset = 2;
|
||||
}
|
||||
if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)
|
||||
{
|
||||
maxLen = 3;
|
||||
distances[offset + 1] = delta3 - 1;
|
||||
offset += 2;
|
||||
delta2 = delta3;
|
||||
}
|
||||
if (offset != 0)
|
||||
{
|
||||
for (; maxLen != lenLimit; maxLen++)
|
||||
if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
|
||||
break;
|
||||
distances[offset - 2] = maxLen;
|
||||
if (maxLen == lenLimit)
|
||||
{
|
||||
p->son[p->cyclicBufferPos] = curMatch;
|
||||
MOVE_POS_RET;
|
||||
}
|
||||
}
|
||||
if (maxLen < 3)
|
||||
maxLen = 3;
|
||||
offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
|
||||
distances + offset, maxLen) - (distances));
|
||||
MOVE_POS_RET
|
||||
}
|
||||
|
||||
UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
|
||||
{
|
||||
UInt32 offset;
|
||||
GET_MATCHES_HEADER(3)
|
||||
HASH_ZIP_CALC;
|
||||
curMatch = p->hash[hashValue];
|
||||
p->hash[hashValue] = p->pos;
|
||||
offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
|
||||
distances, 2) - (distances));
|
||||
MOVE_POS_RET
|
||||
}
|
||||
|
||||
static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
|
||||
{
|
||||
do
|
||||
{
|
||||
SKIP_HEADER(2)
|
||||
HASH2_CALC;
|
||||
curMatch = p->hash[hashValue];
|
||||
p->hash[hashValue] = p->pos;
|
||||
SKIP_FOOTER
|
||||
}
|
||||
while (--num != 0);
|
||||
}
|
||||
|
||||
void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
|
||||
{
|
||||
do
|
||||
{
|
||||
SKIP_HEADER(3)
|
||||
HASH_ZIP_CALC;
|
||||
curMatch = p->hash[hashValue];
|
||||
p->hash[hashValue] = p->pos;
|
||||
SKIP_FOOTER
|
||||
}
|
||||
while (--num != 0);
|
||||
}
|
||||
|
||||
static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
|
||||
{
|
||||
do
|
||||
{
|
||||
UInt32 hash2Value;
|
||||
SKIP_HEADER(3)
|
||||
HASH3_CALC;
|
||||
curMatch = p->hash[kFix3HashSize + hashValue];
|
||||
p->hash[hash2Value] =
|
||||
p->hash[kFix3HashSize + hashValue] = p->pos;
|
||||
SKIP_FOOTER
|
||||
}
|
||||
while (--num != 0);
|
||||
}
|
||||
|
||||
static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
|
||||
{
|
||||
do
|
||||
{
|
||||
UInt32 hash2Value, hash3Value;
|
||||
SKIP_HEADER(4)
|
||||
HASH4_CALC;
|
||||
curMatch = p->hash[kFix4HashSize + hashValue];
|
||||
p->hash[ hash2Value] =
|
||||
p->hash[kFix3HashSize + hash3Value] = p->pos;
|
||||
p->hash[kFix4HashSize + hashValue] = p->pos;
|
||||
SKIP_FOOTER
|
||||
}
|
||||
while (--num != 0);
|
||||
}
|
||||
|
||||
static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
|
||||
{
|
||||
do
|
||||
{
|
||||
UInt32 hash2Value, hash3Value;
|
||||
SKIP_HEADER(4)
|
||||
HASH4_CALC;
|
||||
curMatch = p->hash[kFix4HashSize + hashValue];
|
||||
p->hash[ hash2Value] =
|
||||
p->hash[kFix3HashSize + hash3Value] =
|
||||
p->hash[kFix4HashSize + hashValue] = p->pos;
|
||||
p->son[p->cyclicBufferPos] = curMatch;
|
||||
MOVE_POS
|
||||
}
|
||||
while (--num != 0);
|
||||
}
|
||||
|
||||
void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
|
||||
{
|
||||
do
|
||||
{
|
||||
SKIP_HEADER(3)
|
||||
HASH_ZIP_CALC;
|
||||
curMatch = p->hash[hashValue];
|
||||
p->hash[hashValue] = p->pos;
|
||||
p->son[p->cyclicBufferPos] = curMatch;
|
||||
MOVE_POS
|
||||
}
|
||||
while (--num != 0);
|
||||
}
|
||||
|
||||
void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable)
|
||||
{
|
||||
vTable->Init = (Mf_Init_Func)MatchFinder_Init;
|
||||
vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte;
|
||||
vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes;
|
||||
vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos;
|
||||
if (!p->btMode)
|
||||
{
|
||||
vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches;
|
||||
vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip;
|
||||
}
|
||||
else if (p->numHashBytes == 2)
|
||||
{
|
||||
vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches;
|
||||
vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip;
|
||||
}
|
||||
else if (p->numHashBytes == 3)
|
||||
{
|
||||
vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches;
|
||||
vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip;
|
||||
}
|
||||
else
|
||||
{
|
||||
vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches;
|
||||
vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip;
|
||||
}
|
||||
}
|
115
LZMA/SDK/C/LzFind.h
Normal file
115
LZMA/SDK/C/LzFind.h
Normal file
@ -0,0 +1,115 @@
|
||||
/* LzFind.h -- Match finder for LZ algorithms
|
||||
2009-04-22 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __LZ_FIND_H
|
||||
#define __LZ_FIND_H
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef UInt32 CLzRef;
|
||||
|
||||
typedef struct _CMatchFinder
|
||||
{
|
||||
Byte *buffer;
|
||||
UInt32 pos;
|
||||
UInt32 posLimit;
|
||||
UInt32 streamPos;
|
||||
UInt32 lenLimit;
|
||||
|
||||
UInt32 cyclicBufferPos;
|
||||
UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */
|
||||
|
||||
UInt32 matchMaxLen;
|
||||
CLzRef *hash;
|
||||
CLzRef *son;
|
||||
UInt32 hashMask;
|
||||
UInt32 cutValue;
|
||||
|
||||
Byte *bufferBase;
|
||||
ISeqInStream *stream;
|
||||
int streamEndWasReached;
|
||||
|
||||
UInt32 blockSize;
|
||||
UInt32 keepSizeBefore;
|
||||
UInt32 keepSizeAfter;
|
||||
|
||||
UInt32 numHashBytes;
|
||||
int directInput;
|
||||
size_t directInputRem;
|
||||
int btMode;
|
||||
int bigHash;
|
||||
UInt32 historySize;
|
||||
UInt32 fixedHashSize;
|
||||
UInt32 hashSizeSum;
|
||||
UInt32 numSons;
|
||||
SRes result;
|
||||
UInt32 crc[256];
|
||||
} CMatchFinder;
|
||||
|
||||
#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer)
|
||||
#define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)])
|
||||
|
||||
#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos)
|
||||
|
||||
int MatchFinder_NeedMove(CMatchFinder *p);
|
||||
Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p);
|
||||
void MatchFinder_MoveBlock(CMatchFinder *p);
|
||||
void MatchFinder_ReadIfRequired(CMatchFinder *p);
|
||||
|
||||
void MatchFinder_Construct(CMatchFinder *p);
|
||||
|
||||
/* Conditions:
|
||||
historySize <= 3 GB
|
||||
keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB
|
||||
*/
|
||||
int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
|
||||
UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
|
||||
ISzAlloc *alloc);
|
||||
void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc);
|
||||
void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems);
|
||||
void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue);
|
||||
|
||||
UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son,
|
||||
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
|
||||
UInt32 *distances, UInt32 maxLen);
|
||||
|
||||
/*
|
||||
Conditions:
|
||||
Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func.
|
||||
Mf_GetPointerToCurrentPos_Func's result must be used only before any other function
|
||||
*/
|
||||
|
||||
typedef void (*Mf_Init_Func)(void *object);
|
||||
typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index);
|
||||
typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object);
|
||||
typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object);
|
||||
typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances);
|
||||
typedef void (*Mf_Skip_Func)(void *object, UInt32);
|
||||
|
||||
typedef struct _IMatchFinder
|
||||
{
|
||||
Mf_Init_Func Init;
|
||||
Mf_GetIndexByte_Func GetIndexByte;
|
||||
Mf_GetNumAvailableBytes_Func GetNumAvailableBytes;
|
||||
Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos;
|
||||
Mf_GetMatches_Func GetMatches;
|
||||
Mf_Skip_Func Skip;
|
||||
} IMatchFinder;
|
||||
|
||||
void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable);
|
||||
|
||||
void MatchFinder_Init(CMatchFinder *p);
|
||||
UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
|
||||
UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
|
||||
void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
|
||||
void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
54
LZMA/SDK/C/LzHash.h
Normal file
54
LZMA/SDK/C/LzHash.h
Normal file
@ -0,0 +1,54 @@
|
||||
/* LzHash.h -- HASH functions for LZ algorithms
|
||||
2009-02-07 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __LZ_HASH_H
|
||||
#define __LZ_HASH_H
|
||||
|
||||
#define kHash2Size (1 << 10)
|
||||
#define kHash3Size (1 << 16)
|
||||
#define kHash4Size (1 << 20)
|
||||
|
||||
#define kFix3HashSize (kHash2Size)
|
||||
#define kFix4HashSize (kHash2Size + kHash3Size)
|
||||
#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size)
|
||||
|
||||
#define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8);
|
||||
|
||||
#define HASH3_CALC { \
|
||||
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
|
||||
hash2Value = temp & (kHash2Size - 1); \
|
||||
hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; }
|
||||
|
||||
#define HASH4_CALC { \
|
||||
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
|
||||
hash2Value = temp & (kHash2Size - 1); \
|
||||
hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
|
||||
hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & p->hashMask; }
|
||||
|
||||
#define HASH5_CALC { \
|
||||
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
|
||||
hash2Value = temp & (kHash2Size - 1); \
|
||||
hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
|
||||
hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)); \
|
||||
hashValue = (hash4Value ^ (p->crc[cur[4]] << 3)) & p->hashMask; \
|
||||
hash4Value &= (kHash4Size - 1); }
|
||||
|
||||
/* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */
|
||||
#define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF;
|
||||
|
||||
|
||||
#define MT_HASH2_CALC \
|
||||
hash2Value = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1);
|
||||
|
||||
#define MT_HASH3_CALC { \
|
||||
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
|
||||
hash2Value = temp & (kHash2Size - 1); \
|
||||
hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); }
|
||||
|
||||
#define MT_HASH4_CALC { \
|
||||
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
|
||||
hash2Value = temp & (kHash2Size - 1); \
|
||||
hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
|
||||
hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); }
|
||||
|
||||
#endif
|
999
LZMA/SDK/C/LzmaDec.c
Normal file
999
LZMA/SDK/C/LzmaDec.c
Normal file
@ -0,0 +1,999 @@
|
||||
/* LzmaDec.c -- LZMA Decoder
|
||||
2009-09-20 : Igor Pavlov : Public doma*/
|
||||
|
||||
#include "LzmaDec.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define kNumTopBits 24
|
||||
#define kTopValue ((UInt32)1 << kNumTopBits)
|
||||
|
||||
#define kNumBitModelTotalBits 11
|
||||
#define kBitModelTotal (1 << kNumBitModelTotalBits)
|
||||
#define kNumMoveBits 5
|
||||
|
||||
#define RC_INIT_SIZE 5
|
||||
|
||||
#define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); }
|
||||
|
||||
#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
|
||||
#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
|
||||
#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits));
|
||||
#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \
|
||||
{ UPDATE_0(p); i = (i + i); A0; } else \
|
||||
{ UPDATE_1(p); i = (i + i) + 1; A1; }
|
||||
#define GET_BIT(p, i) GET_BIT2(p, i, ; , ;)
|
||||
|
||||
#define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); }
|
||||
#define TREE_DECODE(probs, limit, i) \
|
||||
{ i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; }
|
||||
|
||||
/* #define _LZMA_SIZE_OPT */
|
||||
|
||||
#ifdef _LZMA_SIZE_OPT
|
||||
#define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i)
|
||||
#else
|
||||
#define TREE_6_DECODE(probs, i) \
|
||||
{ i = 1; \
|
||||
TREE_GET_BIT(probs, i); \
|
||||
TREE_GET_BIT(probs, i); \
|
||||
TREE_GET_BIT(probs, i); \
|
||||
TREE_GET_BIT(probs, i); \
|
||||
TREE_GET_BIT(probs, i); \
|
||||
TREE_GET_BIT(probs, i); \
|
||||
i -= 0x40; }
|
||||
#endif
|
||||
|
||||
#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); }
|
||||
|
||||
#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
|
||||
#define UPDATE_0_CHECK range = bound;
|
||||
#define UPDATE_1_CHECK range -= bound; code -= bound;
|
||||
#define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \
|
||||
{ UPDATE_0_CHECK; i = (i + i); A0; } else \
|
||||
{ UPDATE_1_CHECK; i = (i + i) + 1; A1; }
|
||||
#define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;)
|
||||
#define TREE_DECODE_CHECK(probs, limit, i) \
|
||||
{ i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; }
|
||||
|
||||
|
||||
#define kNumPosBitsMax 4
|
||||
#define kNumPosStatesMax (1 << kNumPosBitsMax)
|
||||
|
||||
#define kLenNumLowBits 3
|
||||
#define kLenNumLowSymbols (1 << kLenNumLowBits)
|
||||
#define kLenNumMidBits 3
|
||||
#define kLenNumMidSymbols (1 << kLenNumMidBits)
|
||||
#define kLenNumHighBits 8
|
||||
#define kLenNumHighSymbols (1 << kLenNumHighBits)
|
||||
|
||||
#define LenChoice 0
|
||||
#define LenChoice2 (LenChoice + 1)
|
||||
#define LenLow (LenChoice2 + 1)
|
||||
#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
|
||||
#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
|
||||
#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
|
||||
|
||||
|
||||
#define kNumStates 12
|
||||
#define kNumLitStates 7
|
||||
|
||||
#define kStartPosModelIndex 4
|
||||
#define kEndPosModelIndex 14
|
||||
#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
|
||||
|
||||
#define kNumPosSlotBits 6
|
||||
#define kNumLenToPosStates 4
|
||||
|
||||
#define kNumAlignBits 4
|
||||
#define kAlignTableSize (1 << kNumAlignBits)
|
||||
|
||||
#define kMatchMinLen 2
|
||||
#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols)
|
||||
|
||||
#define IsMatch 0
|
||||
#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
|
||||
#define IsRepG0 (IsRep + kNumStates)
|
||||
#define IsRepG1 (IsRepG0 + kNumStates)
|
||||
#define IsRepG2 (IsRepG1 + kNumStates)
|
||||
#define IsRep0Long (IsRepG2 + kNumStates)
|
||||
#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
|
||||
#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
|
||||
#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
|
||||
#define LenCoder (Align + kAlignTableSize)
|
||||
#define RepLenCoder (LenCoder + kNumLenProbs)
|
||||
#define Literal (RepLenCoder + kNumLenProbs)
|
||||
|
||||
#define LZMA_BASE_SIZE 1846
|
||||
#define LZMA_LIT_SIZE 768
|
||||
|
||||
#define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp)))
|
||||
|
||||
#if Literal != LZMA_BASE_SIZE
|
||||
StopCompilingDueBUG
|
||||
#endif
|
||||
|
||||
#define LZMA_DIC_MIN (1 << 12)
|
||||
|
||||
/* First LZMA-symbol is always decoded.
|
||||
And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is withlast normalization
|
||||
Out:
|
||||
Result:
|
||||
SZ_OK - OK
|
||||
SZ_ERROR_DATA - Error
|
||||
p->remainLen:
|
||||
< kMatchSpecLenStart : normal remain
|
||||
= kMatchSpecLenStart : finished
|
||||
= kMatchSpecLenStart + 1 : Flush marker
|
||||
= kMatchSpecLenStart + 2 : State Init Marker
|
||||
*/
|
||||
|
||||
static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
|
||||
{
|
||||
CLzmaProb *probs = p->probs;
|
||||
|
||||
unsigned state = p->state;
|
||||
UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3];
|
||||
unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1;
|
||||
unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1;
|
||||
unsigned lc = p->prop.lc;
|
||||
|
||||
Byte *dic = p->dic;
|
||||
SizeT dicBufSize = p->dicBufSize;
|
||||
SizeT dicPos = p->dicPos;
|
||||
|
||||
UInt32 processedPos = p->processedPos;
|
||||
UInt32 checkDicSize = p->checkDicSize;
|
||||
unsigned len = 0;
|
||||
|
||||
const Byte *buf = p->buf;
|
||||
UInt32 range = p->range;
|
||||
UInt32 code = p->code;
|
||||
|
||||
do
|
||||
{
|
||||
CLzmaProb *prob;
|
||||
UInt32 bound;
|
||||
unsigned ttt;
|
||||
unsigned posState = processedPos & pbMask;
|
||||
|
||||
prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;
|
||||
IF_BIT_0(prob)
|
||||
{
|
||||
unsigned symbol;
|
||||
UPDATE_0(prob);
|
||||
prob = probs + Literal;
|
||||
if (checkDicSize != 0 || processedPos != 0)
|
||||
prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) +
|
||||
(dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc))));
|
||||
|
||||
if (state < kNumLitStates)
|
||||
{
|
||||
state -= (state < 4) ? state : 3;
|
||||
symbol = 1;
|
||||
do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
|
||||
unsigned offs = 0x100;
|
||||
state -= (state < 10) ? 3 : 6;
|
||||
symbol = 1;
|
||||
do
|
||||
{
|
||||
unsigned bit;
|
||||
CLzmaProb *probLit;
|
||||
matchByte <<= 1;
|
||||
bit = (matchByte & offs);
|
||||
probLit = prob + offs + bit + symbol;
|
||||
GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit)
|
||||
}
|
||||
while (symbol < 0x100);
|
||||
}
|
||||
dic[dicPos++] = (Byte)symbol;
|
||||
processedPos++;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
UPDATE_1(prob);
|
||||
prob = probs + IsRep + state;
|
||||
IF_BIT_0(prob)
|
||||
{
|
||||
UPDATE_0(prob);
|
||||
state += kNumStates;
|
||||
prob = probs + LenCoder;
|
||||
}
|
||||
else
|
||||
{
|
||||
UPDATE_1(prob);
|
||||
if (checkDicSize == 0 && processedPos == 0)
|
||||
return SZ_ERROR_DATA;
|
||||
prob = probs + IsRepG0 + state;
|
||||
IF_BIT_0(prob)
|
||||
{
|
||||
UPDATE_0(prob);
|
||||
prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;
|
||||
IF_BIT_0(prob)
|
||||
{
|
||||
UPDATE_0(prob);
|
||||
dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
|
||||
dicPos++;
|
||||
processedPos++;
|
||||
state = state < kNumLitStates ? 9 : 11;
|
||||
continue;
|
||||
}
|
||||
UPDATE_1(prob);
|
||||
}
|
||||
else
|
||||
{
|
||||
UInt32 distance;
|
||||
UPDATE_1(prob);
|
||||
prob = probs + IsRepG1 + state;
|
||||
IF_BIT_0(prob)
|
||||
{
|
||||
UPDATE_0(prob);
|
||||
distance = rep1;
|
||||
}
|
||||
else
|
||||
{
|
||||
UPDATE_1(prob);
|
||||
prob = probs + IsRepG2 + state;
|
||||
IF_BIT_0(prob)
|
||||
{
|
||||
UPDATE_0(prob);
|
||||
distance = rep2;
|
||||
}
|
||||
else
|
||||
{
|
||||
UPDATE_1(prob);
|
||||
distance = rep3;
|
||||
rep3 = rep2;
|
||||
}
|
||||
rep2 = rep1;
|
||||
}
|
||||
rep1 = rep0;
|
||||
rep0 = distance;
|
||||
}
|
||||
state = state < kNumLitStates ? 8 : 11;
|
||||
prob = probs + RepLenCoder;
|
||||
}
|
||||
{
|
||||
unsigned limit, offset;
|
||||
CLzmaProb *probLen = prob + LenChoice;
|
||||
IF_BIT_0(probLen)
|
||||
{
|
||||
UPDATE_0(probLen);
|
||||
probLen = prob + LenLow + (posState << kLenNumLowBits);
|
||||
offset = 0;
|
||||
limit = (1 << kLenNumLowBits);
|
||||
}
|
||||
else
|
||||
{
|
||||
UPDATE_1(probLen);
|
||||
probLen = prob + LenChoice2;
|
||||
IF_BIT_0(probLen)
|
||||
{
|
||||
UPDATE_0(probLen);
|
||||
probLen = prob + LenMid + (posState << kLenNumMidBits);
|
||||
offset = kLenNumLowSymbols;
|
||||
limit = (1 << kLenNumMidBits);
|
||||
}
|
||||
else
|
||||
{
|
||||
UPDATE_1(probLen);
|
||||
probLen = prob + LenHigh;
|
||||
offset = kLenNumLowSymbols + kLenNumMidSymbols;
|
||||
limit = (1 << kLenNumHighBits);
|
||||
}
|
||||
}
|
||||
TREE_DECODE(probLen, limit, len);
|
||||
len += offset;
|
||||
}
|
||||
|
||||
if (state >= kNumStates)
|
||||
{
|
||||
UInt32 distance;
|
||||
prob = probs + PosSlot +
|
||||
((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits);
|
||||
TREE_6_DECODE(prob, distance);
|
||||
if (distance >= kStartPosModelIndex)
|
||||
{
|
||||
unsigned posSlot = (unsigned)distance;
|
||||
int numDirectBits = (int)(((distance >> 1) - 1));
|
||||
distance = (2 | (distance & 1));
|
||||
if (posSlot < kEndPosModelIndex)
|
||||
{
|
||||
distance <<= numDirectBits;
|
||||
prob = probs + SpecPos + distance - posSlot - 1;
|
||||
{
|
||||
UInt32 mask = 1;
|
||||
unsigned i = 1;
|
||||
do
|
||||
{
|
||||
GET_BIT2(prob + i, i, ; , distance |= mask);
|
||||
mask <<= 1;
|
||||
}
|
||||
while (--numDirectBits != 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
numDirectBits -= kNumAlignBits;
|
||||
do
|
||||
{
|
||||
NORMALIZE
|
||||
range >>= 1;
|
||||
|
||||
{
|
||||
UInt32 t;
|
||||
code -= range;
|
||||
t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */
|
||||
distance = (distance << 1) + (t + 1);
|
||||
code += range & t;
|
||||
}
|
||||
/*
|
||||
distance <<= 1;
|
||||
if (code >= range)
|
||||
{
|
||||
code -= range;
|
||||
distance |= 1;
|
||||
}
|
||||
*/
|
||||
}
|
||||
while (--numDirectBits != 0);
|
||||
prob = probs + Align;
|
||||
distance <<= kNumAlignBits;
|
||||
{
|
||||
unsigned i = 1;
|
||||
GET_BIT2(prob + i, i, ; , distance |= 1);
|
||||
GET_BIT2(prob + i, i, ; , distance |= 2);
|
||||
GET_BIT2(prob + i, i, ; , distance |= 4);
|
||||
GET_BIT2(prob + i, i, ; , distance |= 8);
|
||||
}
|
||||
if (distance == (UInt32)0xFFFFFFFF)
|
||||
{
|
||||
len += kMatchSpecLenStart;
|
||||
state -= kNumStates;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
rep3 = rep2;
|
||||
rep2 = rep1;
|
||||
rep1 = rep0;
|
||||
rep0 = distance + 1;
|
||||
if (checkDicSize == 0)
|
||||
{
|
||||
if (distance >= processedPos)
|
||||
return SZ_ERROR_DATA;
|
||||
}
|
||||
else if (distance >= checkDicSize)
|
||||
return SZ_ERROR_DATA;
|
||||
state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3;
|
||||
}
|
||||
|
||||
len += kMatchMinLen;
|
||||
|
||||
if (limit == dicPos)
|
||||
return SZ_ERROR_DATA;
|
||||
{
|
||||
SizeT rem = limit - dicPos;
|
||||
unsigned curLen = ((rem < len) ? (unsigned)rem : len);
|
||||
SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0);
|
||||
|
||||
processedPos += curLen;
|
||||
|
||||
len -= curLen;
|
||||
if (pos + curLen <= dicBufSize)
|
||||
{
|
||||
Byte *dest = dic + dicPos;
|
||||
ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos;
|
||||
const Byte *lim = dest + curLen;
|
||||
dicPos += curLen;
|
||||
do
|
||||
*(dest) = (Byte)*(dest + src);
|
||||
while (++dest != lim);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
dic[dicPos++] = dic[pos];
|
||||
if (++pos == dicBufSize)
|
||||
pos = 0;
|
||||
}
|
||||
while (--curLen != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
while (dicPos < limit && buf < bufLimit);
|
||||
NORMALIZE;
|
||||
p->buf = buf;
|
||||
p->range = range;
|
||||
p->code = code;
|
||||
p->remainLen = len;
|
||||
p->dicPos = dicPos;
|
||||
p->processedPos = processedPos;
|
||||
p->reps[0] = rep0;
|
||||
p->reps[1] = rep1;
|
||||
p->reps[2] = rep2;
|
||||
p->reps[3] = rep3;
|
||||
p->state = state;
|
||||
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)
|
||||
{
|
||||
if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart)
|
||||
{
|
||||
Byte *dic = p->dic;
|
||||
SizeT dicPos = p->dicPos;
|
||||
SizeT dicBufSize = p->dicBufSize;
|
||||
unsigned len = p->remainLen;
|
||||
UInt32 rep0 = p->reps[0];
|
||||
if (limit - dicPos < len)
|
||||
len = (unsigned)(limit - dicPos);
|
||||
|
||||
if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len)
|
||||
p->checkDicSize = p->prop.dicSize;
|
||||
|
||||
p->processedPos += len;
|
||||
p->remainLen -= len;
|
||||
while (len-- != 0)
|
||||
{
|
||||
dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
|
||||
dicPos++;
|
||||
}
|
||||
p->dicPos = dicPos;
|
||||
}
|
||||
}
|
||||
|
||||
static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
|
||||
{
|
||||
do
|
||||
{
|
||||
SizeT limit2 = limit;
|
||||
if (p->checkDicSize == 0)
|
||||
{
|
||||
UInt32 rem = p->prop.dicSize - p->processedPos;
|
||||
if (limit - p->dicPos > rem)
|
||||
limit2 = p->dicPos + rem;
|
||||
}
|
||||
RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit));
|
||||
if (p->processedPos >= p->prop.dicSize)
|
||||
p->checkDicSize = p->prop.dicSize;
|
||||
LzmaDec_WriteRem(p, limit);
|
||||
}
|
||||
while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart);
|
||||
|
||||
if (p->remainLen > kMatchSpecLenStart)
|
||||
{
|
||||
p->remainLen = kMatchSpecLenStart;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DUMMY_ERROR, /* unexpected end of input stream */
|
||||
DUMMY_LIT,
|
||||
DUMMY_MATCH,
|
||||
DUMMY_REP
|
||||
} ELzmaDummy;
|
||||
|
||||
static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize)
|
||||
{
|
||||
UInt32 range = p->range;
|
||||
UInt32 code = p->code;
|
||||
const Byte *bufLimit = buf + inSize;
|
||||
CLzmaProb *probs = p->probs;
|
||||
unsigned state = p->state;
|
||||
ELzmaDummy res;
|
||||
|
||||
{
|
||||
CLzmaProb *prob;
|
||||
UInt32 bound;
|
||||
unsigned ttt;
|
||||
unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1);
|
||||
|
||||
prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;
|
||||
IF_BIT_0_CHECK(prob)
|
||||
{
|
||||
UPDATE_0_CHECK
|
||||
|
||||
/* if (bufLimit - buf >= 7) return DUMMY_LIT; */
|
||||
|
||||
prob = probs + Literal;
|
||||
if (p->checkDicSize != 0 || p->processedPos != 0)
|
||||
prob += (LZMA_LIT_SIZE *
|
||||
((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) +
|
||||
(p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc))));
|
||||
|
||||
if (state < kNumLitStates)
|
||||
{
|
||||
unsigned symbol = 1;
|
||||
do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned matchByte = p->dic[p->dicPos - p->reps[0] +
|
||||
((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)];
|
||||
unsigned offs = 0x100;
|
||||
unsigned symbol = 1;
|
||||
do
|
||||
{
|
||||
unsigned bit;
|
||||
CLzmaProb *probLit;
|
||||
matchByte <<= 1;
|
||||
bit = (matchByte & offs);
|
||||
probLit = prob + offs + bit + symbol;
|
||||
GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit)
|
||||
}
|
||||
while (symbol < 0x100);
|
||||
}
|
||||
res = DUMMY_LIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned len;
|
||||
UPDATE_1_CHECK;
|
||||
|
||||
prob = probs + IsRep + state;
|
||||
IF_BIT_0_CHECK(prob)
|
||||
{
|
||||
UPDATE_0_CHECK;
|
||||
state = 0;
|
||||
prob = probs + LenCoder;
|
||||
res = DUMMY_MATCH;
|
||||
}
|
||||
else
|
||||
{
|
||||
UPDATE_1_CHECK;
|
||||
res = DUMMY_REP;
|
||||
prob = probs + IsRepG0 + state;
|
||||
IF_BIT_0_CHECK(prob)
|
||||
{
|
||||
UPDATE_0_CHECK;
|
||||
prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;
|
||||
IF_BIT_0_CHECK(prob)
|
||||
{
|
||||
UPDATE_0_CHECK;
|
||||
NORMALIZE_CHECK;
|
||||
return DUMMY_REP;
|
||||
}
|
||||
else
|
||||
{
|
||||
UPDATE_1_CHECK;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UPDATE_1_CHECK;
|
||||
prob = probs + IsRepG1 + state;
|
||||
IF_BIT_0_CHECK(prob)
|
||||
{
|
||||
UPDATE_0_CHECK;
|
||||
}
|
||||
else
|
||||
{
|
||||
UPDATE_1_CHECK;
|
||||
prob = probs + IsRepG2 + state;
|
||||
IF_BIT_0_CHECK(prob)
|
||||
{
|
||||
UPDATE_0_CHECK;
|
||||
}
|
||||
else
|
||||
{
|
||||
UPDATE_1_CHECK;
|
||||
}
|
||||
}
|
||||
}
|
||||
state = kNumStates;
|
||||
prob = probs + RepLenCoder;
|
||||
}
|
||||
{
|
||||
unsigned limit, offset;
|
||||
CLzmaProb *probLen = prob + LenChoice;
|
||||
IF_BIT_0_CHECK(probLen)
|
||||
{
|
||||
UPDATE_0_CHECK;
|
||||
probLen = prob + LenLow + (posState << kLenNumLowBits);
|
||||
offset = 0;
|
||||
limit = 1 << kLenNumLowBits;
|
||||
}
|
||||
else
|
||||
{
|
||||
UPDATE_1_CHECK;
|
||||
probLen = prob + LenChoice2;
|
||||
IF_BIT_0_CHECK(probLen)
|
||||
{
|
||||
UPDATE_0_CHECK;
|
||||
probLen = prob + LenMid + (posState << kLenNumMidBits);
|
||||
offset = kLenNumLowSymbols;
|
||||
limit = 1 << kLenNumMidBits;
|
||||
}
|
||||
else
|
||||
{
|
||||
UPDATE_1_CHECK;
|
||||
probLen = prob + LenHigh;
|
||||
offset = kLenNumLowSymbols + kLenNumMidSymbols;
|
||||
limit = 1 << kLenNumHighBits;
|
||||
}
|
||||
}
|
||||
TREE_DECODE_CHECK(probLen, limit, len);
|
||||
len += offset;
|
||||
}
|
||||
|
||||
if (state < 4)
|
||||
{
|
||||
unsigned posSlot;
|
||||
prob = probs + PosSlot +
|
||||
((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
|
||||
kNumPosSlotBits);
|
||||
TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot);
|
||||
if (posSlot >= kStartPosModelIndex)
|
||||
{
|
||||
int numDirectBits = ((posSlot >> 1) - 1);
|
||||
|
||||
/* if (bufLimit - buf >= 8) return DUMMY_MATCH; */
|
||||
|
||||
if (posSlot < kEndPosModelIndex)
|
||||
{
|
||||
prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
numDirectBits -= kNumAlignBits;
|
||||
do
|
||||
{
|
||||
NORMALIZE_CHECK
|
||||
range >>= 1;
|
||||
code -= range & (((code - range) >> 31) - 1);
|
||||
/* if (code >= range) code -= range; */
|
||||
}
|
||||
while (--numDirectBits != 0);
|
||||
prob = probs + Align;
|
||||
numDirectBits = kNumAlignBits;
|
||||
}
|
||||
{
|
||||
unsigned i = 1;
|
||||
do
|
||||
{
|
||||
GET_BIT_CHECK(prob + i, i);
|
||||
}
|
||||
while (--numDirectBits != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
NORMALIZE_CHECK;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data)
|
||||
{
|
||||
p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]);
|
||||
p->range = 0xFFFFFFFF;
|
||||
p->needFlush = 0;
|
||||
}
|
||||
|
||||
void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState)
|
||||
{
|
||||
p->needFlush = 1;
|
||||
p->remainLen = 0;
|
||||
p->tempBufSize = 0;
|
||||
|
||||
if (initDic)
|
||||
{
|
||||
p->processedPos = 0;
|
||||
p->checkDicSize = 0;
|
||||
p->needInitState = 1;
|
||||
}
|
||||
if (initState)
|
||||
p->needInitState = 1;
|
||||
}
|
||||
|
||||
void LzmaDec_Init(CLzmaDec *p)
|
||||
{
|
||||
p->dicPos = 0;
|
||||
LzmaDec_InitDicAndState(p, True, True);
|
||||
}
|
||||
|
||||
static void LzmaDec_InitStateReal(CLzmaDec *p)
|
||||
{
|
||||
UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp));
|
||||
UInt32 i;
|
||||
CLzmaProb *probs = p->probs;
|
||||
for (i = 0; i < numProbs; i++)
|
||||
probs[i] = kBitModelTotal >> 1;
|
||||
p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1;
|
||||
p->state = 0;
|
||||
p->needInitState = 0;
|
||||
}
|
||||
|
||||
SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen,
|
||||
ELzmaFinishMode finishMode, ELzmaStatus *status)
|
||||
{
|
||||
SizeT inSize = *srcLen;
|
||||
(*srcLen) = 0;
|
||||
LzmaDec_WriteRem(p, dicLimit);
|
||||
|
||||
*status = LZMA_STATUS_NOT_SPECIFIED;
|
||||
|
||||
while (p->remainLen != kMatchSpecLenStart)
|
||||
{
|
||||
int checkEndMarkNow;
|
||||
|
||||
if (p->needFlush != 0)
|
||||
{
|
||||
for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--)
|
||||
p->tempBuf[p->tempBufSize++] = *src++;
|
||||
if (p->tempBufSize < RC_INIT_SIZE)
|
||||
{
|
||||
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
|
||||
return SZ_OK;
|
||||
}
|
||||
if (p->tempBuf[0] != 0)
|
||||
return SZ_ERROR_DATA;
|
||||
|
||||
LzmaDec_InitRc(p, p->tempBuf);
|
||||
p->tempBufSize = 0;
|
||||
}
|
||||
|
||||
checkEndMarkNow = 0;
|
||||
if (p->dicPos >= dicLimit)
|
||||
{
|
||||
if (p->remainLen == 0 && p->code == 0)
|
||||
{
|
||||
*status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK;
|
||||
return SZ_OK;
|
||||
}
|
||||
if (finishMode == LZMA_FINISH_ANY)
|
||||
{
|
||||
*status = LZMA_STATUS_NOT_FINISHED;
|
||||
return SZ_OK;
|
||||
}
|
||||
if (p->remainLen != 0)
|
||||
{
|
||||
*status = LZMA_STATUS_NOT_FINISHED;
|
||||
return SZ_ERROR_DATA;
|
||||
}
|
||||
checkEndMarkNow = 1;
|
||||
}
|
||||
|
||||
if (p->needInitState)
|
||||
LzmaDec_InitStateReal(p);
|
||||
|
||||
if (p->tempBufSize == 0)
|
||||
{
|
||||
SizeT processed;
|
||||
const Byte *bufLimit;
|
||||
if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
|
||||
{
|
||||
int dummyRes = LzmaDec_TryDummy(p, src, inSize);
|
||||
if (dummyRes == DUMMY_ERROR)
|
||||
{
|
||||
memcpy(p->tempBuf, src, inSize);
|
||||
p->tempBufSize = (unsigned)inSize;
|
||||
(*srcLen) += inSize;
|
||||
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
|
||||
return SZ_OK;
|
||||
}
|
||||
if (checkEndMarkNow && dummyRes != DUMMY_MATCH)
|
||||
{
|
||||
*status = LZMA_STATUS_NOT_FINISHED;
|
||||
return SZ_ERROR_DATA;
|
||||
}
|
||||
bufLimit = src;
|
||||
}
|
||||
else
|
||||
bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX;
|
||||
p->buf = src;
|
||||
if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0)
|
||||
return SZ_ERROR_DATA;
|
||||
processed = (SizeT)(p->buf - src);
|
||||
(*srcLen) += processed;
|
||||
src += processed;
|
||||
inSize -= processed;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned rem = p->tempBufSize, lookAhead = 0;
|
||||
while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize)
|
||||
p->tempBuf[rem++] = src[lookAhead++];
|
||||
p->tempBufSize = rem;
|
||||
if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
|
||||
{
|
||||
int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem);
|
||||
if (dummyRes == DUMMY_ERROR)
|
||||
{
|
||||
(*srcLen) += lookAhead;
|
||||
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
|
||||
return SZ_OK;
|
||||
}
|
||||
if (checkEndMarkNow && dummyRes != DUMMY_MATCH)
|
||||
{
|
||||
*status = LZMA_STATUS_NOT_FINISHED;
|
||||
return SZ_ERROR_DATA;
|
||||
}
|
||||
}
|
||||
p->buf = p->tempBuf;
|
||||
if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0)
|
||||
return SZ_ERROR_DATA;
|
||||
lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf));
|
||||
(*srcLen) += lookAhead;
|
||||
src += lookAhead;
|
||||
inSize -= lookAhead;
|
||||
p->tempBufSize = 0;
|
||||
}
|
||||
}
|
||||
if (p->code == 0)
|
||||
*status = LZMA_STATUS_FINISHED_WITH_MARK;
|
||||
return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA;
|
||||
}
|
||||
|
||||
SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
|
||||
{
|
||||
SizeT outSize = *destLen;
|
||||
SizeT inSize = *srcLen;
|
||||
*srcLen = *destLen = 0;
|
||||
for (;;)
|
||||
{
|
||||
SizeT inSizeCur = inSize, outSizeCur, dicPos;
|
||||
ELzmaFinishMode curFinishMode;
|
||||
SRes res;
|
||||
if (p->dicPos == p->dicBufSize)
|
||||
p->dicPos = 0;
|
||||
dicPos = p->dicPos;
|
||||
if (outSize > p->dicBufSize - dicPos)
|
||||
{
|
||||
outSizeCur = p->dicBufSize;
|
||||
curFinishMode = LZMA_FINISH_ANY;
|
||||
}
|
||||
else
|
||||
{
|
||||
outSizeCur = dicPos + outSize;
|
||||
curFinishMode = finishMode;
|
||||
}
|
||||
|
||||
res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status);
|
||||
src += inSizeCur;
|
||||
inSize -= inSizeCur;
|
||||
*srcLen += inSizeCur;
|
||||
outSizeCur = p->dicPos - dicPos;
|
||||
memcpy(dest, p->dic + dicPos, outSizeCur);
|
||||
dest += outSizeCur;
|
||||
outSize -= outSizeCur;
|
||||
*destLen += outSizeCur;
|
||||
if (res != 0)
|
||||
return res;
|
||||
if (outSizeCur == 0 || outSize == 0)
|
||||
return SZ_OK;
|
||||
}
|
||||
}
|
||||
|
||||
void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc)
|
||||
{
|
||||
alloc->Free(alloc, p->probs);
|
||||
p->probs = 0;
|
||||
}
|
||||
|
||||
static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc)
|
||||
{
|
||||
alloc->Free(alloc, p->dic);
|
||||
p->dic = 0;
|
||||
}
|
||||
|
||||
void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc)
|
||||
{
|
||||
LzmaDec_FreeProbs(p, alloc);
|
||||
LzmaDec_FreeDict(p, alloc);
|
||||
}
|
||||
|
||||
SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size)
|
||||
{
|
||||
UInt32 dicSize;
|
||||
Byte d;
|
||||
|
||||
if (size < LZMA_PROPS_SIZE)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
else
|
||||
dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24);
|
||||
|
||||
if (dicSize < LZMA_DIC_MIN)
|
||||
dicSize = LZMA_DIC_MIN;
|
||||
p->dicSize = dicSize;
|
||||
|
||||
d = data[0];
|
||||
if (d >= (9 * 5 * 5))
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
|
||||
p->lc = d % 9;
|
||||
d /= 9;
|
||||
p->pb = d / 5;
|
||||
p->lp = d % 5;
|
||||
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc)
|
||||
{
|
||||
UInt32 numProbs = LzmaProps_GetNumProbs(propNew);
|
||||
if (p->probs == 0 || numProbs != p->numProbs)
|
||||
{
|
||||
LzmaDec_FreeProbs(p, alloc);
|
||||
p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb));
|
||||
p->numProbs = numProbs;
|
||||
if (p->probs == 0)
|
||||
return SZ_ERROR_MEM;
|
||||
}
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
|
||||
{
|
||||
CLzmaProps propNew;
|
||||
RINOK(LzmaProps_Decode(&propNew, props, propsSize));
|
||||
RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));
|
||||
p->prop = propNew;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
|
||||
{
|
||||
CLzmaProps propNew;
|
||||
SizeT dicBufSize;
|
||||
RINOK(LzmaProps_Decode(&propNew, props, propsSize));
|
||||
RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));
|
||||
dicBufSize = propNew.dicSize;
|
||||
if (p->dic == 0 || dicBufSize != p->dicBufSize)
|
||||
{
|
||||
LzmaDec_FreeDict(p, alloc);
|
||||
p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize);
|
||||
if (p->dic == 0)
|
||||
{
|
||||
LzmaDec_FreeProbs(p, alloc);
|
||||
return SZ_ERROR_MEM;
|
||||
}
|
||||
}
|
||||
p->dicBufSize = dicBufSize;
|
||||
p->prop = propNew;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
|
||||
const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
|
||||
ELzmaStatus *status, ISzAlloc *alloc)
|
||||
{
|
||||
CLzmaDec p;
|
||||
SRes res;
|
||||
SizeT inSize = *srcLen;
|
||||
SizeT outSize = *destLen;
|
||||
*srcLen = *destLen = 0;
|
||||
if (inSize < RC_INIT_SIZE)
|
||||
return SZ_ERROR_INPUT_EOF;
|
||||
|
||||
LzmaDec_Construct(&p);
|
||||
res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc);
|
||||
if (res != 0)
|
||||
return res;
|
||||
p.dic = dest;
|
||||
p.dicBufSize = outSize;
|
||||
|
||||
LzmaDec_Init(&p);
|
||||
|
||||
*srcLen = inSize;
|
||||
res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);
|
||||
|
||||
if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
|
||||
res = SZ_ERROR_INPUT_EOF;
|
||||
|
||||
(*destLen) = p.dicPos;
|
||||
LzmaDec_FreeProbs(&p, alloc);
|
||||
return res;
|
||||
}
|
231
LZMA/SDK/C/LzmaDec.h
Normal file
231
LZMA/SDK/C/LzmaDec.h
Normal file
@ -0,0 +1,231 @@
|
||||
/* LzmaDec.h -- LZMA Decoder
|
||||
2009-02-07 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __LZMA_DEC_H
|
||||
#define __LZMA_DEC_H
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* #define _LZMA_PROB32 */
|
||||
/* _LZMA_PROB32 can increase the speed on some CPUs,
|
||||
but memory usage for CLzmaDec::probs will be doubled in that case */
|
||||
|
||||
#ifdef _LZMA_PROB32
|
||||
#define CLzmaProb UInt32
|
||||
#else
|
||||
#define CLzmaProb UInt16
|
||||
#endif
|
||||
|
||||
|
||||
/* ---------- LZMA Properties ---------- */
|
||||
|
||||
#define LZMA_PROPS_SIZE 5
|
||||
|
||||
typedef struct _CLzmaProps
|
||||
{
|
||||
unsigned lc, lp, pb;
|
||||
UInt32 dicSize;
|
||||
} CLzmaProps;
|
||||
|
||||
/* LzmaProps_Decode - decodes properties
|
||||
Returns:
|
||||
SZ_OK
|
||||
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
||||
*/
|
||||
|
||||
SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size);
|
||||
|
||||
|
||||
/* ---------- LZMA Decoder state ---------- */
|
||||
|
||||
/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case.
|
||||
Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */
|
||||
|
||||
#define LZMA_REQUIRED_INPUT_MAX 20
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CLzmaProps prop;
|
||||
CLzmaProb *probs;
|
||||
Byte *dic;
|
||||
const Byte *buf;
|
||||
UInt32 range, code;
|
||||
SizeT dicPos;
|
||||
SizeT dicBufSize;
|
||||
UInt32 processedPos;
|
||||
UInt32 checkDicSize;
|
||||
unsigned state;
|
||||
UInt32 reps[4];
|
||||
unsigned remainLen;
|
||||
int needFlush;
|
||||
int needInitState;
|
||||
UInt32 numProbs;
|
||||
unsigned tempBufSize;
|
||||
Byte tempBuf[LZMA_REQUIRED_INPUT_MAX];
|
||||
} CLzmaDec;
|
||||
|
||||
#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; }
|
||||
|
||||
void LzmaDec_Init(CLzmaDec *p);
|
||||
|
||||
/* There are two types of LZMA streams:
|
||||
0) Stream with end mark. That end mark adds about 6 bytes to compressed size.
|
||||
1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
LZMA_FINISH_ANY, /* finish at any point */
|
||||
LZMA_FINISH_END /* block must be finished at the end */
|
||||
} ELzmaFinishMode;
|
||||
|
||||
/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!!
|
||||
|
||||
You must use LZMA_FINISH_END, when you know that current output buffer
|
||||
covers last bytes of block. In other cases you must use LZMA_FINISH_ANY.
|
||||
|
||||
If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK,
|
||||
and output value of destLen will be less than output buffer size limit.
|
||||
You can check status result also.
|
||||
|
||||
You can use multiple checks to test data integrity after full decompression:
|
||||
1) Check Result and "status" variable.
|
||||
2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.
|
||||
3) Check that output(srcLen) = compressedSize, if you know real compressedSize.
|
||||
You must use correct finish mode in that case. */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */
|
||||
LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */
|
||||
LZMA_STATUS_NOT_FINISHED, /* stream was not finished */
|
||||
LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */
|
||||
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */
|
||||
} ELzmaStatus;
|
||||
|
||||
/* ELzmaStatus is used only as output value for function call */
|
||||
|
||||
|
||||
/* ---------- Interfaces ---------- */
|
||||
|
||||
/* There are 3 levels of interfaces:
|
||||
1) Dictionary Interface
|
||||
2) Buffer Interface
|
||||
3) One Call Interface
|
||||
You can select any of these interfaces, but don't mix functions from different
|
||||
groups for same object. */
|
||||
|
||||
|
||||
/* There are two variants to allocate state for Dictionary Interface:
|
||||
1) LzmaDec_Allocate / LzmaDec_Free
|
||||
2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs
|
||||
You can use variant 2, if you set dictionary buffer manually.
|
||||
For Buffer Interface you must always use variant 1.
|
||||
|
||||
LzmaDec_Allocate* can return:
|
||||
SZ_OK
|
||||
SZ_ERROR_MEM - Memory allocation error
|
||||
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
||||
*/
|
||||
|
||||
SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc);
|
||||
void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc);
|
||||
|
||||
SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc);
|
||||
void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc);
|
||||
|
||||
/* ---------- Dictionary Interface ---------- */
|
||||
|
||||
/* You can use it, if you want to eliminate the overhead for data copying from
|
||||
dictionary to some other external buffer.
|
||||
You must work with CLzmaDec variables directly in this interface.
|
||||
|
||||
STEPS:
|
||||
LzmaDec_Constr()
|
||||
LzmaDec_Allocate()
|
||||
for (each new stream)
|
||||
{
|
||||
LzmaDec_Init()
|
||||
while (it needs more decompression)
|
||||
{
|
||||
LzmaDec_DecodeToDic()
|
||||
use data from CLzmaDec::dic and update CLzmaDec::dicPos
|
||||
}
|
||||
}
|
||||
LzmaDec_Free()
|
||||
*/
|
||||
|
||||
/* LzmaDec_DecodeToDic
|
||||
|
||||
The decoding to internal dictionary buffer (CLzmaDec::dic).
|
||||
You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!!
|
||||
|
||||
finishMode:
|
||||
It has meaning only if the decoding reaches output limit (dicLimit).
|
||||
LZMA_FINISH_ANY - Decode just dicLimit bytes.
|
||||
LZMA_FINISH_END - Stream must be finished after dicLimit.
|
||||
|
||||
Returns:
|
||||
SZ_OK
|
||||
status:
|
||||
LZMA_STATUS_FINISHED_WITH_MARK
|
||||
LZMA_STATUS_NOT_FINISHED
|
||||
LZMA_STATUS_NEEDS_MORE_INPUT
|
||||
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
|
||||
SZ_ERROR_DATA - Data error
|
||||
*/
|
||||
|
||||
SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit,
|
||||
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
||||
|
||||
|
||||
/* ---------- Buffer Interface ---------- */
|
||||
|
||||
/* It's zlib-like interface.
|
||||
See LzmaDec_DecodeToDic description for information about STEPS and return results,
|
||||
but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need
|
||||
to work with CLzmaDec variables manually.
|
||||
|
||||
finishMode:
|
||||
It has meaning only if the decoding reaches output limit (*destLen).
|
||||
LZMA_FINISH_ANY - Decode just destLen bytes.
|
||||
LZMA_FINISH_END - Stream must be finished after (*destLen).
|
||||
*/
|
||||
|
||||
SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen,
|
||||
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
||||
|
||||
|
||||
/* ---------- One Call Interface ---------- */
|
||||
|
||||
/* LzmaDecode
|
||||
|
||||
finishMode:
|
||||
It has meaning only if the decoding reaches output limit (*destLen).
|
||||
LZMA_FINISH_ANY - Decode just destLen bytes.
|
||||
LZMA_FINISH_END - Stream must be finished after (*destLen).
|
||||
|
||||
Returns:
|
||||
SZ_OK
|
||||
status:
|
||||
LZMA_STATUS_FINISHED_WITH_MARK
|
||||
LZMA_STATUS_NOT_FINISHED
|
||||
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
|
||||
SZ_ERROR_DATA - Data error
|
||||
SZ_ERROR_MEM - Memory allocation error
|
||||
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
||||
SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
|
||||
*/
|
||||
|
||||
SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
|
||||
const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
|
||||
ELzmaStatus *status, ISzAlloc *alloc);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
2268
LZMA/SDK/C/LzmaEnc.c
Normal file
2268
LZMA/SDK/C/LzmaEnc.c
Normal file
File diff suppressed because it is too large
Load Diff
80
LZMA/SDK/C/LzmaEnc.h
Normal file
80
LZMA/SDK/C/LzmaEnc.h
Normal file
@ -0,0 +1,80 @@
|
||||
/* LzmaEnc.h -- LZMA Encoder
|
||||
2009-02-07 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __LZMA_ENC_H
|
||||
#define __LZMA_ENC_H
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define LZMA_PROPS_SIZE 5
|
||||
|
||||
typedef struct _CLzmaEncProps
|
||||
{
|
||||
int level; /* 0 <= level <= 9 */
|
||||
UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version
|
||||
(1 << 12) <= dictSize <= (1 << 30) for 64-bit version
|
||||
default = (1 << 24) */
|
||||
int lc; /* 0 <= lc <= 8, default = 3 */
|
||||
int lp; /* 0 <= lp <= 4, default = 0 */
|
||||
int pb; /* 0 <= pb <= 4, default = 2 */
|
||||
int algo; /* 0 - fast, 1 - normal, default = 1 */
|
||||
int fb; /* 5 <= fb <= 273, default = 32 */
|
||||
int btMode; /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */
|
||||
int numHashBytes; /* 2, 3 or 4, default = 4 */
|
||||
UInt32 mc; /* 1 <= mc <= (1 << 30), default = 32 */
|
||||
unsigned writeEndMark; /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */
|
||||
int numThreads; /* 1 or 2, default = 2 */
|
||||
} CLzmaEncProps;
|
||||
|
||||
void LzmaEncProps_Init(CLzmaEncProps *p);
|
||||
void LzmaEncProps_Normalize(CLzmaEncProps *p);
|
||||
UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2);
|
||||
|
||||
|
||||
/* ---------- CLzmaEncHandle Interface ---------- */
|
||||
|
||||
/* LzmaEnc_* functions can return the following exit codes:
|
||||
Returns:
|
||||
SZ_OK - OK
|
||||
SZ_ERROR_MEM - Memory allocation error
|
||||
SZ_ERROR_PARAM - Incorrect paramater in props
|
||||
SZ_ERROR_WRITE - Write callback error.
|
||||
SZ_ERROR_PROGRESS - some break from progress callback
|
||||
SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
|
||||
*/
|
||||
|
||||
typedef void * CLzmaEncHandle;
|
||||
|
||||
CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc);
|
||||
void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig);
|
||||
SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props);
|
||||
SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size);
|
||||
SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream,
|
||||
ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
|
||||
SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
|
||||
int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
|
||||
|
||||
/* ---------- One Call Interface ---------- */
|
||||
|
||||
/* LzmaEncode
|
||||
Return code:
|
||||
SZ_OK - OK
|
||||
SZ_ERROR_MEM - Memory allocation error
|
||||
SZ_ERROR_PARAM - Incorrect paramater
|
||||
SZ_ERROR_OUTPUT_EOF - output buffer overflow
|
||||
SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
|
||||
*/
|
||||
|
||||
SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
|
||||
const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
|
||||
ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
256
LZMA/SDK/C/Types.h
Normal file
256
LZMA/SDK/C/Types.h
Normal file
@ -0,0 +1,256 @@
|
||||
/* Types.h -- Basic types
|
||||
2010-10-09 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_TYPES_H
|
||||
#define __7Z_TYPES_H
|
||||
|
||||
#include "../../UefiLzma.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#ifndef EXTERN_C_BEGIN
|
||||
#ifdef __cplusplus
|
||||
#define EXTERN_C_BEGIN extern "C" {
|
||||
#define EXTERN_C_END }
|
||||
#else
|
||||
#define EXTERN_C_BEGIN
|
||||
#define EXTERN_C_END
|
||||
#endif
|
||||
#endif
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
#define SZ_OK 0
|
||||
|
||||
#define SZ_ERROR_DATA 1
|
||||
#define SZ_ERROR_MEM 2
|
||||
#define SZ_ERROR_CRC 3
|
||||
#define SZ_ERROR_UNSUPPORTED 4
|
||||
#define SZ_ERROR_PARAM 5
|
||||
#define SZ_ERROR_INPUT_EOF 6
|
||||
#define SZ_ERROR_OUTPUT_EOF 7
|
||||
#define SZ_ERROR_READ 8
|
||||
#define SZ_ERROR_WRITE 9
|
||||
#define SZ_ERROR_PROGRESS 10
|
||||
#define SZ_ERROR_FAIL 11
|
||||
#define SZ_ERROR_THREAD 12
|
||||
|
||||
#define SZ_ERROR_ARCHIVE 16
|
||||
#define SZ_ERROR_NO_ARCHIVE 17
|
||||
|
||||
typedef int SRes;
|
||||
|
||||
#ifdef _WIN32
|
||||
typedef DWORD WRes;
|
||||
#else
|
||||
typedef int WRes;
|
||||
#endif
|
||||
|
||||
#ifndef RINOK
|
||||
#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; }
|
||||
#endif
|
||||
|
||||
typedef unsigned char Byte;
|
||||
typedef short Int16;
|
||||
typedef unsigned short UInt16;
|
||||
|
||||
#ifdef _LZMA_UINT32_IS_ULONG
|
||||
typedef long Int32;
|
||||
typedef unsigned long UInt32;
|
||||
#else
|
||||
typedef int Int32;
|
||||
typedef unsigned int UInt32;
|
||||
#endif
|
||||
|
||||
#ifdef _SZ_NO_INT_64
|
||||
|
||||
/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers.
|
||||
NOTES: Some code will work incorrectly in that case! */
|
||||
|
||||
typedef long Int64;
|
||||
typedef unsigned long UInt64;
|
||||
|
||||
#else
|
||||
|
||||
#if defined(_MSC_VER) || defined(__BORLANDC__)
|
||||
typedef __int64 Int64;
|
||||
typedef unsigned __int64 UInt64;
|
||||
#define UINT64_CONST(n) n
|
||||
#else
|
||||
typedef long long int Int64;
|
||||
typedef unsigned long long int UInt64;
|
||||
#define UINT64_CONST(n) n ## ULL
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef _LZMA_NO_SYSTEM_SIZE_T
|
||||
typedef UInt32 SizeT;
|
||||
#else
|
||||
typedef size_t SizeT;
|
||||
#endif
|
||||
|
||||
typedef int Bool;
|
||||
#define True 1
|
||||
#define False 0
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
#define MY_STD_CALL __stdcall
|
||||
#else
|
||||
#define MY_STD_CALL
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#if _MSC_VER >= 1300
|
||||
#define MY_NO_INLINE __declspec(noinline)
|
||||
#else
|
||||
#define MY_NO_INLINE
|
||||
#endif
|
||||
|
||||
#define MY_CDECL __cdecl
|
||||
#define MY_FAST_CALL __fastcall
|
||||
|
||||
#else
|
||||
|
||||
#define MY_CDECL
|
||||
#define MY_FAST_CALL
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* The following interfaces use first parameter as pointer to structure */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Byte (*Read)(void *p); /* reads one byte, returns 0 in case of EOF or error */
|
||||
} IByteIn;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void (*Write)(void *p, Byte b);
|
||||
} IByteOut;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SRes (*Read)(void *p, void *buf, size_t *size);
|
||||
/* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
|
||||
(output(*size) < input(*size)) is allowed */
|
||||
} ISeqInStream;
|
||||
|
||||
/* it can return SZ_ERROR_INPUT_EOF */
|
||||
SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size);
|
||||
SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType);
|
||||
SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
size_t (*Write)(void *p, const void *buf, size_t size);
|
||||
/* Returns: result - the number of actually written bytes.
|
||||
(result < size) means error */
|
||||
} ISeqOutStream;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SZ_SEEK_SET = 0,
|
||||
SZ_SEEK_CUR = 1,
|
||||
SZ_SEEK_END = 2
|
||||
} ESzSeek;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */
|
||||
SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
|
||||
} ISeekInStream;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SRes (*Look)(void *p, const void **buf, size_t *size);
|
||||
/* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
|
||||
(output(*size) > input(*size)) is not allowed
|
||||
(output(*size) < input(*size)) is allowed */
|
||||
SRes (*Skip)(void *p, size_t offset);
|
||||
/* offset must be <= output(*size) of Look */
|
||||
|
||||
SRes (*Read)(void *p, void *buf, size_t *size);
|
||||
/* reads directly (without buffer). It's same as ISeqInStream::Read */
|
||||
SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
|
||||
} ILookInStream;
|
||||
|
||||
SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size);
|
||||
SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset);
|
||||
|
||||
/* reads via ILookInStream::Read */
|
||||
SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType);
|
||||
SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size);
|
||||
|
||||
#define LookToRead_BUF_SIZE (1 << 14)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ILookInStream s;
|
||||
ISeekInStream *realStream;
|
||||
size_t pos;
|
||||
size_t size;
|
||||
Byte buf[LookToRead_BUF_SIZE];
|
||||
} CLookToRead;
|
||||
|
||||
void LookToRead_CreateVTable(CLookToRead *p, int lookahead);
|
||||
void LookToRead_Init(CLookToRead *p);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ISeqInStream s;
|
||||
ILookInStream *realStream;
|
||||
} CSecToLook;
|
||||
|
||||
void SecToLook_CreateVTable(CSecToLook *p);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ISeqInStream s;
|
||||
ILookInStream *realStream;
|
||||
} CSecToRead;
|
||||
|
||||
void SecToRead_CreateVTable(CSecToRead *p);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize);
|
||||
/* Returns: result. (result != SZ_OK) means break.
|
||||
Value (UInt64)(Int64)-1 for size means unknown value. */
|
||||
} ICompressProgress;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *(*Alloc)(void *p, size_t size);
|
||||
void (*Free)(void *p, void *address); /* address can be 0 */
|
||||
} ISzAlloc;
|
||||
|
||||
#define IAlloc_Alloc(p, size) (p)->Alloc((p), size)
|
||||
#define IAlloc_Free(p, a) (p)->Free((p), a)
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#define CHAR_PATH_SEPARATOR '\\'
|
||||
#define WCHAR_PATH_SEPARATOR L'\\'
|
||||
#define STRING_PATH_SEPARATOR "\\"
|
||||
#define WSTRING_PATH_SEPARATOR L"\\"
|
||||
|
||||
#else
|
||||
|
||||
#define CHAR_PATH_SEPARATOR '/'
|
||||
#define WCHAR_PATH_SEPARATOR L'/'
|
||||
#define STRING_PATH_SEPARATOR "/"
|
||||
#define WSTRING_PATH_SEPARATOR L"/"
|
||||
|
||||
#endif
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
31
LZMA/UefiLzma.h
Normal file
31
LZMA/UefiLzma.h
Normal file
@ -0,0 +1,31 @@
|
||||
/* LZMA UEFI header file
|
||||
|
||||
Copyright (c) 2009, Intel Corporation. All rights reserved.
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __UEFILZMA_H__
|
||||
#define __UEFILZMA_H__
|
||||
|
||||
#include "../basetypes.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#undef _WIN32
|
||||
#endif
|
||||
|
||||
#ifdef _WIN64
|
||||
#undef _WIN64
|
||||
#endif
|
||||
|
||||
#define _LZMA_SIZE_OPT
|
||||
#define _7ZIP_ST
|
||||
|
||||
#endif // __UEFILZMA_H__
|
||||
|
1598
Tiano/EfiCompress.c
Normal file
1598
Tiano/EfiCompress.c
Normal file
File diff suppressed because it is too large
Load Diff
101
Tiano/EfiTianoCompress.h
Normal file
101
Tiano/EfiTianoCompress.h
Normal file
@ -0,0 +1,101 @@
|
||||
/* EFI/Tiano Compress Header
|
||||
|
||||
Copyright (c) 2004 - 2008, Intel Corporation. All rights reserved.
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
Module Name:
|
||||
|
||||
TianoCompress.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Header file for compression routine.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _EFITIANOCOMPRESS_H_
|
||||
#define _EFITIANOCOMPRESS_H_
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../basetypes.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Tiano compression routine.
|
||||
|
||||
Arguments:
|
||||
|
||||
SrcBuffer - The buffer storing the source data
|
||||
SrcSize - The size of source data
|
||||
DstBuffer - The buffer to store the compressed data
|
||||
DstSize - On input, the size of DstBuffer; On output,
|
||||
the size of the actual compressed data.
|
||||
|
||||
Returns:
|
||||
|
||||
EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. this case,
|
||||
DstSize contains the size needed.
|
||||
EFI_SUCCESS - Compression is successful.
|
||||
EFI_OUT_OF_RESOURCES - No resource to complete function.
|
||||
EFI_INVALID_PARAMETER - Parameter supplied is wrong.
|
||||
|
||||
--*/
|
||||
INT32
|
||||
TianoCompress (
|
||||
UINT8 *SrcBuffer,
|
||||
UINT32 SrcSize,
|
||||
UINT8 *DstBuffer,
|
||||
UINT32 *DstSize
|
||||
)
|
||||
;
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
EFI 1.1 compression routine.
|
||||
|
||||
Arguments:
|
||||
|
||||
SrcBuffer - The buffer storing the source data
|
||||
SrcSize - The size of source data
|
||||
DstBuffer - The buffer to store the compressed data
|
||||
DstSize - On input, the size of DstBuffer; On output,
|
||||
the size of the actual compressed data.
|
||||
|
||||
Returns:
|
||||
|
||||
EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. this case,
|
||||
DstSize contains the size needed.
|
||||
EFI_SUCCESS - Compression is successful.
|
||||
EFI_OUT_OF_RESOURCES - No resource to complete function.
|
||||
EFI_INVALID_PARAMETER - Parameter supplied is wrong.
|
||||
|
||||
--*/
|
||||
INT32
|
||||
EfiCompress (
|
||||
UINT8 *SrcBuffer,
|
||||
UINT32 SrcSize,
|
||||
UINT8 *DstBuffer,
|
||||
UINT32 *DstSize
|
||||
)
|
||||
;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
994
Tiano/EfiTianoDecompress.c
Normal file
994
Tiano/EfiTianoDecompress.c
Normal file
@ -0,0 +1,994 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2004 - 2006, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
Module Name:
|
||||
|
||||
Decompress.c
|
||||
|
||||
Abstract:
|
||||
|
||||
Decompressor. Algorithm Ported from OPSD code (Decomp.asm)
|
||||
|
||||
--*/
|
||||
|
||||
#include "EfiTianoDecompress.h"
|
||||
|
||||
//
|
||||
// Decompression algorithm begins here
|
||||
//
|
||||
#define BITBUFSIZ 32
|
||||
#define MAXMATCH 256
|
||||
#define THRESHOLD 3
|
||||
#define CODE_BIT 16
|
||||
//#define UINT8_MAX 0xff
|
||||
#define BAD_TABLE - 1
|
||||
|
||||
//
|
||||
// C: Char&Len Set; P: Position Set; T: exTra Set
|
||||
//
|
||||
#define NC (0xff + MAXMATCH + 2 - THRESHOLD)
|
||||
#define CBIT 9
|
||||
#define MAXPBIT 5
|
||||
#define TBIT 5
|
||||
#define MAXNP ((1U << MAXPBIT) - 1)
|
||||
#define NT (CODE_BIT + 3)
|
||||
#if NT > MAXNP
|
||||
#define NPT NT
|
||||
#else
|
||||
#define NPT MAXNP
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
UINT8 *mSrcBase; // Starting address of compressed data
|
||||
UINT8 *mDstBase; // Starting address of decompressed data
|
||||
UINT32 mOutBuf;
|
||||
UINT32 mInBuf;
|
||||
|
||||
UINT16 mBitCount;
|
||||
UINT32 mBitBuf;
|
||||
UINT32 mSubBitBuf;
|
||||
UINT16 mBlockSize;
|
||||
UINT32 mCompSize;
|
||||
UINT32 mOrigSize;
|
||||
|
||||
UINT16 mBadTableFlag;
|
||||
|
||||
UINT16 mLeft[2 * NC - 1];
|
||||
UINT16 mRight[2 * NC - 1];
|
||||
UINT8 mCLen[NC];
|
||||
UINT8 mPTLen[NPT];
|
||||
UINT16 mCTable[4096];
|
||||
UINT16 mPTTable[256];
|
||||
|
||||
//
|
||||
// The length of the field 'Position Set Code Length Array Size'Block Header.
|
||||
// For EFI 1.1 de/compression algorithm, mPBit = 4
|
||||
// For Tiano de/compression algorithm, mPBit = 5
|
||||
//
|
||||
UINT8 mPBit;
|
||||
} SCRATCH_DATA;
|
||||
|
||||
STATIC
|
||||
VOID
|
||||
FillBuf (
|
||||
SCRATCH_DATA *Sd,
|
||||
UINT16 NumOfBits
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Shift mBitBuf NumOfBits left. ReadNumOfBits of bits from source.
|
||||
|
||||
Arguments:
|
||||
|
||||
Sd - The global scratch data
|
||||
NumOfBits - The number of bits to shift and read.
|
||||
|
||||
Returns: (VOID)
|
||||
|
||||
--*/
|
||||
{
|
||||
Sd->mBitBuf = (UINT32) (Sd->mBitBuf << NumOfBits);
|
||||
|
||||
while (NumOfBits > Sd->mBitCount) {
|
||||
|
||||
Sd->mBitBuf |= (UINT32) (Sd->mSubBitBuf << (NumOfBits = (UINT16) (NumOfBits - Sd->mBitCount)));
|
||||
|
||||
if (Sd->mCompSize > 0) {
|
||||
//
|
||||
// Get 1 byte into SubBitBuf
|
||||
//
|
||||
Sd->mCompSize--;
|
||||
Sd->mSubBitBuf = 0;
|
||||
Sd->mSubBitBuf = Sd->mSrcBase[Sd->mInBuf++];
|
||||
Sd->mBitCount = 8;
|
||||
|
||||
} else {
|
||||
//
|
||||
// No more bits from the source, just pad zero bit.
|
||||
//
|
||||
Sd->mSubBitBuf = 0;
|
||||
Sd->mBitCount = 8;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Sd->mBitCount = (UINT16) (Sd->mBitCount - NumOfBits);
|
||||
Sd->mBitBuf |= Sd->mSubBitBuf >> Sd->mBitCount;
|
||||
}
|
||||
|
||||
STATIC
|
||||
UINT32
|
||||
GetBits (
|
||||
SCRATCH_DATA *Sd,
|
||||
UINT16 NumOfBits
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Get NumOfBits of bits from mBitBuf. Fill mBitBuf with subsequent
|
||||
NumOfBits of bits from source. Returns NumOfBits of bits that are
|
||||
popped.
|
||||
|
||||
Arguments:
|
||||
|
||||
Sd - The global scratch data.
|
||||
NumOfBits - The number of bits to pop and read.
|
||||
|
||||
Returns:
|
||||
|
||||
The bits that are popped.
|
||||
|
||||
--*/
|
||||
{
|
||||
UINT32 Bits;
|
||||
|
||||
Bits = (UINT32) (Sd->mBitBuf >> (BITBUFSIZ - NumOfBits));
|
||||
|
||||
FillBuf (Sd, NumOfBits);
|
||||
|
||||
return Bits;
|
||||
}
|
||||
|
||||
STATIC
|
||||
UINT16
|
||||
MakeTable (
|
||||
SCRATCH_DATA *Sd,
|
||||
UINT16 NumOfChar,
|
||||
UINT8 *BitLen,
|
||||
UINT16 TableBits,
|
||||
UINT16 *Table
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Creates Huffman Code mapping table according to code length array.
|
||||
|
||||
Arguments:
|
||||
|
||||
Sd - The global scratch data
|
||||
NumOfChar - Number of symbolsthe symbol set
|
||||
BitLen - Code length array
|
||||
TableBits - The width of the mapping table
|
||||
Table - The table
|
||||
|
||||
Returns:
|
||||
|
||||
0 - OK.
|
||||
BAD_TABLE - The table is corrupted.
|
||||
|
||||
--*/
|
||||
{
|
||||
UINT16 Count[17];
|
||||
UINT16 Weight[17];
|
||||
UINT16 Start[18];
|
||||
UINT16 *Pointer;
|
||||
UINT16 Index3;
|
||||
UINT16 Index;
|
||||
UINT16 Len;
|
||||
UINT16 Char;
|
||||
UINT16 JuBits;
|
||||
UINT16 Avail;
|
||||
UINT16 NextCode;
|
||||
UINT16 Mask;
|
||||
|
||||
for (Index = 1; Index <= 16; Index++) {
|
||||
Count[Index] = 0;
|
||||
}
|
||||
|
||||
for (Index = 0; Index < NumOfChar; Index++) {
|
||||
Count[BitLen[Index]]++;
|
||||
}
|
||||
|
||||
Start[1] = 0;
|
||||
|
||||
for (Index = 1; Index <= 16; Index++) {
|
||||
Start[Index + 1] = (UINT16) (Start[Index] + (Count[Index] << (16 - Index)));
|
||||
}
|
||||
|
||||
if (Start[17] != 0) {
|
||||
/*(1U << 16)*/
|
||||
return (UINT16) BAD_TABLE;
|
||||
}
|
||||
|
||||
JuBits = (UINT16) (16 - TableBits);
|
||||
|
||||
for (Index = 1; Index <= TableBits; Index++) {
|
||||
Start[Index] >>= JuBits;
|
||||
Weight[Index] = (UINT16) (1U << (TableBits - Index));
|
||||
}
|
||||
|
||||
while (Index <= 16) {
|
||||
Weight[Index++] = (UINT16) (1U << (16 - Index));
|
||||
}
|
||||
|
||||
Index = (UINT16) (Start[TableBits + 1] >> JuBits);
|
||||
|
||||
if (Index != 0) {
|
||||
Index3 = (UINT16) (1U << TableBits);
|
||||
while (Index != Index3) {
|
||||
Table[Index++] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Avail = NumOfChar;
|
||||
Mask = (UINT16) (1U << (15 - TableBits));
|
||||
|
||||
for (Char = 0; Char < NumOfChar; Char++) {
|
||||
|
||||
Len = BitLen[Char];
|
||||
if (Len == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
NextCode = (UINT16) (Start[Len] + Weight[Len]);
|
||||
|
||||
if (Len <= TableBits) {
|
||||
|
||||
for (Index = Start[Len]; Index < NextCode; Index++) {
|
||||
Table[Index] = Char;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
Index3 = Start[Len];
|
||||
Pointer = &Table[Index3 >> JuBits];
|
||||
Index = (UINT16) (Len - TableBits);
|
||||
|
||||
while (Index != 0) {
|
||||
if (*Pointer == 0) {
|
||||
Sd->mRight[Avail] = Sd->mLeft[Avail] = 0;
|
||||
*Pointer = Avail++;
|
||||
}
|
||||
|
||||
if (Index3 & Mask) {
|
||||
Pointer = &Sd->mRight[*Pointer];
|
||||
} else {
|
||||
Pointer = &Sd->mLeft[*Pointer];
|
||||
}
|
||||
|
||||
Index3 <<= 1;
|
||||
Index--;
|
||||
}
|
||||
|
||||
*Pointer = Char;
|
||||
|
||||
}
|
||||
|
||||
Start[Len] = NextCode;
|
||||
}
|
||||
//
|
||||
// Succeeds
|
||||
//
|
||||
return 0;
|
||||
}
|
||||
|
||||
STATIC
|
||||
UINT32
|
||||
DecodeP (
|
||||
SCRATCH_DATA *Sd
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Decodes a position value.
|
||||
|
||||
Arguments:
|
||||
|
||||
Sd - the global scratch data
|
||||
|
||||
Returns:
|
||||
|
||||
The position value decoded.
|
||||
|
||||
--*/
|
||||
{
|
||||
UINT16 Val;
|
||||
UINT32 Mask;
|
||||
UINT32 Pos;
|
||||
|
||||
Val = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)];
|
||||
|
||||
if (Val >= MAXNP) {
|
||||
Mask = 1U << (BITBUFSIZ - 1 - 8);
|
||||
|
||||
do {
|
||||
|
||||
if (Sd->mBitBuf & Mask) {
|
||||
Val = Sd->mRight[Val];
|
||||
} else {
|
||||
Val = Sd->mLeft[Val];
|
||||
}
|
||||
|
||||
Mask >>= 1;
|
||||
} while (Val >= MAXNP);
|
||||
}
|
||||
//
|
||||
// Advance what we have read
|
||||
//
|
||||
FillBuf (Sd, Sd->mPTLen[Val]);
|
||||
|
||||
Pos = Val;
|
||||
if (Val > 1) {
|
||||
Pos = (UINT32) ((1U << (Val - 1)) + GetBits (Sd, (UINT16) (Val - 1)));
|
||||
}
|
||||
|
||||
return Pos;
|
||||
}
|
||||
|
||||
STATIC
|
||||
UINT16
|
||||
ReadPTLen (
|
||||
SCRATCH_DATA *Sd,
|
||||
UINT16 nn,
|
||||
UINT16 nbit,
|
||||
UINT16 Special
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Reads code lengths for the Extra Set or the Position Set
|
||||
|
||||
Arguments:
|
||||
|
||||
Sd - The global scratch data
|
||||
nn - Number of symbols
|
||||
nbit - Number of bits needed to represent nn
|
||||
Special - The special symbol that needs to be taken care of
|
||||
|
||||
Returns:
|
||||
|
||||
0 - OK.
|
||||
BAD_TABLE - Table is corrupted.
|
||||
|
||||
--*/
|
||||
{
|
||||
UINT16 Number;
|
||||
UINT16 CharC;
|
||||
UINT16 Index;
|
||||
UINT32 Mask;
|
||||
|
||||
Number = (UINT16) GetBits (Sd, nbit);
|
||||
|
||||
if (Number == 0) {
|
||||
CharC = (UINT16) GetBits (Sd, nbit);
|
||||
|
||||
for (Index = 0; Index < 256; Index++) {
|
||||
Sd->mPTTable[Index] = CharC;
|
||||
}
|
||||
|
||||
for (Index = 0; Index < nn; Index++) {
|
||||
Sd->mPTLen[Index] = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Index = 0;
|
||||
|
||||
while (Index < Number) {
|
||||
|
||||
CharC = (UINT16) (Sd->mBitBuf >> (BITBUFSIZ - 3));
|
||||
|
||||
if (CharC == 7) {
|
||||
Mask = 1U << (BITBUFSIZ - 1 - 3);
|
||||
while (Mask & Sd->mBitBuf) {
|
||||
Mask >>= 1;
|
||||
CharC += 1;
|
||||
}
|
||||
}
|
||||
|
||||
FillBuf (Sd, (UINT16) ((CharC < 7) ? 3 : CharC - 3));
|
||||
|
||||
Sd->mPTLen[Index++] = (UINT8) CharC;
|
||||
|
||||
if (Index == Special) {
|
||||
CharC = (UINT16) GetBits (Sd, 2);
|
||||
while ((INT16) (--CharC) >= 0) {
|
||||
Sd->mPTLen[Index++] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (Index < nn) {
|
||||
Sd->mPTLen[Index++] = 0;
|
||||
}
|
||||
|
||||
return MakeTable (Sd, nn, Sd->mPTLen, 8, Sd->mPTTable);
|
||||
}
|
||||
|
||||
STATIC
|
||||
VOID
|
||||
ReadCLen (
|
||||
SCRATCH_DATA *Sd
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Reads code lengths for Char&Len Set.
|
||||
|
||||
Arguments:
|
||||
|
||||
Sd - the global scratch data
|
||||
|
||||
Returns: (VOID)
|
||||
|
||||
--*/
|
||||
{
|
||||
UINT16 Number;
|
||||
UINT16 CharC;
|
||||
UINT16 Index;
|
||||
UINT32 Mask;
|
||||
|
||||
Number = (UINT16) GetBits (Sd, CBIT);
|
||||
|
||||
if (Number == 0) {
|
||||
CharC = (UINT16) GetBits (Sd, CBIT);
|
||||
|
||||
for (Index = 0; Index < NC; Index++) {
|
||||
Sd->mCLen[Index] = 0;
|
||||
}
|
||||
|
||||
for (Index = 0; Index < 4096; Index++) {
|
||||
Sd->mCTable[Index] = CharC;
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
Index = 0;
|
||||
while (Index < Number) {
|
||||
|
||||
CharC = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)];
|
||||
if (CharC >= NT) {
|
||||
Mask = 1U << (BITBUFSIZ - 1 - 8);
|
||||
|
||||
do {
|
||||
|
||||
if (Mask & Sd->mBitBuf) {
|
||||
CharC = Sd->mRight[CharC];
|
||||
} else {
|
||||
CharC = Sd->mLeft[CharC];
|
||||
}
|
||||
|
||||
Mask >>= 1;
|
||||
|
||||
} while (CharC >= NT);
|
||||
}
|
||||
//
|
||||
// Advance what we have read
|
||||
//
|
||||
FillBuf (Sd, Sd->mPTLen[CharC]);
|
||||
|
||||
if (CharC <= 2) {
|
||||
|
||||
if (CharC == 0) {
|
||||
CharC = 1;
|
||||
} else if (CharC == 1) {
|
||||
CharC = (UINT16) (GetBits (Sd, 4) + 3);
|
||||
} else if (CharC == 2) {
|
||||
CharC = (UINT16) (GetBits (Sd, CBIT) + 20);
|
||||
}
|
||||
|
||||
while ((INT16) (--CharC) >= 0) {
|
||||
Sd->mCLen[Index++] = 0;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
Sd->mCLen[Index++] = (UINT8) (CharC - 2);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
while (Index < NC) {
|
||||
Sd->mCLen[Index++] = 0;
|
||||
}
|
||||
|
||||
MakeTable (Sd, NC, Sd->mCLen, 12, Sd->mCTable);
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
STATIC
|
||||
UINT16
|
||||
DecodeC (
|
||||
SCRATCH_DATA *Sd
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Decode a character/length value.
|
||||
|
||||
Arguments:
|
||||
|
||||
Sd - The global scratch data.
|
||||
|
||||
Returns:
|
||||
|
||||
The value decoded.
|
||||
|
||||
--*/
|
||||
{
|
||||
UINT16 Index2;
|
||||
UINT32 Mask;
|
||||
|
||||
if (Sd->mBlockSize == 0) {
|
||||
//
|
||||
// Starting a new block
|
||||
//
|
||||
Sd->mBlockSize = (UINT16) GetBits (Sd, 16);
|
||||
Sd->mBadTableFlag = ReadPTLen (Sd, NT, TBIT, 3);
|
||||
if (Sd->mBadTableFlag != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ReadCLen (Sd);
|
||||
|
||||
Sd->mBadTableFlag = ReadPTLen (Sd, MAXNP, Sd->mPBit, (UINT16) (-1));
|
||||
if (Sd->mBadTableFlag != 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
Sd->mBlockSize--;
|
||||
Index2 = Sd->mCTable[Sd->mBitBuf >> (BITBUFSIZ - 12)];
|
||||
|
||||
if (Index2 >= NC) {
|
||||
Mask = 1U << (BITBUFSIZ - 1 - 12);
|
||||
|
||||
do {
|
||||
if (Sd->mBitBuf & Mask) {
|
||||
Index2 = Sd->mRight[Index2];
|
||||
} else {
|
||||
Index2 = Sd->mLeft[Index2];
|
||||
}
|
||||
|
||||
Mask >>= 1;
|
||||
} while (Index2 >= NC);
|
||||
}
|
||||
//
|
||||
// Advance what we have read
|
||||
//
|
||||
FillBuf (Sd, Sd->mCLen[Index2]);
|
||||
|
||||
return Index2;
|
||||
}
|
||||
|
||||
STATIC
|
||||
VOID
|
||||
Decode (
|
||||
SCRATCH_DATA *Sd
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Decode the source data and put the resulting data into the destination buffer.
|
||||
|
||||
Arguments:
|
||||
|
||||
Sd - The global scratch data
|
||||
|
||||
Returns: (VOID)
|
||||
|
||||
--*/
|
||||
{
|
||||
UINT16 BytesRemain;
|
||||
UINT32 DataIdx;
|
||||
UINT16 CharC;
|
||||
|
||||
BytesRemain = (UINT16) (-1);
|
||||
|
||||
DataIdx = 0;
|
||||
|
||||
for (;;) {
|
||||
CharC = DecodeC (Sd);
|
||||
if (Sd->mBadTableFlag != 0) {
|
||||
return ;
|
||||
}
|
||||
|
||||
if (CharC < 256) {
|
||||
//
|
||||
// Process an Original character
|
||||
//
|
||||
if (Sd->mOutBuf >= Sd->mOrigSize) {
|
||||
return ;
|
||||
} else {
|
||||
Sd->mDstBase[Sd->mOutBuf++] = (UINT8) CharC;
|
||||
}
|
||||
|
||||
} else {
|
||||
//
|
||||
// Process a Pointer
|
||||
//
|
||||
CharC = (UINT16) (CharC - (UINT8_MAX + 1 - THRESHOLD));
|
||||
|
||||
BytesRemain = CharC;
|
||||
|
||||
DataIdx = Sd->mOutBuf - DecodeP (Sd) - 1;
|
||||
|
||||
BytesRemain--;
|
||||
while ((INT16) (BytesRemain) >= 0) {
|
||||
Sd->mDstBase[Sd->mOutBuf++] = Sd->mDstBase[DataIdx++];
|
||||
if (Sd->mOutBuf >= Sd->mOrigSize) {
|
||||
return ;
|
||||
}
|
||||
|
||||
BytesRemain--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
UINT32
|
||||
GetInfo (
|
||||
VOID *Source,
|
||||
UINT32 SrcSize,
|
||||
UINT32 *DstSize,
|
||||
UINT32 *ScratchSize
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
The internal implementation of *_DECOMPRESS_PROTOCOL.GetInfo().
|
||||
|
||||
Arguments:
|
||||
|
||||
Source - The source buffer containing the compressed data.
|
||||
SrcSize - The size of source buffer
|
||||
DstSize - The size of destination buffer.
|
||||
ScratchSize - The size of scratch buffer.
|
||||
|
||||
Returns:
|
||||
|
||||
EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved.
|
||||
EFI_INVALID_PARAMETER - The source data is corrupted
|
||||
|
||||
--*/
|
||||
{
|
||||
UINT8 *Src;
|
||||
|
||||
*ScratchSize = sizeof (SCRATCH_DATA);
|
||||
|
||||
Src = Source;
|
||||
if (SrcSize < 8) {
|
||||
return ERR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
*DstSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24);
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
|
||||
UINT32
|
||||
Decompress (
|
||||
VOID *Source,
|
||||
UINT32 SrcSize,
|
||||
VOID *Destination,
|
||||
UINT32 DstSize,
|
||||
VOID *Scratch,
|
||||
UINT32 ScratchSize,
|
||||
UINT8 Version
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
The internal implementation of *_DECOMPRESS_PROTOCOL.Decompress().
|
||||
|
||||
Arguments:
|
||||
|
||||
Source - The source buffer containing the compressed data.
|
||||
SrcSize - The size of source buffer
|
||||
Destination - The destination buffer to store the decompressed data
|
||||
DstSize - The size of destination buffer.
|
||||
Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data.
|
||||
ScratchSize - The size of scratch buffer.
|
||||
Version - The version of de/compression algorithm.
|
||||
Version 1 for EFI 1.1 de/compression algorithm.
|
||||
Version 2 for Tiano de/compression algorithm.
|
||||
|
||||
Returns:
|
||||
|
||||
EFI_SUCCESS - Decompression is successfull
|
||||
EFI_INVALID_PARAMETER - The source data is corrupted
|
||||
|
||||
--*/
|
||||
{
|
||||
UINT32 Index;
|
||||
UINT32 CompSize;
|
||||
UINT32 OrigSize;
|
||||
UINT32 Status;
|
||||
SCRATCH_DATA *Sd;
|
||||
UINT8 *Src;
|
||||
UINT8 *Dst;
|
||||
|
||||
Status = ERR_SUCCESS;
|
||||
Src = Source;
|
||||
Dst = Destination;
|
||||
|
||||
if (ScratchSize < sizeof (SCRATCH_DATA)) {
|
||||
return ERR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Sd = (SCRATCH_DATA *) Scratch;
|
||||
|
||||
if (SrcSize < 8) {
|
||||
return ERR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
CompSize = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24);
|
||||
OrigSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24);
|
||||
|
||||
//
|
||||
// If compressed file size is 0, return
|
||||
//
|
||||
if (OrigSize == 0) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (SrcSize < CompSize + 8) {
|
||||
return ERR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (DstSize != OrigSize) {
|
||||
return ERR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Src = Src + 8;
|
||||
|
||||
for (Index = 0; Index < sizeof (SCRATCH_DATA); Index++) {
|
||||
((UINT8 *) Sd)[Index] = 0;
|
||||
}
|
||||
//
|
||||
// The length of the field 'Position Set Code Length Array Size'Block Header.
|
||||
// For EFI 1.1 de/compression algorithm(Version 1), mPBit = 4
|
||||
// For Tiano de/compression algorithm(Version 2), mPBit = 5
|
||||
//
|
||||
switch (Version) {
|
||||
case 1:
|
||||
Sd->mPBit = 4;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
Sd->mPBit = 5;
|
||||
break;
|
||||
|
||||
default:
|
||||
//
|
||||
// Currently, only have 2 versions
|
||||
//
|
||||
return ERR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Sd->mSrcBase = Src;
|
||||
Sd->mDstBase = Dst;
|
||||
Sd->mCompSize = CompSize;
|
||||
Sd->mOrigSize = OrigSize;
|
||||
|
||||
//
|
||||
// Fill the first BITBUFSIZ bits
|
||||
//
|
||||
FillBuf (Sd, BITBUFSIZ);
|
||||
|
||||
//
|
||||
// Decompress it
|
||||
//
|
||||
Decode (Sd);
|
||||
|
||||
if (Sd->mBadTableFlag != 0) {
|
||||
//
|
||||
// Something wrong with the source
|
||||
//
|
||||
Status = ERR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
UINT32
|
||||
EFIAPI
|
||||
EfiGetInfo (
|
||||
VOID *Source,
|
||||
UINT32 SrcSize,
|
||||
UINT32 *DstSize,
|
||||
UINT32 *ScratchSize
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
The implementation is same as that of EFI_DECOMPRESS_PROTOCOL.GetInfo().
|
||||
|
||||
Arguments:
|
||||
|
||||
This - The protocol instance pointer
|
||||
Source - The source buffer containing the compressed data.
|
||||
SrcSize - The size of source buffer
|
||||
DstSize - The size of destination buffer.
|
||||
ScratchSize - The size of scratch buffer.
|
||||
|
||||
Returns:
|
||||
|
||||
EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved.
|
||||
EFI_INVALID_PARAMETER - The source data is corrupted
|
||||
|
||||
--*/
|
||||
{
|
||||
return GetInfo (
|
||||
Source,
|
||||
SrcSize,
|
||||
DstSize,
|
||||
ScratchSize
|
||||
);
|
||||
}
|
||||
|
||||
UINT32
|
||||
EFIAPI
|
||||
EfiDecompress (
|
||||
VOID *Source,
|
||||
UINT32 SrcSize,
|
||||
VOID *Destination,
|
||||
UINT32 DstSize,
|
||||
VOID *Scratch,
|
||||
UINT32 ScratchSize
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
The implementation is same as that of EFI_DECOMPRESS_PROTOCOL.Decompress().
|
||||
|
||||
Arguments:
|
||||
|
||||
This - The protocol instance pointer
|
||||
Source - The source buffer containing the compressed data.
|
||||
SrcSize - The size of source buffer
|
||||
Destination - The destination buffer to store the decompressed data
|
||||
DstSize - The size of destination buffer.
|
||||
Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data.
|
||||
ScratchSize - The size of scratch buffer.
|
||||
|
||||
Returns:
|
||||
|
||||
EFI_SUCCESS - Decompression is successfull
|
||||
EFI_INVALID_PARAMETER - The source data is corrupted
|
||||
|
||||
--*/
|
||||
{
|
||||
//
|
||||
// For EFI 1.1 de/compression algorithm, the version is 1.
|
||||
//
|
||||
return Decompress (
|
||||
Source,
|
||||
SrcSize,
|
||||
Destination,
|
||||
DstSize,
|
||||
Scratch,
|
||||
ScratchSize,
|
||||
1
|
||||
);
|
||||
}
|
||||
|
||||
UINT32
|
||||
EFIAPI
|
||||
TianoGetInfo (
|
||||
VOID *Source,
|
||||
UINT32 SrcSize,
|
||||
UINT32 *DstSize,
|
||||
UINT32 *ScratchSize
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
The implementation is same as that of EFI_TIANO_DECOMPRESS_PROTOCOL.GetInfo().
|
||||
|
||||
Arguments:
|
||||
|
||||
This - The protocol instance pointer
|
||||
Source - The source buffer containing the compressed data.
|
||||
SrcSize - The size of source buffer
|
||||
DstSize - The size of destination buffer.
|
||||
ScratchSize - The size of scratch buffer.
|
||||
|
||||
Returns:
|
||||
|
||||
EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved.
|
||||
EFI_INVALID_PARAMETER - The source data is corrupted
|
||||
|
||||
--*/
|
||||
{
|
||||
return GetInfo (
|
||||
Source,
|
||||
SrcSize,
|
||||
DstSize,
|
||||
ScratchSize
|
||||
);
|
||||
}
|
||||
|
||||
UINT32
|
||||
EFIAPI
|
||||
TianoDecompress (
|
||||
VOID *Source,
|
||||
UINT32 SrcSize,
|
||||
VOID *Destination,
|
||||
UINT32 DstSize,
|
||||
VOID *Scratch,
|
||||
UINT32 ScratchSize
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
The implementation is same as that of EFI_TIANO_DECOMPRESS_PROTOCOL.Decompress().
|
||||
|
||||
Arguments:
|
||||
|
||||
This - The protocol instance pointer
|
||||
Source - The source buffer containing the compressed data.
|
||||
SrcSize - The size of source buffer
|
||||
Destination - The destination buffer to store the decompressed data
|
||||
DstSize - The size of destination buffer.
|
||||
Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data.
|
||||
ScratchSize - The size of scratch buffer.
|
||||
|
||||
Returns:
|
||||
|
||||
EFI_SUCCESS - Decompression is successfull
|
||||
EFI_INVALID_PARAMETER - The source data is corrupted
|
||||
|
||||
--*/
|
||||
{
|
||||
//
|
||||
// For Tiano de/compression algorithm, the version is 2.
|
||||
//
|
||||
return Decompress (
|
||||
Source,
|
||||
SrcSize,
|
||||
Destination,
|
||||
DstSize,
|
||||
Scratch,
|
||||
ScratchSize,
|
||||
2
|
||||
);
|
||||
}
|
||||
|
185
Tiano/EfiTianoDecompress.h
Normal file
185
Tiano/EfiTianoDecompress.h
Normal file
@ -0,0 +1,185 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2004 - 2006, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
Module Name:
|
||||
|
||||
Decompress.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Header file for decompression routine.
|
||||
Providing both EFI and Tiano decompress algorithms.
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef _EFITIANODECOMPRESS_H_
|
||||
#define _EFITIANODECOMPRESS_H_
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../basetypes.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
UINT32
|
||||
EFIAPI
|
||||
EfiGetInfo (
|
||||
VOID *Source,
|
||||
UINT32 SrcSize,
|
||||
UINT32 *DstSize,
|
||||
UINT32 *ScratchSize
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
The implementation is same as that of EFI_DECOMPRESS_PROTOCOL.GetInfo().
|
||||
|
||||
Arguments:
|
||||
|
||||
This - The protocol instance pointer
|
||||
Source - The source buffer containing the compressed data.
|
||||
SrcSize - The size of source buffer
|
||||
DstSize - The size of destination buffer.
|
||||
ScratchSize - The size of scratch buffer.
|
||||
|
||||
Returns:
|
||||
|
||||
EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved.
|
||||
EFI_INVALID_PARAMETER - The source data is corrupted
|
||||
|
||||
--*/
|
||||
;
|
||||
|
||||
UINT32
|
||||
EFIAPI
|
||||
EfiDecompress (
|
||||
VOID *Source,
|
||||
UINT32 SrcSize,
|
||||
VOID *Destination,
|
||||
UINT32 DstSize,
|
||||
VOID *Scratch,
|
||||
UINT32 ScratchSize
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
The implementation is same as that of EFI_DECOMPRESS_PROTOCOL.Decompress().
|
||||
|
||||
Arguments:
|
||||
|
||||
This - The protocol instance pointer
|
||||
Source - The source buffer containing the compressed data.
|
||||
SrcSize - The size of source buffer
|
||||
Destination - The destination buffer to store the decompressed data
|
||||
DstSize - The size of destination buffer.
|
||||
Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data.
|
||||
ScratchSize - The size of scratch buffer.
|
||||
|
||||
Returns:
|
||||
|
||||
EFI_SUCCESS - Decompression is successfull
|
||||
EFI_INVALID_PARAMETER - The source data is corrupted
|
||||
|
||||
--*/
|
||||
;
|
||||
|
||||
UINT32
|
||||
EFIAPI
|
||||
TianoGetInfo (
|
||||
VOID *Source,
|
||||
UINT32 SrcSize,
|
||||
UINT32 *DstSize,
|
||||
UINT32 *ScratchSize
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
The implementation is same as that of EFI_TIANO_DECOMPRESS_PROTOCOL.GetInfo().
|
||||
|
||||
Arguments:
|
||||
|
||||
This - The protocol instance pointer
|
||||
Source - The source buffer containing the compressed data.
|
||||
SrcSize - The size of source buffer
|
||||
DstSize - The size of destination buffer.
|
||||
ScratchSize - The size of scratch buffer.
|
||||
|
||||
Returns:
|
||||
|
||||
EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved.
|
||||
EFI_INVALID_PARAMETER - The source data is corrupted
|
||||
|
||||
--*/
|
||||
;
|
||||
|
||||
UINT32
|
||||
EFIAPI
|
||||
TianoDecompress (
|
||||
VOID *Source,
|
||||
UINT32 SrcSize,
|
||||
VOID *Destination,
|
||||
UINT32 DstSize,
|
||||
VOID *Scratch,
|
||||
UINT32 ScratchSize
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
The implementation is same as that of EFI_TIANO_DECOMPRESS_PROTOCOL.Decompress().
|
||||
|
||||
Arguments:
|
||||
|
||||
This - The protocol instance pointer
|
||||
Source - The source buffer containing the compressed data.
|
||||
SrcSize - The size of source buffer
|
||||
Destination - The destination buffer to store the decompressed data
|
||||
DstSize - The size of destination buffer.
|
||||
Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data.
|
||||
ScratchSize - The size of scratch buffer.
|
||||
|
||||
Returns:
|
||||
|
||||
EFI_SUCCESS - Decompression is successfull
|
||||
EFI_INVALID_PARAMETER - The source data is corrupted
|
||||
|
||||
--*/
|
||||
;
|
||||
|
||||
typedef
|
||||
UINT32
|
||||
(*GETINFO_FUNCTION) (
|
||||
VOID *Source,
|
||||
UINT32 SrcSize,
|
||||
UINT32 *DstSize,
|
||||
UINT32 *ScratchSize
|
||||
);
|
||||
|
||||
typedef
|
||||
UINT32
|
||||
(*DECOMPRESS_FUNCTION) (
|
||||
VOID *Source,
|
||||
UINT32 SrcSize,
|
||||
VOID *Destination,
|
||||
UINT32 DstSize,
|
||||
VOID *Scratch,
|
||||
UINT32 ScratchSize
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
1753
Tiano/TianoCompress.c
Normal file
1753
Tiano/TianoCompress.c
Normal file
File diff suppressed because it is too large
Load Diff
86
basetypes.h
Normal file
86
basetypes.h
Normal file
@ -0,0 +1,86 @@
|
||||
/* basetypes.h
|
||||
|
||||
Copyright (c) 2013, Nikolaj Schlej. All rights reserved.
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __BASETYPES_H__
|
||||
#define __BASETYPES_H__
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef uint8_t BOOLEAN;
|
||||
typedef int8_t INT8;
|
||||
typedef uint8_t UINT8;
|
||||
typedef int16_t INT16;
|
||||
typedef uint16_t UINT16;
|
||||
typedef int32_t INT32;
|
||||
typedef uint32_t UINT32;
|
||||
typedef int64_t INT64;
|
||||
typedef uint64_t UINT64;
|
||||
typedef char CHAR8;
|
||||
typedef uint16_t CHAR16;
|
||||
|
||||
#define CONST const
|
||||
#define VOID void
|
||||
#define STATIC static
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE ((BOOLEAN)(1==1))
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE ((BOOLEAN)(0==1))
|
||||
#endif
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL ((VOID *) 0)
|
||||
#endif
|
||||
|
||||
#if _MSC_EXTENSIONS
|
||||
//
|
||||
// Microsoft* compiler requires _EFIAPI useage, __cdecl is Microsoft* specific C.
|
||||
//
|
||||
#define EFIAPI __cdecl
|
||||
#endif
|
||||
|
||||
#if __GNUC__
|
||||
#define EFIAPI __attribute__((cdecl))
|
||||
#endif
|
||||
|
||||
#define ERR_SUCCESS 0
|
||||
#define ERR_INVALID_PARAMETER 1
|
||||
#define ERR_BUFFER_TOO_SMALL 2
|
||||
#define ERR_OUT_OF_RESOURCES 3
|
||||
#define ERR_OUT_OF_MEMORY 4
|
||||
#define ERR_FILE_OPEN 5
|
||||
#define ERR_FILE_READ 6
|
||||
#define ERR_FILE_WRITE 7
|
||||
#define ERR_INVALID_FLASH_DESCRIPTOR 8
|
||||
#define ERR_BIOS_REGION_NOT_FOUND 9
|
||||
#define ERR_VOLUMES_NOT_FOUND 10
|
||||
#define ERR_INVALID_VOLUME 11
|
||||
#define ERR_VOLUME_REVISION_NOT_SUPPORTED 12
|
||||
#define ERR_UNKNOWN_FFS 13
|
||||
|
||||
|
||||
// EFI GUID
|
||||
typedef struct{
|
||||
UINT8 Data[16];
|
||||
} EFI_GUID;
|
||||
|
||||
#define ALIGN4(Value) (((Value)+3) & ~3)
|
||||
#define ALIGN8(Value) (((Value)+7) & ~7)
|
||||
|
||||
#include <assert.h>
|
||||
#define ASSERT(x) assert(x)
|
||||
|
||||
#endif
|
34
descriptor.cpp
Normal file
34
descriptor.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
/* descriptor.cpp
|
||||
|
||||
Copyright (c) 2013, Nikolaj Schlej. All rights reserved.
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
*/
|
||||
|
||||
#include "descriptor.h"
|
||||
|
||||
// Calculate address of data structure addressed by descriptor address format
|
||||
// 8 bit base or limit
|
||||
UINT8* calculateAddress8(UINT8* baseAddress, const UINT8 baseOrLimit)
|
||||
{
|
||||
return baseAddress + baseOrLimit * 0x10;
|
||||
}
|
||||
|
||||
// 16 bit base or limit
|
||||
UINT8* calculateAddress16(UINT8* baseAddress, const UINT16 baseOrLimit)
|
||||
{
|
||||
return baseAddress + baseOrLimit * 0x1000;
|
||||
}
|
||||
|
||||
//Calculate size of region using its base and limit
|
||||
UINT32 calculateRegionSize(const UINT16 base, const UINT16 limit)
|
||||
{
|
||||
if (limit)
|
||||
return (limit + 1 - base) * 0x1000;
|
||||
return 0;
|
||||
}
|
163
descriptor.h
Normal file
163
descriptor.h
Normal file
@ -0,0 +1,163 @@
|
||||
/* descriptor.h
|
||||
|
||||
Copyright (c) 2013, Nikolaj Schlej. All rights reserved.
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
*/
|
||||
|
||||
#ifndef __DESCRIPTOR_H__
|
||||
#define __DESCRIPTOR_H__
|
||||
|
||||
#include "basetypes.h"
|
||||
|
||||
// Make sure we use right packing rules
|
||||
#pragma pack(push,1)
|
||||
|
||||
// Flash descriptor header
|
||||
typedef struct {
|
||||
UINT8 FfVector[16]; // Must be 16 0xFFs
|
||||
UINT32 Signature; // 0x0FF0A55A
|
||||
} FLASH_DESCRIPTOR_HEADER;
|
||||
|
||||
// Flash descriptor signature
|
||||
#define FLASH_DESCRIPTOR_SIGNATURE 0x0FF0A55A
|
||||
|
||||
// Descriptor region size
|
||||
#define FLASH_DESCRIPTOR_SIZE 0x1000
|
||||
|
||||
// Descriptor map
|
||||
// Base fields are storing bits [11:4] of actual base addresses, all other bits are 0
|
||||
typedef struct {
|
||||
UINT8 ComponentBase; // 0x03 on most machines
|
||||
UINT8 NumberOfFlashChips; // Zero-based number of flash chips installed on board
|
||||
UINT8 RegionBase; // 0x04 on most machines
|
||||
UINT8 NumberOfRegions; // Zero-based number of flash regions (descriptor is always included)
|
||||
UINT8 MasterBase; // 0x06 on most machines
|
||||
UINT8 NumberOfMasters; // Zero-based number of flash masters
|
||||
UINT8 PchStrapsBase; // 0x10 on most machines
|
||||
UINT8 NumberOfPchStraps; // One-based number of UINT32s to read as PCH Straps, min=0, max=255 (1 Kb)
|
||||
UINT8 ProcStrapsBase; // 0x20 on most machines
|
||||
UINT8 NumberOfProcStraps; // Number of PROC staps to be read, can be 0 or 1
|
||||
UINT8 IccTableBase; // 0x21 on most machines
|
||||
UINT8 NumberOfIccTableEntries; // 0x00 on most machines
|
||||
UINT8 DmiTableBase; // 0x25 on most machines
|
||||
UINT8 NumberOfDmiTableEntries; // 0x00 on most machines
|
||||
UINT16 ReservedZero; // Still unknown, zeroes in all descriptors I have seen
|
||||
} FLASH_DESCRIPTOR_MAP;
|
||||
|
||||
|
||||
// Component section
|
||||
// Flash parameters dword structure
|
||||
typedef struct {
|
||||
UINT8 FirstChipDensity : 3;
|
||||
UINT8 SecondFlashDensity : 3;
|
||||
UINT8 ReservedZero0 : 2; // Still unknown, zeroes in all descriptors I have seen
|
||||
UINT8 ReservedZero1 : 8; // Still unknown, zeroes in all descriptors I have seen
|
||||
UINT8 ReservedZero2 : 4; // Still unknown, zeroes in all descriptors I have seen
|
||||
UINT8 FastReadEnabled : 1;
|
||||
UINT8 FastReadFreqency : 3;
|
||||
UINT8 FlashReadStatusFrequency : 3;
|
||||
UINT8 FlashWriteFrequency : 3;
|
||||
UINT8 DualOutputFastReadSupported : 1;
|
||||
UINT8 ReservedZero3 : 1; // Still unknown, zero in all descriptors I have seen
|
||||
} FLASH_PARAMETERS;
|
||||
|
||||
// Flash densities
|
||||
#define FLASH_DENSITY_512KB 0x00
|
||||
#define FLASH_DENSITY_1MB 0x01
|
||||
#define FLASH_DENSITY_2MB 0x02
|
||||
#define FLASH_DENSITY_4MB 0x03
|
||||
#define FLASH_DENSITY_8MB 0x04
|
||||
#define FLASH_DENSITY_16MB 0x05
|
||||
|
||||
// Flash frequences
|
||||
#define FLASH_FREQUENCY_20MHZ 0x00
|
||||
#define FLASH_FREQUENCY_33MHZ 0x01
|
||||
#define FLASH_FREQUENCY_50MHZ 0x04
|
||||
|
||||
// Component section structure
|
||||
typedef struct {
|
||||
FLASH_PARAMETERS FlashParameters;
|
||||
UINT8 InvalidInstruction0; // Instructions for SPI chip, that must not be executed, like FLASH ERASE
|
||||
UINT8 InvalidInstruction1; //
|
||||
UINT8 InvalidInstruction2; //
|
||||
UINT8 InvalidInstruction3; //
|
||||
UINT16 PartitionBoundary; // Upper 16 bit of partition boundary address. Default is 0x0000, which makes the boundary to be 0x00001000
|
||||
UINT16 RezervedZero; // Still unknown, zero in all descriptors I have seen
|
||||
} FLASH_DESCRIPTOR_COMPONENT_SECTION;
|
||||
|
||||
// Region section
|
||||
// All base and limit register are storing upper part of actual UINT32 base and limit
|
||||
// If limit is zero - region is not present
|
||||
typedef struct {
|
||||
UINT16 RezervedZero; // Still unknown, zero in all descriptors I have seen
|
||||
UINT16 FlashBlockEraseSize; // Size of block erased by single BLOCK ERASE command
|
||||
UINT16 BiosBase;
|
||||
UINT16 BiosLimit;
|
||||
UINT16 MeBase;
|
||||
UINT16 MeLimit;
|
||||
UINT16 GbeBase;
|
||||
UINT16 GbeLimit;
|
||||
UINT16 PdrBase;
|
||||
UINT16 PdrLimit;
|
||||
} FLASH_DESCRIPTOR_REGION_SECTION;
|
||||
|
||||
// Flash block erase sizes
|
||||
#define FLASH_BLOCK_ERASE_SIZE_4KB 0x0000
|
||||
#define FLASH_BLOCK_ERASE_SIZE_8KB 0x0001
|
||||
#define FLASH_BLOCK_ERASE_SIZE_64KB 0x000F
|
||||
|
||||
// Master section
|
||||
typedef struct {
|
||||
UINT16 BiosId;
|
||||
UINT8 BiosRead;
|
||||
UINT8 BiosWrite;
|
||||
UINT16 MeId;
|
||||
UINT8 MeRead;
|
||||
UINT8 MeWrite;
|
||||
UINT16 GbeId;
|
||||
UINT8 GbeRead;
|
||||
UINT8 GbeWrite;
|
||||
} FLASH_DESCRIPTOR_MASTER_SECTION;
|
||||
|
||||
//!TODO: Describe PCH and PROC straps sections, as well as ICC and DMI tables
|
||||
|
||||
// Base address of descriptor upper map
|
||||
#define FLASH_DESCRIPTOR_UPPER_MAP_BASE 0x0EFC
|
||||
|
||||
// Descriptor upper map structure
|
||||
typedef struct {
|
||||
UINT8 VsccTableBase; // Base address of VSCC Table for ME, bits [11:4]
|
||||
UINT8 VsccTableSize; // Counted in UINT32s
|
||||
UINT16 ReservedZero; // Still unknown, zero in all descriptors I have seen
|
||||
} FLASH_DESCRIPTOR_UPPER_MAP;
|
||||
|
||||
// VSCC table entry structure
|
||||
typedef struct {
|
||||
UINT8 VendorId; // JEDEC VendorID byte
|
||||
UINT8 DeviceId0; // JEDEC DeviceID first byte
|
||||
UINT8 DeviceId1; // JEDEC DeviceID second byte
|
||||
UINT8 ReservedZero; // Reserved, must be zero
|
||||
UINT32 VsccId; // VSCC ID, normally it is 0x20052005 or 0x20152015
|
||||
} VSCC_TABLE_ENTRY;
|
||||
|
||||
// Base address and size of OEM section
|
||||
#define FLASH_DESCRIPTOR_OEM_SECTION_BASE 0x0F00
|
||||
#define FLASH_DESCRIPTOR_OEM_SECTION_SIZE 0xFF
|
||||
|
||||
// Restore previous packing rules
|
||||
#pragma pack(pop)
|
||||
|
||||
// Calculate address of data structure addressed by descriptor address format
|
||||
// 8 bit base or limit
|
||||
UINT8* calculateAddress8(UINT8* baseAddress, const UINT8 baseOrLimit);
|
||||
// 16 bit base or limit
|
||||
UINT8* calculateAddress16(UINT8* baseAddress, const UINT16 baseOrLimit);
|
||||
//Calculate size of region using its base and limit
|
||||
size_t calculateRegionSize(const UINT16 base, const UINT16 limit);
|
||||
#endif
|
151
ffs.cpp
Normal file
151
ffs.cpp
Normal file
@ -0,0 +1,151 @@
|
||||
/* ffs.cpp
|
||||
|
||||
Copyright (c) 2013, Nikolaj Schlej. All rights reserved.
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
*/
|
||||
|
||||
#include "ffs.h"
|
||||
|
||||
const UINT8 ffsAlignmentTable[] =
|
||||
{0, 4, 7, 9, 10, 12, 15, 16};
|
||||
|
||||
UINT8 calculateChecksum8(UINT8* buffer, UINT32 bufferSize)
|
||||
{
|
||||
UINT8 counter = 0;
|
||||
while(bufferSize--)
|
||||
counter += buffer[bufferSize];
|
||||
return ~counter + 1;
|
||||
}
|
||||
|
||||
UINT16 calculateChecksum16(UINT8* buffer, UINT32 bufferSize)
|
||||
{
|
||||
UINT16 counter = 0;
|
||||
while(bufferSize--)
|
||||
counter += buffer[bufferSize];
|
||||
return ~counter + 1;
|
||||
}
|
||||
|
||||
VOID uint32ToUint24(UINT32 size, UINT8* ffsSize)
|
||||
{
|
||||
ffsSize[2] = (UINT8) ((size) >> 16);
|
||||
ffsSize[1] = (UINT8) ((size) >> 8);
|
||||
ffsSize[0] = (UINT8) ((size) );
|
||||
}
|
||||
|
||||
UINT32 uint24ToUint32(UINT8* ffsSize)
|
||||
{
|
||||
return (ffsSize[2] << 16) +
|
||||
(ffsSize[1] << 8) +
|
||||
ffsSize[0];
|
||||
}
|
||||
|
||||
QString guidToQString(const EFI_GUID guid)
|
||||
{
|
||||
QByteArray baGuid = QByteArray::fromRawData((const char*) guid.Data, sizeof(EFI_GUID));
|
||||
UINT32 i32 = *(UINT32*)baGuid.left(4).constData();
|
||||
UINT16 i16_0 = *(UINT16*)baGuid.mid(4, 2).constData();
|
||||
UINT16 i16_1 = *(UINT16*)baGuid.mid(6, 2).constData();
|
||||
UINT8 i8_0 = *(UINT8*)baGuid.mid(8, 1).constData();
|
||||
UINT8 i8_1 = *(UINT8*)baGuid.mid(9, 1).constData();
|
||||
UINT8 i8_2 = *(UINT8*)baGuid.mid(10, 1).constData();
|
||||
UINT8 i8_3 = *(UINT8*)baGuid.mid(11, 1).constData();
|
||||
UINT8 i8_4 = *(UINT8*)baGuid.mid(12, 1).constData();
|
||||
UINT8 i8_5 = *(UINT8*)baGuid.mid(13, 1).constData();
|
||||
UINT8 i8_6 = *(UINT8*)baGuid.mid(14, 1).constData();
|
||||
UINT8 i8_7 = *(UINT8*)baGuid.mid(15, 1).constData();
|
||||
|
||||
return QString("%1-%2-%3-%4%5-%6%7%8%9%10%11")
|
||||
.arg(i32, 8, 16, QChar('0'))
|
||||
.arg(i16_0, 4, 16, QChar('0'))
|
||||
.arg(i16_1, 4, 16, QChar('0'))
|
||||
.arg(i8_0, 2, 16, QChar('0'))
|
||||
.arg(i8_1, 2, 16, QChar('0'))
|
||||
.arg(i8_2, 2, 16, QChar('0'))
|
||||
.arg(i8_3, 2, 16, QChar('0'))
|
||||
.arg(i8_4, 2, 16, QChar('0'))
|
||||
.arg(i8_5, 2, 16, QChar('0'))
|
||||
.arg(i8_6, 2, 16, QChar('0'))
|
||||
.arg(i8_7, 2, 16, QChar('0')).toUpper();
|
||||
}
|
||||
|
||||
QString fileTypeToQString(const UINT8 type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case EFI_FV_FILETYPE_RAW:
|
||||
return QObject::tr("Raw");
|
||||
case EFI_FV_FILETYPE_FREEFORM:
|
||||
return QObject::tr("Freeform");
|
||||
case EFI_FV_FILETYPE_SECURITY_CORE:
|
||||
return QObject::tr("Security core");
|
||||
case EFI_FV_FILETYPE_PEI_CORE:
|
||||
return QObject::tr("PEI core");
|
||||
case EFI_FV_FILETYPE_DXE_CORE:
|
||||
return QObject::tr("DXE core");
|
||||
case EFI_FV_FILETYPE_PEIM:
|
||||
return QObject::tr("PEI module");
|
||||
case EFI_FV_FILETYPE_DRIVER:
|
||||
return QObject::tr("DXE driver");
|
||||
case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER:
|
||||
return QObject::tr("Combined PEI/DXE");
|
||||
case EFI_FV_FILETYPE_APPLICATION:
|
||||
return QObject::tr("Application");
|
||||
case EFI_FV_FILETYPE_SMM:
|
||||
return QObject::tr("SMM module");
|
||||
case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE:
|
||||
return QObject::tr("Volume image");
|
||||
case EFI_FV_FILETYPE_COMBINED_SMM_DXE:
|
||||
return QObject::tr("Combined SMM/DXE");
|
||||
case EFI_FV_FILETYPE_SMM_CORE:
|
||||
return QObject::tr("SMM core");
|
||||
case EFI_FV_FILETYPE_PAD:
|
||||
return QObject::tr("Pad");
|
||||
default:
|
||||
return QObject::tr("Unknown");
|
||||
};
|
||||
}
|
||||
|
||||
QString sectionTypeToQString(const UINT8 type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case EFI_SECTION_COMPRESSION:
|
||||
return QObject::tr("Compressed");
|
||||
case EFI_SECTION_GUID_DEFINED:
|
||||
return QObject::tr("GUID defined");
|
||||
case EFI_SECTION_DISPOSABLE:
|
||||
return QObject::tr("Disposable");
|
||||
case EFI_SECTION_PE32:
|
||||
return QObject::tr("PE32+ image");
|
||||
case EFI_SECTION_PIC:
|
||||
return QObject::tr("PIC image");
|
||||
case EFI_SECTION_TE:
|
||||
return QObject::tr("TE image");
|
||||
case EFI_SECTION_DXE_DEPEX:
|
||||
return QObject::tr("DXE dependency");
|
||||
case EFI_SECTION_VERSION:
|
||||
return QObject::tr("Version");
|
||||
case EFI_SECTION_USER_INTERFACE:
|
||||
return QObject::tr("User interface");
|
||||
case EFI_SECTION_COMPATIBILITY16:
|
||||
return QObject::tr("16-bit image");
|
||||
case EFI_SECTION_FIRMWARE_VOLUME_IMAGE:
|
||||
return QObject::tr("Volume image");
|
||||
case EFI_SECTION_FREEFORM_SUBTYPE_GUID:
|
||||
return QObject::tr("Freeform subtype GUID");
|
||||
case EFI_SECTION_RAW:
|
||||
return QObject::tr("Raw");
|
||||
case EFI_SECTION_PEI_DEPEX:
|
||||
return QObject::tr("PEI dependency");
|
||||
case EFI_SECTION_SMM_DEPEX:
|
||||
return QObject::tr("SMM dependency");
|
||||
default:
|
||||
return QObject::tr("Unknown");
|
||||
}
|
||||
}
|
415
ffs.h
Normal file
415
ffs.h
Normal file
@ -0,0 +1,415 @@
|
||||
/* ffs.h
|
||||
|
||||
Copyright (c) 2013, Nikolaj Schlej. All rights reserved.
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
*/
|
||||
|
||||
#ifndef __FFS_H__
|
||||
#define __FFS_H__
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QString>
|
||||
#include <QObject>
|
||||
#include "basetypes.h"
|
||||
|
||||
// C++ functions
|
||||
// GUID to QString routine
|
||||
extern QString guidToQString(const EFI_GUID guid);
|
||||
// File type to QString routine
|
||||
extern QString fileTypeToQString(const UINT8 type);
|
||||
// Section type to QString routine
|
||||
extern QString sectionTypeToQString(const UINT8 type);
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
// Make sure we use right packing rules
|
||||
#pragma pack(push,1)
|
||||
|
||||
//*****************************************************************************
|
||||
// EFI Capsule
|
||||
//*****************************************************************************
|
||||
// Capsule header
|
||||
typedef struct {
|
||||
EFI_GUID CapsuleGuid;
|
||||
UINT32 HeaderSize;
|
||||
UINT32 Flags;
|
||||
UINT32 CapsuleImageSize;
|
||||
} EFI_CAPSULE_HEADER;
|
||||
|
||||
// Capsule flags
|
||||
#define EFI_CAPSULE_HEADER_FLAG_SETUP 0x00000001
|
||||
#define EFI_CAPSULE_HEADER_FLAG_PERSIST_ACROSS_RESET 0x00010000
|
||||
#define EFI_CAPSULE_HEADER_FLAG_POPULATE_SYSTEM_TABLE 0x00020000
|
||||
|
||||
// Standard EFI capsule GUID
|
||||
const QByteArray EFI_CAPSULE_GUID("\xBD\x86\x66\x3B\x76\x0D\x30\x40\xB7\x0E\xB5\x51\x9E\x2F\xC5\xA0", 16);
|
||||
|
||||
// AMI Aptio extended capsule header
|
||||
typedef struct {
|
||||
EFI_CAPSULE_HEADER CapsuleHeader;
|
||||
UINT16 RomImageOffset; // offset in bytes from the beginning of the capsule header to the start of
|
||||
// the capsule volume
|
||||
//!TODO: Enable certificate and rom layout reading
|
||||
//UINT16 RomLayoutOffset; // offset to the table of the module descriptors in the capsule's volume
|
||||
// that are included in the signature calculation
|
||||
//FW_CERTIFICATE FWCert;
|
||||
//ROM_AREA RomAreaMap[1];
|
||||
} APTIO_CAPSULE_HEADER;
|
||||
|
||||
// AMI Aptio extended capsule GUID
|
||||
const QByteArray APTIO_CAPSULE_GUID("\x8B\xA6\x3C\x4A\x23\x77\xFB\x48\x80\x3D\x57\x8C\xC1\xFE\xC4\x4D", 16);
|
||||
|
||||
//*****************************************************************************
|
||||
// EFI Firmware Volume
|
||||
//*****************************************************************************
|
||||
// Firmware block map entry
|
||||
// FvBlockMap ends with an entry {0x00000000, 0x00000000}
|
||||
typedef struct {
|
||||
UINT32 NumBlocks;
|
||||
UINT32 BlockLength;
|
||||
} EFI_FV_BLOCK_MAP_ENTRY;
|
||||
|
||||
// Volume header
|
||||
typedef struct {
|
||||
UINT8 ZeroVector[16];
|
||||
EFI_GUID FileSystemGuid;
|
||||
UINT64 FvLength;
|
||||
UINT32 Signature;
|
||||
UINT32 Attributes;
|
||||
UINT16 HeaderLength;
|
||||
UINT16 Checksum;
|
||||
UINT16 ExtHeaderOffset; //Reserved in Revision 1
|
||||
UINT8 Reserved[1];
|
||||
UINT8 Revision;
|
||||
//EFI_FV_BLOCK_MAP_ENTRY FvBlockMap[1];
|
||||
} EFI_FIRMWARE_VOLUME_HEADER;
|
||||
|
||||
// Filesystem GUIDs
|
||||
const QByteArray EFI_FIRMWARE_FILE_SYSTEM_GUID
|
||||
("\xD9\x54\x93\x7A\x68\x04\x4A\x44\x81\xCE\x0B\xF6\x17\xD8\x90\xDF", 16);
|
||||
const QByteArray EFI_FIRMWARE_FILE_SYSTEM2_GUID
|
||||
("\x78\xE5\x8C\x8C\x3D\x8A\x1C\x4F\x99\x35\x89\x61\x85\xC3\x2D\xD3", 16);
|
||||
|
||||
// Firmware volume signature
|
||||
const QByteArray EFI_FV_SIGNATURE("_FVH", 4);
|
||||
#define EFI_FV_SIGNATURE_OFFSET 0x28
|
||||
|
||||
// Firmware volume attributes
|
||||
// Revision 1
|
||||
#define EFI_FVB_READ_DISABLED_CAP 0x00000001
|
||||
#define EFI_FVB_READ_ENABLED_CAP 0x00000002
|
||||
#define EFI_FVB_READ_STATUS 0x00000004
|
||||
#define EFI_FVB_WRITE_DISABLED_CAP 0x00000008
|
||||
#define EFI_FVB_WRITE_ENABLED_CAP 0x00000010
|
||||
#define EFI_FVB_WRITE_STATUS 0x00000020
|
||||
#define EFI_FVB_LOCK_CAP 0x00000040
|
||||
#define EFI_FVB_LOCK_STATUS 0x00000080
|
||||
#define EFI_FVB_STICKY_WRITE 0x00000200
|
||||
#define EFI_FVB_MEMORY_MAPPED 0x00000400
|
||||
#define EFI_FVB_ERASE_POLARITY 0x00000800
|
||||
#define EFI_FVB_ALIGNMENT_CAP 0x00008000
|
||||
#define EFI_FVB_ALIGNMENT_2 0x00010000
|
||||
#define EFI_FVB_ALIGNMENT_4 0x00020000
|
||||
#define EFI_FVB_ALIGNMENT_8 0x00040000
|
||||
#define EFI_FVB_ALIGNMENT_16 0x00080000
|
||||
#define EFI_FVB_ALIGNMENT_32 0x00100000
|
||||
#define EFI_FVB_ALIGNMENT_64 0x00200000
|
||||
#define EFI_FVB_ALIGNMENT_128 0x00400000
|
||||
#define EFI_FVB_ALIGNMENT_256 0x00800000
|
||||
#define EFI_FVB_ALIGNMENT_512 0x01000000
|
||||
#define EFI_FVB_ALIGNMENT_1K 0x02000000
|
||||
#define EFI_FVB_ALIGNMENT_2K 0x04000000
|
||||
#define EFI_FVB_ALIGNMENT_4K 0x08000000
|
||||
#define EFI_FVB_ALIGNMENT_8K 0x10000000
|
||||
#define EFI_FVB_ALIGNMENT_16K 0x20000000
|
||||
#define EFI_FVB_ALIGNMENT_32K 0x40000000
|
||||
#define EFI_FVB_ALIGNMENT_64K 0x80000000
|
||||
// Revision 2
|
||||
#define EFI_FVB2_READ_DISABLED_CAP 0x00000001
|
||||
#define EFI_FVB2_READ_ENABLED_CAP 0x00000002
|
||||
#define EFI_FVB2_READ_STATUS 0x00000004
|
||||
#define EFI_FVB2_WRITE_DISABLED_CAP 0x00000008
|
||||
#define EFI_FVB2_WRITE_ENABLED_CAP 0x00000010
|
||||
#define EFI_FVB2_WRITE_STATUS 0x00000020
|
||||
#define EFI_FVB2_LOCK_CAP 0x00000040
|
||||
#define EFI_FVB2_LOCK_STATUS 0x00000080
|
||||
#define EFI_FVB2_STICKY_WRITE 0x00000200
|
||||
#define EFI_FVB2_MEMORY_MAPPED 0x00000400
|
||||
#define EFI_FVB2_ERASE_POLARITY 0x00000800
|
||||
#define EFI_FVB2_READ_LOCK_CAP 0x00001000
|
||||
#define EFI_FVB2_READ_LOCK_STATUS 0x00002000
|
||||
#define EFI_FVB2_WRITE_LOCK_CAP 0x00004000
|
||||
#define EFI_FVB2_WRITE_LOCK_STATUS 0x00008000
|
||||
#define EFI_FVB2_ALIGNMENT 0x001F0000
|
||||
#define EFI_FVB2_ALIGNMENT_1 0x00000000
|
||||
#define EFI_FVB2_ALIGNMENT_2 0x00010000
|
||||
#define EFI_FVB2_ALIGNMENT_4 0x00020000
|
||||
#define EFI_FVB2_ALIGNMENT_8 0x00030000
|
||||
#define EFI_FVB2_ALIGNMENT_16 0x00040000
|
||||
#define EFI_FVB2_ALIGNMENT_32 0x00050000
|
||||
#define EFI_FVB2_ALIGNMENT_64 0x00060000
|
||||
#define EFI_FVB2_ALIGNMENT_128 0x00070000
|
||||
#define EFI_FVB2_ALIGNMENT_256 0x00080000
|
||||
#define EFI_FVB2_ALIGNMENT_512 0x00090000
|
||||
#define EFI_FVB2_ALIGNMENT_1K 0x000A0000
|
||||
#define EFI_FVB2_ALIGNMENT_2K 0x000B0000
|
||||
#define EFI_FVB2_ALIGNMENT_4K 0x000C0000
|
||||
#define EFI_FVB2_ALIGNMENT_8K 0x000D0000
|
||||
#define EFI_FVB2_ALIGNMENT_16K 0x000E0000
|
||||
#define EFI_FVB2_ALIGNMENT_32K 0x000F0000
|
||||
#define EFI_FVB2_ALIGNMENT_64K 0x00100000
|
||||
#define EFI_FVB2_ALIGNMENT_128K 0x00110000
|
||||
#define EFI_FVB2_ALIGNMENT_256K 0x00120000
|
||||
#define EFI_FVB2_ALIGNMENT_512K 0x00130000
|
||||
#define EFI_FVB2_ALIGNMENT_1M 0x00140000
|
||||
#define EFI_FVB2_ALIGNMENT_2M 0x00150000
|
||||
#define EFI_FVB2_ALIGNMENT_4M 0x00160000
|
||||
#define EFI_FVB2_ALIGNMENT_8M 0x00170000
|
||||
#define EFI_FVB2_ALIGNMENT_16M 0x00180000
|
||||
#define EFI_FVB2_ALIGNMENT_32M 0x00190000
|
||||
#define EFI_FVB2_ALIGNMENT_64M 0x001A0000
|
||||
#define EFI_FVB2_ALIGNMENT_128M 0x001B0000
|
||||
#define EFI_FVB2_ALIGNMENT_256M 0x001C0000
|
||||
#define EFI_FVB2_ALIGNMENT_512M 0x001D0000
|
||||
#define EFI_FVB2_ALIGNMENT_1G 0x001E0000
|
||||
#define EFI_FVB2_ALIGNMENT_2G 0x001F0000
|
||||
#define EFI_FVB2_WEAK_ALIGNMENT 0x80000000
|
||||
|
||||
// Extended firmware volume header
|
||||
typedef struct {
|
||||
EFI_GUID FvName;
|
||||
UINT32 ExtHeaderSize;
|
||||
} EFI_FIRMWARE_VOLUME_EXT_HEADER;
|
||||
|
||||
// Extended header entry
|
||||
// The extended header entries follow each other and are
|
||||
// terminated by ExtHeaderType EFI_FV_EXT_TYPE_END
|
||||
#define EFI_FV_EXT_TYPE_END 0x00
|
||||
typedef struct {
|
||||
UINT16 ExtEntrySize;
|
||||
UINT16 ExtEntryType;
|
||||
} EFI_FIRMWARE_VOLUME_EXT_ENTRY;
|
||||
|
||||
// GUID that maps OEM file types to GUIDs
|
||||
#define EFI_FV_EXT_TYPE_OEM_TYPE 0x01
|
||||
typedef struct {
|
||||
EFI_FIRMWARE_VOLUME_EXT_ENTRY Header;
|
||||
UINT32 TypeMask;
|
||||
//EFI_GUID Types[1];
|
||||
} EFI_FIRMWARE_VOLUME_EXT_HEADER_OEM_TYPE;
|
||||
|
||||
#define EFI_FV_EXT_TYPE_GUID_TYPE 0x02
|
||||
typedef struct {
|
||||
EFI_FIRMWARE_VOLUME_EXT_ENTRY Header;
|
||||
EFI_GUID FormatType;
|
||||
//UINT8 Data[];
|
||||
} EFI_FIRMWARE_VOLUME_EXT_ENTRY_GUID_TYPE;
|
||||
|
||||
|
||||
// Volume header 16bit checksum calculation routine
|
||||
extern UINT16 calculateChecksum16(UINT8* buffer, UINT32 bufferSize);
|
||||
|
||||
//*****************************************************************************
|
||||
// EFI FFS File
|
||||
//*****************************************************************************
|
||||
// Integrity check
|
||||
typedef union {
|
||||
struct {
|
||||
UINT8 Header;
|
||||
UINT8 File;
|
||||
} Checksum;
|
||||
UINT16 TailReference; // Revision 1
|
||||
UINT16 Checksum16; // Revision 2
|
||||
} EFI_FFS_INTEGRITY_CHECK;
|
||||
// File header
|
||||
typedef struct {
|
||||
EFI_GUID Name;
|
||||
EFI_FFS_INTEGRITY_CHECK IntegrityCheck;
|
||||
UINT8 Type;
|
||||
UINT8 Attributes;
|
||||
UINT8 Size[3];
|
||||
UINT8 State;
|
||||
} EFI_FFS_FILE_HEADER;
|
||||
|
||||
// Large file header
|
||||
//typedef struct {
|
||||
// EFI_GUID Name;
|
||||
// EFI_FFS_INTEGRITY_CHECK IntegrityCheck;
|
||||
// UINT8 Type;
|
||||
// UINT8 Attributes;
|
||||
// UINT8 Size[3];
|
||||
// UINT8 State;
|
||||
// UINT12 ExtendedSize;
|
||||
//} EFI_FFS_FILE_HEADER2;
|
||||
|
||||
// Standart data checksum, used if FFS_ATTRIB_CHECKSUM is clear
|
||||
#define FFS_FIXED_CHECKSUM 0x5A
|
||||
#define FFS_FIXED_CHECKSUM2 0xAA
|
||||
|
||||
// File types
|
||||
#define EFI_FV_FILETYPE_ALL 0x00
|
||||
#define EFI_FV_FILETYPE_RAW 0x01
|
||||
#define EFI_FV_FILETYPE_FREEFORM 0x02
|
||||
#define EFI_FV_FILETYPE_SECURITY_CORE 0x03
|
||||
#define EFI_FV_FILETYPE_PEI_CORE 0x04
|
||||
#define EFI_FV_FILETYPE_DXE_CORE 0x05
|
||||
#define EFI_FV_FILETYPE_PEIM 0x06
|
||||
#define EFI_FV_FILETYPE_DRIVER 0x07
|
||||
#define EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER 0x08
|
||||
#define EFI_FV_FILETYPE_APPLICATION 0x09
|
||||
#define EFI_FV_FILETYPE_SMM 0x0A
|
||||
#define EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE 0x0B
|
||||
#define EFI_FV_FILETYPE_COMBINED_SMM_DXE 0x0C
|
||||
#define EFI_FV_FILETYPE_SMM_CORE 0x0D
|
||||
#define EFI_FV_FILETYPE_OEM_MIN 0xC0
|
||||
#define EFI_FV_FILETYPE_OEM_MAX 0xDF
|
||||
#define EFI_FV_FILETYPE_DEBUG_MIN 0xE0
|
||||
#define EFI_FV_FILETYPE_DEBUG_MAX 0xEF
|
||||
#define EFI_FV_FILETYPE_PAD 0xF0
|
||||
#define EFI_FV_FILETYPE_FFS_MIN 0xF0
|
||||
#define EFI_FV_FILETYPE_FFS_MAX 0xFF
|
||||
|
||||
// File attributes
|
||||
// Revision 1
|
||||
#define FFS_ATTRIB_TAIL_PRESENT 0x01
|
||||
#define FFS_ATTRIB_RECOVERY 0x02
|
||||
//#define FFS_ATTRIB_HEADER_EXTENSION 0x04 //Must be set to zero in Revision 1
|
||||
#define FFS_ATTRIB_DATA_ALIGNMENT 0x38
|
||||
#define FFS_ATTRIB_CHECKSUM 0x40
|
||||
// Revision 2
|
||||
#define FFS_ATTRIB_LARGE_FILE 0x01
|
||||
#define FFS_ATTRIB_FIXED 0x04
|
||||
|
||||
// FFS alignment table
|
||||
extern const UINT8 ffsAlignmentTable[];
|
||||
|
||||
// File states
|
||||
#define EFI_FILE_HEADER_CONSTRUCTION 0x01
|
||||
#define EFI_FILE_HEADER_VALID 0x02
|
||||
#define EFI_FILE_DATA_VALID 0x04
|
||||
#define EFI_FILE_MARKED_FOR_UPDATE 0x08
|
||||
#define EFI_FILE_DELETED 0x10
|
||||
#define EFI_FILE_HEADER_INVALID 0x20
|
||||
|
||||
// Volume top file
|
||||
const QByteArray EFI_FFS_VOLUME_TOP_FILE_GUID
|
||||
("\x2E\x06\xA0\x1B\x79\xC7\x82\x45\x85\x66\x33\x6A\xE8\xF7\x8F\x09", 16);
|
||||
|
||||
// FFS size convertion routines
|
||||
extern VOID uint32ToUint24(UINT32 size, UINT8* ffsSize);
|
||||
extern UINT32 uint24ToUint32(UINT8* ffsSize);
|
||||
// FFS file 8bit checksum calculation routine
|
||||
extern UINT8 calculateChecksum8(UINT8* buffer, UINT32 bufferSize);
|
||||
|
||||
//*****************************************************************************
|
||||
// EFI FFS File Section
|
||||
//*****************************************************************************
|
||||
// Common section header
|
||||
typedef struct {
|
||||
UINT8 Size[3];
|
||||
UINT8 Type;
|
||||
} EFI_COMMON_SECTION_HEADER;
|
||||
|
||||
// Large file common section header
|
||||
//typedef struct {
|
||||
// UINT8 Size[3]; //Must be 0xFFFFFF for this header to be used
|
||||
// UINT8 Type;
|
||||
// UINT32 ExtendedSize;
|
||||
//} EFI_COMMON_SECTION_HEADER2;
|
||||
|
||||
// File section types
|
||||
#define EFI_SECTION_ALL 0x00 // Imposible attribute for file in the FS
|
||||
|
||||
// Encapsulation section types
|
||||
#define EFI_SECTION_COMPRESSION 0x01
|
||||
#define EFI_SECTION_GUID_DEFINED 0x02
|
||||
#define EFI_SECTION_DISPOSABLE 0x03
|
||||
|
||||
// Leaf section types
|
||||
#define EFI_SECTION_PE32 0x10
|
||||
#define EFI_SECTION_PIC 0x11
|
||||
#define EFI_SECTION_TE 0x12
|
||||
#define EFI_SECTION_DXE_DEPEX 0x13
|
||||
#define EFI_SECTION_VERSION 0x14
|
||||
#define EFI_SECTION_USER_INTERFACE 0x15
|
||||
#define EFI_SECTION_COMPATIBILITY16 0x16
|
||||
#define EFI_SECTION_FIRMWARE_VOLUME_IMAGE 0x17
|
||||
#define EFI_SECTION_FREEFORM_SUBTYPE_GUID 0x18
|
||||
#define EFI_SECTION_RAW 0x19
|
||||
#define EFI_SECTION_PEI_DEPEX 0x1B
|
||||
#define EFI_SECTION_SMM_DEPEX 0x1C
|
||||
|
||||
// Compression section
|
||||
typedef struct {
|
||||
UINT8 Size[3];
|
||||
UINT8 Type;
|
||||
UINT32 UncompressedLength;
|
||||
UINT8 CompressionType;
|
||||
} EFI_COMPRESSION_SECTION;
|
||||
|
||||
// Compression types
|
||||
#define EFI_NOT_COMPRESSED 0x00
|
||||
#define EFI_STANDARD_COMPRESSION 0x01 //Tiano for Revision 2, EFI for Revision 1
|
||||
#define EFI_CUSTOMIZED_COMPRESSION 0x02 //LZMA for Revision 2 Tiano for Revision 1
|
||||
|
||||
//GUID defined section
|
||||
typedef struct {
|
||||
UINT8 Size[3];
|
||||
UINT8 Type;
|
||||
EFI_GUID SectionDefinitionGuid;
|
||||
UINT16 DataOffset;
|
||||
UINT16 Attributes;
|
||||
} EFI_GUID_DEFINED_SECTION;
|
||||
|
||||
// Attributes for GUID defined section
|
||||
#define EFI_GUIDED_SECTION_PROCESSING_REQUIRED 0x01
|
||||
#define EFI_GUIDED_SECTION_AUTH_STATUS_VALID 0x02
|
||||
|
||||
// Version section
|
||||
typedef struct {
|
||||
UINT8 Size[3];
|
||||
UINT8 Type;
|
||||
UINT16 BuildNumber;
|
||||
//CHAR16 VersionString[1];
|
||||
} EFI_VERSION_SECTION;
|
||||
|
||||
// Freeform subtype GUID section
|
||||
typedef struct {
|
||||
UINT8 Size[3];
|
||||
UINT8 Type;
|
||||
EFI_GUID SubTypeGuid;
|
||||
} EFI_FREEFORM_SUBTYPE_GUID_SECTION;
|
||||
|
||||
// User interface section
|
||||
typedef struct {
|
||||
UINT8 Size[3];
|
||||
UINT8 Type;
|
||||
//CHAR16 FileNameString[1];
|
||||
} EFI_USER_INTERFACE_SECTION;
|
||||
|
||||
// Other sections
|
||||
typedef EFI_COMMON_SECTION_HEADER EFI_DISPOSABLE_SECTION;
|
||||
typedef EFI_COMMON_SECTION_HEADER EFI_RAW_SECTION;
|
||||
typedef EFI_COMMON_SECTION_HEADER EFI_DXE_DEPEX_SECTION;
|
||||
typedef EFI_COMMON_SECTION_HEADER EFI_PEI_DEPEX_SECTION;
|
||||
typedef EFI_COMMON_SECTION_HEADER EFI_SMM_DEPEX_SECTION;
|
||||
typedef EFI_COMMON_SECTION_HEADER EFI_PE32_SECTION;
|
||||
typedef EFI_COMMON_SECTION_HEADER EFI_PIC_SECTION;
|
||||
typedef EFI_COMMON_SECTION_HEADER EFI_TE_SECTION;
|
||||
typedef EFI_COMMON_SECTION_HEADER EFI_COMPATIBILITY16_SECTION;
|
||||
typedef EFI_COMMON_SECTION_HEADER EFI_FIRMWARE_VOLUME_IMAGE_SECTION;
|
||||
|
||||
// Restore previous packing rules
|
||||
#pragma pack(pop)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
28
main.cpp
Normal file
28
main.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
/* main.cpp
|
||||
|
||||
Copyright (c) 2013, Nikolaj Schlej. All rights reserved.
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
*/
|
||||
|
||||
#include <QApplication>
|
||||
#include <QString>
|
||||
#include "uefitool.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication a(argc, argv);
|
||||
UEFITool w;
|
||||
|
||||
if (a.arguments().length() > 1)
|
||||
w.openImageFile(a.arguments().at(1));
|
||||
w.show();
|
||||
|
||||
return a.exec();
|
||||
}
|
520
parse.cpp
Normal file
520
parse.cpp
Normal file
@ -0,0 +1,520 @@
|
||||
/* parse.cpp
|
||||
|
||||
Copyright (c) 2013, Nikolaj Schlej. All rights reserved.
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
*/
|
||||
|
||||
#include "parse.h"
|
||||
|
||||
// Implementation of GNU memmem function using Boyer-Moore-Horspool algorithm
|
||||
UINT8* find_pattern(UINT8* string, UINT32 slen, CONST UINT8* pattern, UINT32 plen)
|
||||
{
|
||||
UINT32 scan = 0;
|
||||
UINT32 bad_char_skip[256];
|
||||
UINT32 last;
|
||||
|
||||
if (plen == 0 || !string || !pattern)
|
||||
return NULL;
|
||||
|
||||
for (scan = 0; scan <= 255; scan++)
|
||||
bad_char_skip[scan] = plen;
|
||||
|
||||
last = plen - 1;
|
||||
|
||||
for (scan = 0; scan < last; scan++)
|
||||
bad_char_skip[pattern[scan]] = last - scan;
|
||||
|
||||
while (slen >= plen)
|
||||
{
|
||||
for (scan = last; string[scan] == pattern[scan]; scan--)
|
||||
if (scan == 0)
|
||||
return string;
|
||||
|
||||
slen -= bad_char_skip[string[last]];
|
||||
string += bad_char_skip[string[last]];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UINT8 write_to_file(UINT8* buffer, CONST size_t size, const char* name, const char* extension)
|
||||
{
|
||||
/*char str[_MAX_PATH]; // Buffer for file name construction
|
||||
FILE* file;
|
||||
|
||||
sprintf(str, "%s.%s", name, extension);
|
||||
file = fopen((const char*) str, "wb");
|
||||
if (!file) {
|
||||
printf("Can't create %s file\n", str);
|
||||
return ERR_FILE_OPEN;
|
||||
}
|
||||
if (fwrite(buffer, sizeof(UINT8), size, file) != size) {
|
||||
printf("Can't write %s file\n", str);
|
||||
return ERR_FILE_WRITE;
|
||||
}
|
||||
fclose(file);*/
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
|
||||
UINT8* parse_region(UINT8* buffer, size_t size, CONST BOOLEAN two_flash_chips, const char* region_name, CONST UINT16 region_base, CONST UINT16 region_limit)
|
||||
{
|
||||
UINT8 result = ERR_SUCCESS;
|
||||
UINT8* region = NULL;
|
||||
size_t region_size = calculate_region_size(region_base, region_limit);
|
||||
|
||||
if (!buffer || !size || !region_name || !region_size)
|
||||
return NULL;
|
||||
|
||||
// Check region base to be in buffer
|
||||
if (region_base >= size)
|
||||
{
|
||||
printf("Warning: %s region stored in descriptor is not found\n", region_name);
|
||||
if (two_flash_chips)
|
||||
printf("Two flash chips installed, so it could be in another flash chip\n"
|
||||
"Make a dump from another flash chip and open it to view information about %s region\n", region_name);
|
||||
else
|
||||
printf("Error: one flash chip installed, so it is an error caused by damaged or incomplete dump\n");
|
||||
printf("Warning: absence of %s region assumed\n", region_name);
|
||||
return NULL;
|
||||
}
|
||||
// Check region to be fully present in buffer
|
||||
else if (region_base + region_size > size)
|
||||
{
|
||||
printf("Warning: %s region stored in descriptor overlaps the end of opened file\n", region_name);
|
||||
if (two_flash_chips)
|
||||
printf("Two flash chips installed, so it could be in another flash chip\n"
|
||||
"Make a dump from another flash chip and open it to view information about %s region\n", region_name);
|
||||
else
|
||||
printf("Error: One flash chip installed, so it is an error caused by damaged or incomplete dump\n");
|
||||
printf("Warning: absence of %s region assumed\n", region_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Calculate region address
|
||||
region = calculate_address_16(buffer, region_base);
|
||||
|
||||
// Display information about region
|
||||
printf("%s region found, size: %d (0x%08X)\n", region_name, region_size, region_size);
|
||||
|
||||
// Write all regions that has non-zero size to files
|
||||
result = write_to_file(region, region_size, region_name, "region");
|
||||
if (result){
|
||||
printf("Error: Can't write %s region to file\n", region_name);
|
||||
return NULL;
|
||||
}
|
||||
printf("%s region written to file\n", region_name);
|
||||
|
||||
return region;
|
||||
}
|
||||
|
||||
UINT8* find_next_volume(UINT8* buffer, size_t buffer_size)
|
||||
{
|
||||
UINT8* pointer;
|
||||
if (!buffer || !buffer_size)
|
||||
return NULL;
|
||||
|
||||
pointer = find_pattern(buffer, buffer_size, FV_SIGNATURE_STR, FV_SIGNATURE_LENGTH);
|
||||
if (pointer && pointer - FV_SIGNATURE_OFFSET >= buffer)
|
||||
return pointer - FV_SIGNATURE_OFFSET;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UINT8 calculate_checksum_8(UINT8* buffer, size_t buffer_size)
|
||||
{
|
||||
UINT8 counter = 0;
|
||||
while(buffer_size--)
|
||||
counter += buffer[buffer_size];
|
||||
return ~counter + 1;
|
||||
}
|
||||
|
||||
UINT16 calculate_checksum_16(UINT8* buffer, size_t buffer_size)
|
||||
{
|
||||
UINT16 counter = 0;
|
||||
while(buffer_size--)
|
||||
counter += buffer[buffer_size];
|
||||
return ~counter + 1;
|
||||
}
|
||||
|
||||
// Format GUID to standard readable form
|
||||
// Assumes str to have at least 37 bytes free
|
||||
UINT8 format_guid(EFI_GUID* guid, char* str)
|
||||
{
|
||||
UINT8* guid1 = (UINT8*) guid;
|
||||
UINT8* guid2 = guid1 + 4;
|
||||
UINT8* guid3 = guid1 + 6;
|
||||
UINT32* data1 = (UINT32*) guid1;
|
||||
UINT16* data2 = (UINT16*) guid2;
|
||||
UINT16* data3 = (UINT16*) guid3;
|
||||
UINT8* data41 = guid1 + 8;
|
||||
UINT8* data42 = guid1 + 9;
|
||||
UINT8* data51 = guid1 + 10;
|
||||
UINT8* data52 = guid1 + 11;
|
||||
UINT8* data53 = guid1 + 12;
|
||||
UINT8* data54 = guid1 + 13;
|
||||
UINT8* data55 = guid1 + 14;
|
||||
UINT8* data56 = guid1 + 15;
|
||||
|
||||
sprintf(str, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", *data1, *data2, *data3, *data41, *data42,
|
||||
*data51, *data52, *data53, *data54, *data55, *data56);
|
||||
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
|
||||
VOID size_to_filesize(size_t size, UINT8* module_size)
|
||||
{
|
||||
module_size[2] = (UINT8) ((size) >> 16);
|
||||
module_size[1] = (UINT8) ((size) >> 8);
|
||||
module_size[0] = (UINT8) ((size) );
|
||||
}
|
||||
|
||||
size_t filesize_to_size(UINT8* module_size)
|
||||
{
|
||||
return (module_size[2] << 16) +
|
||||
(module_size[1] << 8) +
|
||||
module_size[0];
|
||||
}
|
||||
|
||||
UINT8 parse_volume(UINT8* buffer, size_t buffer_size, const char* prefix)
|
||||
{
|
||||
EFI_FIRMWARE_VOLUME_HEADER* volume_header;
|
||||
UINT8* current_file;
|
||||
char str[_MAX_PATH];
|
||||
char guid[37]; // FD44820B-F1AB-41C0-AE4E-0C55556EB9BD for example
|
||||
UINT8 empty_byte;
|
||||
UINT8 result;
|
||||
size_t header_size;
|
||||
size_t file_size;
|
||||
size_t files_counter = 0;
|
||||
|
||||
volume_header = (EFI_FIRMWARE_VOLUME_HEADER*) buffer;
|
||||
if (volume_header->Signature != FV_SIGNATURE_INT)
|
||||
return ERR_INVALID_VOLUME;
|
||||
|
||||
//!TODO: Check zero vector for code, so it could be a boot volume
|
||||
|
||||
// Check filesystem GUID to be known
|
||||
// Check for FFS1
|
||||
if (find_pattern((UINT8*)&volume_header->FileSystemGuid, sizeof(EFI_GUID), EFI_FIRMWARE_FILE_SYSTEM_GUID, sizeof(EFI_GUID)) == (UINT8*)&volume_header->FileSystemGuid) {
|
||||
printf("File system: PI FFS v1\n");
|
||||
// Check for FFS2
|
||||
} else if (find_pattern((UINT8*)&volume_header->FileSystemGuid, sizeof(EFI_GUID), EFI_FIRMWARE_FILE_SYSTEM2_GUID, sizeof(EFI_GUID)) == (UINT8*)&volume_header->FileSystemGuid) {
|
||||
printf("File system: PI FFS v2\n");
|
||||
// Unknown FFS
|
||||
} else {
|
||||
printf("File system: unknown\nWarning: volume can't be parsed\n");
|
||||
return ERR_UNKNOWN_FFS;
|
||||
}
|
||||
|
||||
// Check attributes
|
||||
// Determine erase polarity
|
||||
if (volume_header->Attributes & EFI_FVB_ERASE_POLARITY)
|
||||
empty_byte = 0xFF;
|
||||
else
|
||||
empty_byte = 0x00;
|
||||
printf("Empty byte: 0x%02X\n", empty_byte);
|
||||
|
||||
// Check header checksum by recalculating it
|
||||
if (!calculate_checksum_16(buffer, volume_header->HeaderLength)) {
|
||||
printf("Warning: volume header checksum is invalid\nVolume can be inacessible for UEFI routines\n");
|
||||
}
|
||||
|
||||
// Check for presence of extended header, only if header revision is not 1
|
||||
if (volume_header->Revision > 1 && volume_header->ExtHeaderOffset) {
|
||||
EFI_FIRMWARE_VOLUME_EXT_HEADER* extended_header;
|
||||
extended_header = (EFI_FIRMWARE_VOLUME_EXT_HEADER*) (buffer + volume_header->ExtHeaderOffset);
|
||||
result = format_guid(&extended_header->FvName, guid);
|
||||
if (result)
|
||||
return result;
|
||||
printf("Extended header: present\n"
|
||||
"Volume GUID: %s", guid);
|
||||
header_size = volume_header->ExtHeaderOffset + extended_header->ExtHeaderSize;
|
||||
} else {
|
||||
printf("Extended header: none\n");
|
||||
header_size = volume_header->HeaderLength;
|
||||
}
|
||||
|
||||
//!TODO: Check block map to make enough space for the whole volume
|
||||
|
||||
// Find and parse all files in current volume
|
||||
for(current_file = buffer + header_size; current_file && current_file < buffer + volume_header->FvLength - header_size;) {
|
||||
EFI_FFS_FILE_HEADER* file_header = (EFI_FFS_FILE_HEADER*) current_file;
|
||||
UINT8* byte;
|
||||
size_t empty_bytes_counter = 0;
|
||||
// Check if no more files left
|
||||
for (byte = current_file; *byte == empty_byte; byte++) {
|
||||
empty_bytes_counter++;
|
||||
if(empty_bytes_counter >= sizeof(EFI_FFS_FILE_HEADER))
|
||||
{
|
||||
printf("No more files left in current volume\n");
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
result = format_guid(&file_header->Name, guid);
|
||||
if (result)
|
||||
return result;
|
||||
printf("FFS file %s found\n", guid);
|
||||
|
||||
// Constructing file name
|
||||
sprintf(str, "%s.%d.%s", prefix, files_counter, guid);
|
||||
|
||||
// Getting file size
|
||||
file_size = filesize_to_size(file_header->Size);
|
||||
|
||||
// Store current volume to file
|
||||
result = write_to_file(current_file, file_size,
|
||||
str, "file");
|
||||
if (result){
|
||||
printf("Error: Can't write FFS file to file\n");
|
||||
return result;
|
||||
}
|
||||
printf("FFS file %s stored to file\n", guid);
|
||||
|
||||
//!TODO: Parse current file
|
||||
|
||||
// Parsed
|
||||
printf("FFS file %s parsed\n", guid);
|
||||
current_file += ALIGN_8(file_size);
|
||||
files_counter++;
|
||||
}
|
||||
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
|
||||
UINT8 parse_bios_space(UINT8* buffer, size_t buffer_size)
|
||||
{
|
||||
UINT8* current_pointer = NULL;
|
||||
UINT8* previous_pointer = NULL;
|
||||
size_t previous_volume_size = 0;
|
||||
EFI_FIRMWARE_VOLUME_HEADER* volume_header = NULL;
|
||||
UINT32 files_counter = 0;
|
||||
size_t rest_size = 0;
|
||||
UINT8 result = 0;
|
||||
char str[_MAX_PATH];
|
||||
|
||||
// Search for all firmware volume headers
|
||||
for (current_pointer = buffer, previous_pointer = NULL; current_pointer && current_pointer - buffer <= buffer_size;) {
|
||||
rest_size = buffer_size - (current_pointer - buffer);
|
||||
// Search for next firmware volume
|
||||
//!TODO: add checks for incomplete file
|
||||
previous_pointer = current_pointer;
|
||||
current_pointer = find_next_volume(current_pointer, rest_size);
|
||||
if (current_pointer) {
|
||||
// Check for padding between previous and current volumes
|
||||
if (previous_pointer + previous_volume_size < current_pointer) {
|
||||
sprintf(str, "%d", files_counter);
|
||||
result = write_to_file(previous_pointer + previous_volume_size,
|
||||
current_pointer - previous_pointer - previous_volume_size,
|
||||
str, "padding");
|
||||
if (result){
|
||||
printf("Error: Can't write padding to file\n");
|
||||
return result;
|
||||
}
|
||||
printf("Padding between firmware volumes stored to file\n\n");
|
||||
files_counter++;
|
||||
}
|
||||
|
||||
volume_header = (EFI_FIRMWARE_VOLUME_HEADER*) current_pointer;
|
||||
printf("Firmware volume found\n");
|
||||
|
||||
// Check if volume overlaps the end if buffer
|
||||
if (current_pointer + volume_header->FvLength > buffer + buffer_size) {
|
||||
printf("Error: Volume overlaps the end of input buffer.\n");
|
||||
return ERR_INVALID_VOLUME;
|
||||
}
|
||||
|
||||
// Constructing volume name
|
||||
sprintf(str, "%d", files_counter);
|
||||
|
||||
// Store current volume to file
|
||||
result = write_to_file(current_pointer, volume_header->FvLength,
|
||||
str, "volume");
|
||||
if (result){
|
||||
printf("Error: Can't write volume to file\n");
|
||||
return result;
|
||||
}
|
||||
printf("Volume stored to file\n");
|
||||
|
||||
// Parse volume
|
||||
result = parse_volume(current_pointer, volume_header->FvLength, str);
|
||||
if (result)
|
||||
return result;
|
||||
printf("Firmware volume parsed\n\n");
|
||||
|
||||
// Move to next volume
|
||||
current_pointer += volume_header->FvLength;
|
||||
files_counter++;
|
||||
}
|
||||
else {// Previous_pointer was the last one (or there was none at all)
|
||||
// Check for padding between previous volume and end of buffer
|
||||
if (previous_pointer + previous_volume_size < buffer + buffer_size) {
|
||||
char str[256];
|
||||
sprintf(str, "%d", files_counter);
|
||||
result = write_to_file(previous_pointer + previous_volume_size,
|
||||
buffer_size + buffer - previous_pointer,
|
||||
str, "padding");
|
||||
if (result){
|
||||
printf("Error: Can't write padding to file\n");
|
||||
return result;
|
||||
}
|
||||
printf("Padding between last firmware volume and end of buffer stored to file\n\n");
|
||||
files_counter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
|
||||
UINT8 parse_buffer(UINT8* buffer, size_t buffer_size)
|
||||
{
|
||||
UINT8* original_buffer = buffer;
|
||||
size_t original_size = buffer_size;
|
||||
size_t capsule_header_size = 0;
|
||||
size_t flash_image_size = 0;
|
||||
FLASH_DESCRIPTOR_HEADER* descriptor_header = NULL;
|
||||
UINT8 result = ERR_SUCCESS;
|
||||
|
||||
// Check buffer to be valid
|
||||
if (!buffer || !buffer_size)
|
||||
return ERR_INVALID_PARAMETER;
|
||||
|
||||
// Check buffer for being normal EFI capsule header
|
||||
if (find_pattern(buffer, sizeof(EFI_GUID), EFI_CAPSULE_GUID, sizeof(EFI_GUID)) == buffer) {
|
||||
EFI_CAPSULE_HEADER* capsule_header = (EFI_CAPSULE_HEADER*) buffer;
|
||||
printf("EFI Capsule header found\n"
|
||||
"Header size: %d (0x%08X)\n"
|
||||
"Header flags: %08X\n"
|
||||
"Image size: %d (0x%08X)\n\n",
|
||||
capsule_header->HeaderSize,
|
||||
capsule_header->HeaderSize,
|
||||
capsule_header->Flags,
|
||||
capsule_header->CapsuleImageSize,
|
||||
capsule_header->CapsuleImageSize);
|
||||
capsule_header_size = capsule_header->HeaderSize;
|
||||
}
|
||||
|
||||
// Check buffer for being extended Aptio capsule header
|
||||
else if (find_pattern(buffer, sizeof(EFI_GUID), APTIO_CAPSULE_GUID, sizeof(EFI_GUID)) == buffer) {
|
||||
APTIO_CAPSULE_HEADER* aptio_capsule_header = (APTIO_CAPSULE_HEADER*) buffer;
|
||||
printf("AMI Aptio extended capsule header found\n"
|
||||
"Header size: %d (0x%08X)\n"
|
||||
"Header flags: %08X\n"
|
||||
"Image size: %d (0x%08X)\n\n",
|
||||
aptio_capsule_header->RomImageOffset,
|
||||
aptio_capsule_header->RomImageOffset,
|
||||
aptio_capsule_header->CapsuleHeader.Flags,
|
||||
aptio_capsule_header->CapsuleHeader.CapsuleImageSize - aptio_capsule_header->RomImageOffset,
|
||||
aptio_capsule_header->CapsuleHeader.CapsuleImageSize - aptio_capsule_header->RomImageOffset);
|
||||
//!TODO: add more information about extended headed here
|
||||
capsule_header_size = aptio_capsule_header->RomImageOffset;
|
||||
}
|
||||
|
||||
// Skip capsule header
|
||||
buffer += capsule_header_size;
|
||||
flash_image_size = buffer_size - capsule_header_size;
|
||||
|
||||
// Consider buffer to be normal flash image without any headers now
|
||||
|
||||
// Check buffer for being Intel flash descriptor
|
||||
descriptor_header = (FLASH_DESCRIPTOR_HEADER*) buffer;
|
||||
// Check descriptor signature
|
||||
if (descriptor_header->Signature == FLASH_DESCRIPTOR_SIGNATURE) {
|
||||
FLASH_DESCRIPTOR_MAP* descriptor_map;
|
||||
FLASH_DESCRIPTOR_COMPONENT_SECTION* component_section;
|
||||
FLASH_DESCRIPTOR_REGION_SECTION* region_section;
|
||||
FLASH_DESCRIPTOR_MASTER_SECTION* master_section;
|
||||
// Vector of 16 0xFF for sanity check
|
||||
CONST UINT8 FFVector[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
|
||||
// Store the beginning of descriptor as descriptor base address
|
||||
UINT8* descriptor = buffer;
|
||||
UINT8* bios_region = NULL;
|
||||
|
||||
printf("Intel flash descriptor found\n");
|
||||
// Check for buffer size to be greater or equal to descriptor region size
|
||||
if (flash_image_size < FLASH_DESCRIPTOR_SIZE) {
|
||||
printf("Error: Input file is smaller then mininum descriptor size of 4KB\nAborting\n");
|
||||
return ERR_INVALID_FLASH_DESCRIPTOR;
|
||||
}
|
||||
|
||||
//Write descriptor to desc.bin
|
||||
result = write_to_file(descriptor, FLASH_DESCRIPTOR_SIZE, "DESC", "region");
|
||||
if (result){
|
||||
printf("Error: Can't write descriptor region to file\nAborting\n");
|
||||
return result;
|
||||
}
|
||||
printf("Descriptor region written to file\n");
|
||||
|
||||
// Check FFVector to consist 16 0xFF, as sanity check
|
||||
if (find_pattern(buffer, 16, FFVector, 16) != buffer)
|
||||
printf("Warning: Descriptor start vector has something but 0xFF bytes. That's strange\n");
|
||||
|
||||
// Skip descriptor header
|
||||
buffer += sizeof(FLASH_DESCRIPTOR_HEADER);
|
||||
|
||||
// Parse descriptor map
|
||||
descriptor_map = (FLASH_DESCRIPTOR_MAP*) buffer;
|
||||
component_section = (FLASH_DESCRIPTOR_COMPONENT_SECTION*) calculate_address_8(descriptor, descriptor_map->ComponentBase);
|
||||
region_section = (FLASH_DESCRIPTOR_REGION_SECTION*) calculate_address_8(descriptor, descriptor_map->RegionBase);
|
||||
master_section = (FLASH_DESCRIPTOR_MASTER_SECTION*) calculate_address_8(descriptor, descriptor_map->MasterBase);
|
||||
printf("\nParsing descriptor map\n"
|
||||
"Flash chips: %d\n"
|
||||
"Flash regions: %d\n"
|
||||
"Flash masters: %d\n"
|
||||
"PCH straps: %d\n"
|
||||
"PROC straps: %d\n"
|
||||
"ICC table entries: %d\n",
|
||||
descriptor_map->NumberOfFlashChips + 1,
|
||||
descriptor_map->NumberOfRegions + 1,
|
||||
descriptor_map->NumberOfMasters + 1,
|
||||
descriptor_map->NumberOfPchStraps,
|
||||
descriptor_map->NumberOfProcStraps,
|
||||
descriptor_map->NumberOfIccTableEntries);
|
||||
printf("Descriptor map parsed\n\n");
|
||||
|
||||
// Parse component section
|
||||
//!TODO: add parsing code
|
||||
// Parse master section
|
||||
//!TODO: add parsing code
|
||||
|
||||
// Parse region section
|
||||
printf("Parsing region section\n");
|
||||
parse_region(descriptor, flash_image_size, descriptor_map->NumberOfFlashChips, "GBE", region_section->GbeBase, region_section->GbeLimit);
|
||||
parse_region(descriptor, flash_image_size, descriptor_map->NumberOfFlashChips, "ME", region_section->MeBase, region_section->MeLimit);
|
||||
bios_region = parse_region(descriptor, flash_image_size, descriptor_map->NumberOfFlashChips, "BIOS", region_section->BiosBase, region_section->BiosLimit);
|
||||
parse_region(descriptor, flash_image_size, descriptor_map->NumberOfFlashChips, "PDR", region_section->PdrBase, region_section->PdrLimit);
|
||||
printf("Region section parsed\n\n");
|
||||
|
||||
// Parsing complete
|
||||
printf("Descriptor parsing complete\n\n");
|
||||
|
||||
// Exiting if no bios region found
|
||||
if (!bios_region) {
|
||||
printf("BIOS region not found\nAborting\n");
|
||||
return ERR_BIOS_REGION_NOT_FOUND;
|
||||
}
|
||||
|
||||
// BIOS region is our buffer now
|
||||
buffer = bios_region;
|
||||
buffer_size = calculate_region_size(region_section->BiosBase, region_section->BiosLimit);
|
||||
}
|
||||
else {
|
||||
printf("Intel flash descriptor not found, assuming that input file is BIOS region image\n\n");
|
||||
}
|
||||
|
||||
// We are in the beginning of BIOS space, where firmware volumes are
|
||||
// Parse BIOS space
|
||||
|
||||
result = parse_bios_space(buffer, buffer_size);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
return ERR_SUCCESS;
|
||||
}
|
28
parse.h
Normal file
28
parse.h
Normal file
@ -0,0 +1,28 @@
|
||||
/* parse.h
|
||||
|
||||
Copyright (c) 2013, Nikolaj Schlej. All rights reserved.
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
*/
|
||||
|
||||
#ifndef __PARSE_H__
|
||||
#define __PARSE_H__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "basetypes.h"
|
||||
#include "ffs.h"
|
||||
#include "descriptor.h"
|
||||
//#include "Tiano/TianoCompress.h"
|
||||
//#include "Tiano/TianoDecompress.h"
|
||||
//#include "LZMA/LzmaCompress.h"
|
||||
//#include "LZMA/LzmaDecompress.h"
|
||||
|
||||
UINT8 parse_buffer(UINT8* buffer, size_t size);
|
||||
|
||||
#endif
|
155
treeitem.cpp
Normal file
155
treeitem.cpp
Normal file
@ -0,0 +1,155 @@
|
||||
/* treeitem.cpp
|
||||
|
||||
Copyright (c) 2013, Nikolaj Schlej. All rights reserved.
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
*/
|
||||
|
||||
#include "treeitem.h"
|
||||
#include "treeitemtypes.h"
|
||||
|
||||
TreeItem::TreeItem(const UINT8 type, const UINT8 subtype, const QString & name, const QString & typeName, const QString & subtypeName,
|
||||
const QString & text, const QString & info, const QByteArray & header, const QByteArray & body, TreeItem *parent)
|
||||
{
|
||||
|
||||
itemType = type;
|
||||
itemSubtype = subtype;
|
||||
itemName = name;
|
||||
itemTypeName = typeName;
|
||||
itemSubtypeName = subtypeName;
|
||||
itemText = text;
|
||||
itemInfo = info;
|
||||
itemHeader = header;
|
||||
itemBody = body;
|
||||
parentItem = parent;
|
||||
}
|
||||
|
||||
TreeItem::~TreeItem()
|
||||
{
|
||||
qDeleteAll(childItems);
|
||||
}
|
||||
|
||||
void TreeItem::appendChild(TreeItem *item)
|
||||
{
|
||||
childItems.append(item);
|
||||
}
|
||||
|
||||
void TreeItem::removeChild(TreeItem *item)
|
||||
{
|
||||
childItems.removeAll(item);
|
||||
}
|
||||
|
||||
TreeItem *TreeItem::child(int row)
|
||||
{
|
||||
return childItems.value(row);
|
||||
}
|
||||
|
||||
int TreeItem::childCount() const
|
||||
{
|
||||
return childItems.count();
|
||||
}
|
||||
|
||||
int TreeItem::columnCount() const
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
QString TreeItem::data(int column) const
|
||||
{
|
||||
switch(column)
|
||||
{
|
||||
case 0: //Object
|
||||
return itemName;
|
||||
break;
|
||||
case 1: //Type
|
||||
return itemTypeName;
|
||||
break;
|
||||
case 2: //Subtype
|
||||
return itemSubtypeName;
|
||||
break;
|
||||
case 3: //Text
|
||||
return itemText;
|
||||
break;
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
TreeItem *TreeItem::parent()
|
||||
{
|
||||
return parentItem;
|
||||
}
|
||||
|
||||
void TreeItem::setName(const QString &text)
|
||||
{
|
||||
itemName = text;
|
||||
}
|
||||
|
||||
void TreeItem::setText(const QString &text)
|
||||
{
|
||||
itemText = text;
|
||||
}
|
||||
|
||||
void TreeItem::setTypeName(const QString &text)
|
||||
{
|
||||
itemTypeName = text;
|
||||
}
|
||||
|
||||
void TreeItem::setSubtypeName(const QString &text)
|
||||
{
|
||||
itemSubtypeName = text;
|
||||
}
|
||||
|
||||
QString TreeItem::info()
|
||||
{
|
||||
return itemInfo;
|
||||
}
|
||||
|
||||
void TreeItem::setInfo(const QString &text)
|
||||
{
|
||||
itemInfo = text;
|
||||
}
|
||||
|
||||
int TreeItem::row() const
|
||||
{
|
||||
if (parentItem)
|
||||
return parentItem->childItems.indexOf(const_cast<TreeItem*>(this));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
UINT8 TreeItem::type()
|
||||
{
|
||||
return itemType;
|
||||
}
|
||||
|
||||
UINT8 TreeItem::subtype()
|
||||
{
|
||||
return itemSubtype;
|
||||
}
|
||||
|
||||
QByteArray TreeItem::header()
|
||||
{
|
||||
return itemHeader;
|
||||
}
|
||||
|
||||
QByteArray TreeItem::body()
|
||||
{
|
||||
return itemBody;
|
||||
}
|
||||
|
||||
bool TreeItem::hasEmptyHeader()
|
||||
{
|
||||
return itemHeader.isEmpty();
|
||||
}
|
||||
|
||||
bool TreeItem::hasEmptyBody()
|
||||
{
|
||||
return itemBody.isEmpty();
|
||||
}
|
68
treeitem.h
Normal file
68
treeitem.h
Normal file
@ -0,0 +1,68 @@
|
||||
/* treeitem.h
|
||||
|
||||
Copyright (c) 2013, Nikolaj Schlej. All rights reserved.
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __TREEITEM_H__
|
||||
#define __TREEITEM_H__
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
|
||||
#include "basetypes.h"
|
||||
|
||||
class TreeItem
|
||||
{
|
||||
public:
|
||||
TreeItem(const UINT8 type, const UINT8 subtype = 0, const QString & name = QString(), const QString & typeName = QString(), const QString & subtypeName = QString(),
|
||||
const QString & text = QString(), const QString & info = QString(), const QByteArray & header = QByteArray(), const QByteArray & body = QByteArray(), TreeItem *parent = 0);
|
||||
~TreeItem();
|
||||
|
||||
void appendChild(TreeItem *item);
|
||||
void removeChild(TreeItem *item);
|
||||
|
||||
TreeItem *child(int row);
|
||||
int childCount() const;
|
||||
int columnCount() const;
|
||||
QString data(int column) const;
|
||||
int row() const;
|
||||
TreeItem *parent();
|
||||
|
||||
UINT8 type();
|
||||
UINT8 subtype();
|
||||
QByteArray header();
|
||||
QByteArray body();
|
||||
QString info();
|
||||
bool hasEmptyHeader();
|
||||
bool hasEmptyBody();
|
||||
|
||||
void setName(const QString &text);
|
||||
void setText(const QString &text);
|
||||
void setTypeName(const QString &text);
|
||||
void setSubtypeName(const QString &text);
|
||||
void setInfo(const QString &text);
|
||||
|
||||
private:
|
||||
QList<TreeItem*> childItems;
|
||||
UINT8 itemType;
|
||||
UINT8 itemSubtype;
|
||||
QByteArray itemHeader;
|
||||
QByteArray itemBody;
|
||||
QString itemName;
|
||||
QString itemTypeName;
|
||||
QString itemSubtypeName;
|
||||
QString itemText;
|
||||
QString itemInfo;
|
||||
TreeItem *parentItem;
|
||||
};
|
||||
|
||||
#endif
|
80
treeitemtypes.h
Normal file
80
treeitemtypes.h
Normal file
@ -0,0 +1,80 @@
|
||||
/* treeitemtypes.h
|
||||
|
||||
Copyright (c) 2013, Nikolaj Schlej. All rights reserved.
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __TREEITEMTYPES_H__
|
||||
#define __TREEITEMTYPES_H__
|
||||
|
||||
// TreeItem types
|
||||
enum ItemTypes {
|
||||
RootItem,
|
||||
CapsuleItem,
|
||||
DescriptorItem,
|
||||
RegionItem,
|
||||
PaddingItem,
|
||||
VolumeItem,
|
||||
FileItem,
|
||||
SectionItem
|
||||
};
|
||||
|
||||
// Capsule subtypes
|
||||
enum CapsuleSubtypes {
|
||||
AptioCapsule,
|
||||
UefiCapsule
|
||||
};
|
||||
|
||||
// Region subtypes
|
||||
enum RegionSubtypes {
|
||||
GbeRegion,
|
||||
MeRegion,
|
||||
BiosRegion,
|
||||
PdrRegion
|
||||
};
|
||||
|
||||
// File subtypes
|
||||
enum FileSubtypes {
|
||||
RawFile,
|
||||
FreeformFile,
|
||||
SecurityCoreFile,
|
||||
PeiCoreFile,
|
||||
DxeCoreFile,
|
||||
PeiModuleFile,
|
||||
DxeDriverFile,
|
||||
CombinedPeiDxeFile,
|
||||
ApplicationFile,
|
||||
SmmModuleFile,
|
||||
VolumeImageFile,
|
||||
CombinedSmmDxeFile,
|
||||
SmmCoreFile,
|
||||
PadFile = 0xF0
|
||||
};
|
||||
|
||||
enum SectionSubtypes {
|
||||
CompressionSection = 0x01,
|
||||
GuidDefinedSection,
|
||||
DisposableSection,
|
||||
Pe32ImageSection = 0x10,
|
||||
PicImageSection,
|
||||
TeImageSection,
|
||||
DxeDepexSection,
|
||||
VersionSection,
|
||||
UserInterfaceSection,
|
||||
Compatibility16Section,
|
||||
VolumeImageSection,
|
||||
FreeformSubtypeGuidSection,
|
||||
RawSection,
|
||||
PeiDepexSection = 0x1B,
|
||||
SmmDepexSection
|
||||
};
|
||||
|
||||
|
||||
#endif
|
354
treemodel.cpp
Normal file
354
treemodel.cpp
Normal file
@ -0,0 +1,354 @@
|
||||
/* treemodel.cpp
|
||||
|
||||
Copyright (c) 2013, Nikolaj Schlej. All rights reserved.
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
*/
|
||||
|
||||
#include "treeitem.h"
|
||||
#include "treemodel.h"
|
||||
#include "ffs.h"
|
||||
#include "descriptor.h"
|
||||
|
||||
TreeModel::TreeModel(QObject *parent)
|
||||
: QAbstractItemModel(parent)
|
||||
{
|
||||
rootItem = new TreeItem(ItemTypes::RootItem, 0, tr("Object"), tr("Type"), tr("Subtype"), tr("Text"));
|
||||
}
|
||||
|
||||
TreeModel::~TreeModel()
|
||||
{
|
||||
delete rootItem;
|
||||
}
|
||||
|
||||
bool TreeModel::hasEmptyHeader(const QModelIndex& index)
|
||||
{
|
||||
if (!index.isValid())
|
||||
return true;
|
||||
|
||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
||||
|
||||
return item->hasEmptyHeader();
|
||||
}
|
||||
|
||||
bool TreeModel::hasEmptyBody(const QModelIndex& index)
|
||||
{
|
||||
if (!index.isValid())
|
||||
return true;
|
||||
|
||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
||||
|
||||
return item->hasEmptyBody();
|
||||
}
|
||||
|
||||
|
||||
int TreeModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
if (parent.isValid())
|
||||
return static_cast<TreeItem*>(parent.internalPointer())->columnCount();
|
||||
else
|
||||
return rootItem->columnCount();
|
||||
}
|
||||
|
||||
QVariant TreeModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
if (role != Qt::DisplayRole && role != Qt::UserRole)
|
||||
return QVariant();
|
||||
|
||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
||||
|
||||
if (role == Qt::DisplayRole)
|
||||
return item->data(index.column());
|
||||
else
|
||||
return item->info();
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
Qt::ItemFlags TreeModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return 0;
|
||||
|
||||
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
||||
}
|
||||
|
||||
QVariant TreeModel::headerData(int section, Qt::Orientation orientation,
|
||||
int role) const
|
||||
{
|
||||
if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
|
||||
return rootItem->data(section);
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent)
|
||||
const
|
||||
{
|
||||
if (!hasIndex(row, column, parent))
|
||||
return QModelIndex();
|
||||
|
||||
TreeItem *parentItem;
|
||||
|
||||
if (!parent.isValid())
|
||||
parentItem = rootItem;
|
||||
else
|
||||
parentItem = static_cast<TreeItem*>(parent.internalPointer());
|
||||
|
||||
TreeItem *childItem = parentItem->child(row);
|
||||
if (childItem)
|
||||
return createIndex(row, column, childItem);
|
||||
else
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
QModelIndex TreeModel::parent(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QModelIndex();
|
||||
|
||||
TreeItem *childItem = static_cast<TreeItem*>(index.internalPointer());
|
||||
TreeItem *parentItem = childItem->parent();
|
||||
|
||||
if (parentItem == rootItem)
|
||||
return QModelIndex();
|
||||
|
||||
return createIndex(parentItem->row(), 0, parentItem);
|
||||
}
|
||||
|
||||
|
||||
int TreeModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
TreeItem *parentItem;
|
||||
if (parent.column() > 0)
|
||||
return 0;
|
||||
|
||||
if (!parent.isValid())
|
||||
parentItem = rootItem;
|
||||
else
|
||||
parentItem = static_cast<TreeItem*>(parent.internalPointer());
|
||||
|
||||
return parentItem->childCount();
|
||||
}
|
||||
|
||||
QModelIndex TreeModel::addItem(UINT8 type, UINT8 subtype, const QByteArray &header, const QByteArray &body, const QModelIndex &parent)
|
||||
{
|
||||
TreeItem *parentItem;
|
||||
int parentColumn = 0;
|
||||
|
||||
if (!parent.isValid())
|
||||
parentItem = rootItem;
|
||||
else
|
||||
{
|
||||
parentItem = static_cast<TreeItem*>(parent.internalPointer());
|
||||
parentColumn = parent.column();
|
||||
}
|
||||
|
||||
// All information extraction must be here
|
||||
QString name, typeName, subtypeName, info;
|
||||
EFI_CAPSULE_HEADER* capsuleHeader;
|
||||
APTIO_CAPSULE_HEADER* aptioCapsuleHeader;
|
||||
FLASH_DESCRIPTOR_MAP* descriptorMap;
|
||||
//FLASH_DESCRIPTOR_COMPONENT_SECTION* componentSection;
|
||||
//FLASH_DESCRIPTOR_REGION_SECTION* regionSection;
|
||||
//FLASH_DESCRIPTOR_MASTER_SECTION* masterSection;
|
||||
EFI_FIRMWARE_VOLUME_HEADER* volumeHeader;
|
||||
EFI_FFS_FILE_HEADER* fileHeader;
|
||||
//EFI_COMMON_SECTION_HEADER* sectionHeader;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case ItemTypes::RootItem:
|
||||
// Do not allow to add another root item
|
||||
return QModelIndex();
|
||||
break;
|
||||
case ItemTypes::CapsuleItem:
|
||||
//typeName = tr("Capsule");
|
||||
switch (subtype)
|
||||
{
|
||||
case CapsuleSubtypes::AptioCapsule:
|
||||
name = tr("AMI Aptio capsule");
|
||||
aptioCapsuleHeader = (APTIO_CAPSULE_HEADER*) header.constData();
|
||||
info = tr("GUID: %1\nHeader size: %2\nFlags: %3\nImage size: %4")
|
||||
.arg(guidToQString(aptioCapsuleHeader->CapsuleHeader.CapsuleGuid))
|
||||
.arg(aptioCapsuleHeader->CapsuleHeader.Flags, 8, 16, QChar('0'))
|
||||
.arg(aptioCapsuleHeader->RomImageOffset, 4, 16, QChar('0'))
|
||||
.arg(aptioCapsuleHeader->CapsuleHeader.CapsuleImageSize - aptioCapsuleHeader->RomImageOffset, 8, 16, QChar('0'));
|
||||
//!TODO: more info about Aptio capsule
|
||||
break;
|
||||
case CapsuleSubtypes::UefiCapsule:
|
||||
name = tr("UEFI capsule");
|
||||
capsuleHeader = (EFI_CAPSULE_HEADER*) header.constData();
|
||||
info = tr("GUID: %1\nHeader size: %2\nFlags: %3\nImage size: %4")
|
||||
.arg(guidToQString(capsuleHeader->CapsuleGuid))
|
||||
.arg(capsuleHeader->Flags, 8, 16, QChar('0'))
|
||||
.arg(capsuleHeader->HeaderSize, 8, 16, QChar('0'))
|
||||
.arg(capsuleHeader->CapsuleImageSize, 8, 16, QChar('0'));
|
||||
break;
|
||||
default:
|
||||
name = tr("Unknown capsule");
|
||||
info = tr("GUID: %1\n").arg(guidToQString(*(EFI_GUID*)header.constData()));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ItemTypes::DescriptorItem:
|
||||
name = tr("Descriptor");
|
||||
descriptorMap = (FLASH_DESCRIPTOR_MAP*) body.constData();
|
||||
info = tr("Flash chips: %1\nRegions: %2\nMasters: %3\nPCH straps:%4\nPROC straps: %5\nICC table entries: %6")
|
||||
.arg(descriptorMap->NumberOfFlashChips + 1) //
|
||||
.arg(descriptorMap->NumberOfRegions + 1) // Zero-based numbers in storage
|
||||
.arg(descriptorMap->NumberOfMasters + 1) //
|
||||
.arg(descriptorMap->NumberOfPchStraps)
|
||||
.arg(descriptorMap->NumberOfProcStraps)
|
||||
.arg(descriptorMap->NumberOfIccTableEntries);
|
||||
//!TODO: more info about descriptor
|
||||
break;
|
||||
case ItemTypes::RegionItem:
|
||||
typeName = tr("Region");
|
||||
info = tr("Size: %1").arg(body.size(), 8, 16, QChar('0'));
|
||||
//!TODO: more info about GbE and ME regions
|
||||
switch (subtype)
|
||||
{
|
||||
case RegionSubtypes::GbeRegion:
|
||||
name = tr("GbE region");
|
||||
break;
|
||||
case RegionSubtypes::MeRegion:
|
||||
name = tr("ME region");
|
||||
break;
|
||||
case RegionSubtypes::BiosRegion:
|
||||
name = tr("BIOS region");
|
||||
break;
|
||||
case RegionSubtypes::PdrRegion:
|
||||
name = tr("PDR region");
|
||||
break;
|
||||
default:
|
||||
name = tr("Unknown region");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ItemTypes::PaddingItem:
|
||||
name = tr("Padding");
|
||||
info = tr("Size: %1").arg(body.size(), 8, 16, QChar('0'));
|
||||
break;
|
||||
case ItemTypes::VolumeItem:
|
||||
typeName = tr("Volume");
|
||||
// Parse volume header to determine its revision and file system
|
||||
volumeHeader = (EFI_FIRMWARE_VOLUME_HEADER*) header.constData();
|
||||
name = guidToQString(volumeHeader->FileSystemGuid);
|
||||
subtypeName = tr("Revision %1").arg(volumeHeader->Revision);
|
||||
info = tr("Size: %1\nSignature: %2\nAttributes: %3\nHeader size: %4")
|
||||
.arg(volumeHeader->FvLength, 8, 16, QChar('0'))
|
||||
.arg(volumeHeader->Signature, 8, 16, QChar('0'))
|
||||
.arg(volumeHeader->Attributes, 8, 16, QChar('0'))
|
||||
.arg(volumeHeader->HeaderLength, 4, 16, QChar('0'));
|
||||
break;
|
||||
case ItemTypes::FileItem:
|
||||
typeName = tr("File");
|
||||
// Parse file header to determine its GUID and type
|
||||
fileHeader = (EFI_FFS_FILE_HEADER*) header.constData();
|
||||
name = guidToQString(fileHeader->Name);
|
||||
subtypeName = fileTypeToQString(subtype);
|
||||
info = tr("Type: %1\nAttributes: %2\nSize: %3\nState: %4")
|
||||
.arg(fileHeader->Type, 2, 16, QChar('0'))
|
||||
.arg(fileHeader->Attributes, 2, 16, QChar('0'))
|
||||
.arg(uint24ToUint32(fileHeader->Size), 6, 16, QChar('0'))
|
||||
.arg(fileHeader->State, 2, 16, QChar('0'));
|
||||
break;
|
||||
case ItemTypes::SectionItem:
|
||||
typeName = tr("Section");
|
||||
name = sectionTypeToQString(subtype) + tr(" section");
|
||||
info = tr("Size: %1").arg(body.size(), 8, 16, QChar('0'));
|
||||
//!TODO: add more specific info for all section types with uncommon headers
|
||||
// Set name of file
|
||||
if (subtype == SectionSubtypes::UserInterfaceSection)
|
||||
{
|
||||
QString text = QString::fromUtf16((const ushort*)body.constData());
|
||||
setItemText(text, findParentOfType(ItemTypes::FileItem, parent));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
name = tr("Unknown");
|
||||
break;
|
||||
}
|
||||
|
||||
emit layoutAboutToBeChanged();
|
||||
TreeItem *item = new TreeItem(type, subtype, name, typeName, subtypeName, "", info, header, body, parentItem);
|
||||
parentItem->appendChild(item);
|
||||
emit layoutChanged();
|
||||
return createIndex(parentItem->childCount() - 1, parentColumn, item);
|
||||
}
|
||||
|
||||
bool TreeModel::setItemName(const QString &data, const QModelIndex &index)
|
||||
{
|
||||
if(!index.isValid())
|
||||
return false;
|
||||
|
||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
||||
item->setName(data);
|
||||
emit dataChanged(index, index);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TreeModel::setItemText(const QString &data, const QModelIndex &index)
|
||||
{
|
||||
if(!index.isValid())
|
||||
return false;
|
||||
|
||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
||||
item->setText(data);
|
||||
emit dataChanged(index, index);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TreeModel::removeItem(const QModelIndex &index)
|
||||
{
|
||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
||||
item->parent()->removeChild(item);
|
||||
delete item;
|
||||
return true;
|
||||
}
|
||||
|
||||
QModelIndex TreeModel::findParentOfType(UINT8 type, const QModelIndex& index)
|
||||
{
|
||||
if(!index.isValid())
|
||||
return QModelIndex();
|
||||
|
||||
TreeItem *item;
|
||||
QModelIndex parent = index;
|
||||
|
||||
for(item = static_cast<TreeItem*>(parent.internalPointer());
|
||||
item != NULL && item != rootItem && item->type() != type;
|
||||
item = static_cast<TreeItem*>(parent.internalPointer()))
|
||||
parent = parent.parent();
|
||||
if (item != NULL && item != rootItem)
|
||||
return parent;
|
||||
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
QByteArray TreeModel::header(const QModelIndex& index)
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QByteArray();
|
||||
|
||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
||||
return item->header();
|
||||
}
|
||||
|
||||
QByteArray TreeModel::body(const QModelIndex& index)
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QByteArray();
|
||||
|
||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
||||
return item->body();
|
||||
}
|
60
treemodel.h
Normal file
60
treemodel.h
Normal file
@ -0,0 +1,60 @@
|
||||
/* treemodel.h
|
||||
|
||||
Copyright (c) 2013, Nikolaj Schlej. All rights reserved.
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __TREEMODEL_H__
|
||||
#define __TREEMODEL_H__
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QModelIndex>
|
||||
#include <QString>
|
||||
#include <QVariant>
|
||||
|
||||
#include "basetypes.h"
|
||||
#include "treeitemtypes.h"
|
||||
|
||||
class TreeItem;
|
||||
|
||||
class TreeModel : public QAbstractItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TreeModel(QObject *parent = 0);
|
||||
~TreeModel();
|
||||
|
||||
QVariant data(const QModelIndex &index, int role) const;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const;
|
||||
QVariant headerData(int section, Qt::Orientation orientation,
|
||||
int role = Qt::DisplayRole) const;
|
||||
QModelIndex index(int row, int column,
|
||||
const QModelIndex &parent = QModelIndex()) const;
|
||||
QModelIndex parent(const QModelIndex &index) const;
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
|
||||
QModelIndex addItem(UINT8 type, UINT8 subtype = 0, const QByteArray &header = QByteArray(), const QByteArray &body = QByteArray(), const QModelIndex &parent = QModelIndex());
|
||||
bool removeItem(const QModelIndex &index);
|
||||
|
||||
QByteArray header(const QModelIndex& index);
|
||||
bool hasEmptyHeader(const QModelIndex& index);
|
||||
QByteArray body(const QModelIndex& index);
|
||||
bool hasEmptyBody(const QModelIndex& index);
|
||||
|
||||
private:
|
||||
QModelIndex findParentOfType(UINT8 type, const QModelIndex& index);
|
||||
bool setItemName(const QString &data, const QModelIndex &index);
|
||||
bool setItemText(const QString &data, const QModelIndex &index);
|
||||
TreeItem *rootItem;
|
||||
};
|
||||
|
||||
#endif
|
960
uefitool.cpp
Normal file
960
uefitool.cpp
Normal file
@ -0,0 +1,960 @@
|
||||
/* uefitool.cpp
|
||||
|
||||
Copyright (c) 2013, Nikolaj Schlej. All rights reserved.
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
*/
|
||||
|
||||
#include "uefitool.h"
|
||||
#include "ui_uefitool.h"
|
||||
|
||||
UEFITool::UEFITool(QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
ui(new Ui::UEFITool)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
treeModel = NULL;
|
||||
|
||||
// Signal-slot connections
|
||||
connect(ui->fromFileButton, SIGNAL(clicked()), this, SLOT(openImageFile()));
|
||||
connect(ui->exportAllButton, SIGNAL(clicked()), this, SLOT(saveAll()));
|
||||
connect(ui->exportBodyButton, SIGNAL(clicked()), this, SLOT(saveBody()));
|
||||
|
||||
// Enable Drag-and-Drop actions
|
||||
this->setAcceptDrops(true);
|
||||
|
||||
// Initialise non-persistent data
|
||||
init();
|
||||
}
|
||||
|
||||
UEFITool::~UEFITool()
|
||||
{
|
||||
delete ui;
|
||||
delete treeModel;
|
||||
}
|
||||
|
||||
void UEFITool::init()
|
||||
{
|
||||
// Clear UI components
|
||||
ui->debugEdit->clear();
|
||||
ui->infoEdit->clear();
|
||||
ui->exportAllButton->setDisabled(true);
|
||||
ui->exportBodyButton->setDisabled(true);
|
||||
// Make new tree model
|
||||
TreeModel * newModel = new TreeModel(this);
|
||||
ui->structureTreeView->setModel(newModel);
|
||||
if (treeModel)
|
||||
delete treeModel;
|
||||
treeModel = newModel;
|
||||
// Show info after selection the item in tree view
|
||||
connect(ui->structureTreeView->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)),
|
||||
this, SLOT(populateUi(const QModelIndex &)));
|
||||
//connect(ui->structureTreeView, SIGNAL(collapsed(const QModelIndex &)), this, SLOT(resizeTreeViewColums(void)));
|
||||
connect(ui->structureTreeView, SIGNAL(expanded(const QModelIndex &)), this, SLOT(resizeTreeViewColums(void)));
|
||||
resizeTreeViewColums();
|
||||
}
|
||||
|
||||
void UEFITool::populateUi(const QModelIndex ¤t/*, const QModelIndex &previous*/)
|
||||
{
|
||||
//!TODO: make widget
|
||||
currentIndex = current;
|
||||
ui->infoEdit->setPlainText(current.data(Qt::UserRole).toString());
|
||||
ui->exportAllButton->setDisabled(treeModel->hasEmptyBody(current) && treeModel->hasEmptyHeader(current));
|
||||
ui->exportBodyButton->setDisabled(treeModel->hasEmptyHeader(current));
|
||||
}
|
||||
|
||||
void UEFITool::resizeTreeViewColums(/*const QModelIndex &index*/)
|
||||
{
|
||||
int count = treeModel->columnCount();
|
||||
for(int i = 0; i < count; i++)
|
||||
ui->structureTreeView->resizeColumnToContents(i);
|
||||
}
|
||||
|
||||
void UEFITool::openImageFile()
|
||||
{
|
||||
QString path = QFileDialog::getOpenFileName(this, tr("Open BIOS image file"),".","BIOS image file (*.rom *.bin *.cap *.bio *.fd *.wph *.efi);;All files (*.*)");
|
||||
openImageFile(path);
|
||||
}
|
||||
|
||||
void UEFITool::openImageFile(QString path)
|
||||
{
|
||||
QFileInfo fileInfo = QFileInfo(path);
|
||||
if (!fileInfo.exists())
|
||||
{
|
||||
ui->statusBar->showMessage(tr("Please select existing BIOS image file."));
|
||||
return;
|
||||
}
|
||||
|
||||
QFile inputFile;
|
||||
inputFile.setFileName(path);
|
||||
|
||||
if (!inputFile.open(QFile::ReadOnly))
|
||||
{
|
||||
ui->statusBar->showMessage(tr("Can't open file for reading. Check file permissions."));
|
||||
return;
|
||||
}
|
||||
|
||||
QByteArray buffer = inputFile.readAll();
|
||||
inputFile.close();
|
||||
|
||||
init();
|
||||
UINT8 result = parseInputFile(buffer);
|
||||
if (result)
|
||||
debug(tr("Opened file can't be parsed as UEFI image (%1)").arg(result));
|
||||
else
|
||||
ui->statusBar->showMessage(tr("Opened: %1").arg(fileInfo.fileName()));
|
||||
resizeTreeViewColums();
|
||||
}
|
||||
|
||||
void UEFITool::saveAll()
|
||||
{
|
||||
QString path = QFileDialog::getSaveFileName(this, tr("Save header to binary file"),".","Binary files (*.bin);;All files (*.*)");
|
||||
|
||||
QFile outputFile;
|
||||
outputFile.setFileName(path);
|
||||
if (!outputFile.open(QFile::WriteOnly))
|
||||
{
|
||||
ui->statusBar->showMessage(tr("Can't open file for writing. Check file permissions."));
|
||||
return;
|
||||
}
|
||||
|
||||
outputFile.write(treeModel->header(currentIndex) + treeModel->body(currentIndex));
|
||||
outputFile.close();
|
||||
}
|
||||
|
||||
void UEFITool::saveBody()
|
||||
{
|
||||
QString path = QFileDialog::getSaveFileName(this, tr("Save body to binary file"),".","Binary files (*.bin);;All files (*.*)");
|
||||
|
||||
QFile outputFile;
|
||||
outputFile.setFileName(path);
|
||||
if (!outputFile.open(QFile::WriteOnly))
|
||||
{
|
||||
ui->statusBar->showMessage(tr("Can't open file for writing. Check file permissions."));
|
||||
return;
|
||||
}
|
||||
|
||||
outputFile.write(treeModel->body(currentIndex));
|
||||
outputFile.close();
|
||||
}
|
||||
|
||||
/*void UEFITool::saveImageFile()
|
||||
{
|
||||
QString path = QFileDialog::getSaveFileName(this, tr("Save BIOS image file"),".","BIOS image file (*.rom *.bin *.cap *.fd *.fwh);;All files (*.*)");
|
||||
|
||||
QFileInfo fileInfo = QFileInfo(path);
|
||||
if (!fileInfo.exists())
|
||||
{
|
||||
ui->statusBar->showMessage(tr("Please select existing BIOS image file."));
|
||||
return;
|
||||
}
|
||||
|
||||
QFile outputFile;
|
||||
outputFile.setFileName(path);
|
||||
if (!outputFile.open(QFile::ReadWrite))
|
||||
{
|
||||
ui->statusBar->showMessage(tr("Can't open file for writing. Check file permissions."));
|
||||
return;
|
||||
}
|
||||
}*/
|
||||
|
||||
void UEFITool::dragEnterEvent(QDragEnterEvent* event)
|
||||
{
|
||||
if (event->mimeData()->hasFormat("text/uri-list"))
|
||||
event->acceptProposedAction();
|
||||
}
|
||||
|
||||
void UEFITool::dropEvent(QDropEvent* event)
|
||||
{
|
||||
QString path = event->mimeData()->urls().at(0).toLocalFile();
|
||||
openImageFile(path);
|
||||
}
|
||||
|
||||
void UEFITool::debug(const QString & text)
|
||||
{
|
||||
//!TODO: log to separate debug window
|
||||
ui->debugEdit->appendPlainText(text);
|
||||
}
|
||||
|
||||
QModelIndex UEFITool::addTreeItem(UINT8 type, UINT8 subtype,
|
||||
const QByteArray & header, const QByteArray & body, const QModelIndex & parent)
|
||||
{
|
||||
return treeModel->addItem(type, subtype, header, body, parent);
|
||||
}
|
||||
|
||||
UINT8 UEFITool::parseInputFile(const QByteArray & buffer)
|
||||
{
|
||||
UINT32 capsuleHeaderSize = 0;
|
||||
FLASH_DESCRIPTOR_HEADER* descriptorHeader = NULL;
|
||||
QByteArray flashImage;
|
||||
QByteArray bios;
|
||||
QModelIndex index;
|
||||
|
||||
// Check buffer for being normal EFI capsule header
|
||||
if (buffer.startsWith(EFI_CAPSULE_GUID)) {
|
||||
EFI_CAPSULE_HEADER* capsuleHeader = (EFI_CAPSULE_HEADER*) buffer.constData();
|
||||
capsuleHeaderSize = capsuleHeader->HeaderSize;
|
||||
QByteArray header = buffer.left(capsuleHeaderSize);
|
||||
QByteArray body = buffer.right(buffer.size() - capsuleHeaderSize);
|
||||
index = addTreeItem(ItemTypes::CapsuleItem, CapsuleSubtypes::UefiCapsule, header, body);
|
||||
}
|
||||
|
||||
// Check buffer for being extended Aptio capsule header
|
||||
else if (buffer.startsWith(APTIO_CAPSULE_GUID)) {
|
||||
APTIO_CAPSULE_HEADER* aptioCapsuleHeader = (APTIO_CAPSULE_HEADER*) buffer.constData();
|
||||
capsuleHeaderSize = aptioCapsuleHeader->RomImageOffset;
|
||||
QByteArray header = buffer.left(capsuleHeaderSize);
|
||||
QByteArray body = buffer.right(buffer.size() - capsuleHeaderSize);
|
||||
index = addTreeItem(ItemTypes::CapsuleItem, CapsuleSubtypes::AptioCapsule, header, body);
|
||||
}
|
||||
|
||||
// Skip capsule header to have flash chip image
|
||||
flashImage = buffer.right(buffer.size() - capsuleHeaderSize);
|
||||
|
||||
// Check buffer for being Intel flash descriptor
|
||||
descriptorHeader = (FLASH_DESCRIPTOR_HEADER*) flashImage.constData();
|
||||
// Check descriptor signature
|
||||
if (descriptorHeader->Signature == FLASH_DESCRIPTOR_SIGNATURE) {
|
||||
FLASH_DESCRIPTOR_MAP* descriptorMap;
|
||||
FLASH_DESCRIPTOR_REGION_SECTION* regionSection;
|
||||
|
||||
// Store the beginning of descriptor as descriptor base address
|
||||
UINT8* descriptor = (UINT8*) flashImage.constData();
|
||||
UINT8* gbeRegion = NULL;
|
||||
UINT8* meRegion = NULL;
|
||||
UINT8* biosRegion = NULL;
|
||||
UINT8* pdrRegion = NULL;
|
||||
|
||||
// Check for buffer size to be greater or equal to descriptor region size
|
||||
if (flashImage.size() < FLASH_DESCRIPTOR_SIZE) {
|
||||
debug(tr("Input file is smaller then mininum descriptor size of 4KB"));
|
||||
return ERR_INVALID_FLASH_DESCRIPTOR;
|
||||
}
|
||||
|
||||
// Parse descriptor map
|
||||
descriptorMap = (FLASH_DESCRIPTOR_MAP*) (flashImage.constData() + sizeof(FLASH_DESCRIPTOR_HEADER));
|
||||
regionSection = (FLASH_DESCRIPTOR_REGION_SECTION*) calculateAddress8(descriptor, descriptorMap->RegionBase);
|
||||
|
||||
// Add tree item
|
||||
QByteArray header = flashImage.left(sizeof(FLASH_DESCRIPTOR_HEADER));
|
||||
QByteArray body = flashImage.mid(sizeof(FLASH_DESCRIPTOR_HEADER), FLASH_DESCRIPTOR_SIZE - sizeof(FLASH_DESCRIPTOR_HEADER));
|
||||
index = addTreeItem(ItemTypes::DescriptorItem, 0, header, body, index);
|
||||
|
||||
// Parse region section
|
||||
QModelIndex gbeIndex(index);
|
||||
QModelIndex meIndex(index);
|
||||
QModelIndex biosIndex(index);
|
||||
QModelIndex pdrIndex(index);
|
||||
gbeRegion = parseRegion(flashImage, RegionSubtypes::GbeRegion, regionSection->GbeBase, regionSection->GbeLimit, gbeIndex);
|
||||
meRegion = parseRegion(flashImage, RegionSubtypes::MeRegion, regionSection->MeBase, regionSection->MeLimit, meIndex);
|
||||
biosRegion = parseRegion(flashImage, RegionSubtypes::BiosRegion, regionSection->BiosBase, regionSection->BiosLimit, biosIndex);
|
||||
pdrRegion = parseRegion(flashImage, RegionSubtypes::PdrRegion, regionSection->PdrBase, regionSection->PdrLimit, pdrIndex);
|
||||
|
||||
// Parse complete
|
||||
//!TODO: show some info about GbE, ME and PDR regions if found
|
||||
|
||||
// Exit if no bios region found
|
||||
if (!biosRegion) {
|
||||
debug(tr("BIOS region not found"));
|
||||
return ERR_BIOS_REGION_NOT_FOUND;
|
||||
}
|
||||
|
||||
index = biosIndex;
|
||||
bios = QByteArray::fromRawData((const char*) biosRegion, calculateRegionSize(regionSection->BiosBase, regionSection->BiosLimit));
|
||||
}
|
||||
else {
|
||||
bios = buffer;
|
||||
}
|
||||
|
||||
// We are in the beginning of BIOS space, where firmware volumes are
|
||||
// Parse BIOS space
|
||||
|
||||
return parseBios(bios, index);
|
||||
}
|
||||
|
||||
UINT8* UEFITool::parseRegion(const QByteArray & flashImage, UINT8 regionSubtype, const UINT16 regionBase, const UINT16 regionLimit, QModelIndex & index)
|
||||
{
|
||||
// Check for empty region
|
||||
if (!regionLimit)
|
||||
return NULL;
|
||||
|
||||
// Calculate region size
|
||||
UINT32 regionSize = calculateRegionSize(regionBase, regionLimit);
|
||||
|
||||
// Populate descriptor map
|
||||
FLASH_DESCRIPTOR_MAP* descriptor_map = (FLASH_DESCRIPTOR_MAP*) flashImage.constData() + sizeof(FLASH_DESCRIPTOR_HEADER);
|
||||
|
||||
// Determine presence of 2 flash chips
|
||||
bool twoChips = descriptor_map->NumberOfFlashChips;
|
||||
|
||||
// construct region name
|
||||
//!TODO: make this to regionTypeToQString(const UINT8 type) in descriptor.cpp
|
||||
QString regionName;
|
||||
switch (regionSubtype)
|
||||
{
|
||||
case RegionSubtypes::GbeRegion:
|
||||
regionName = "GbE";
|
||||
break;
|
||||
case RegionSubtypes::MeRegion:
|
||||
regionName = "ME";
|
||||
break;
|
||||
case RegionSubtypes::BiosRegion:
|
||||
regionName = "Bios";
|
||||
break;
|
||||
case RegionSubtypes::PdrRegion:
|
||||
regionName = "PDR";
|
||||
break;
|
||||
default:
|
||||
regionName = "Unknown";
|
||||
debug(tr("Unknown region type"));
|
||||
};
|
||||
|
||||
// Check region base to be in buffer
|
||||
if (regionBase * 0x1000 >= flashImage.size())
|
||||
{
|
||||
debug(tr("%1 region stored in descriptor not found").arg(regionName));
|
||||
if (twoChips)
|
||||
debug(tr("Two flash chips installed, so it could be in another flash chip\n"
|
||||
"Make a dump from another flash chip and open it to view information about %1 region").arg(regionName));
|
||||
else
|
||||
debug(tr("One flash chip installed, so it is an error caused by damaged or incomplete dump"));
|
||||
debug(tr("Absence of %1 region assumed").arg(regionName));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Check region to be fully present in buffer
|
||||
else if (regionBase * 0x1000 + regionSize > flashImage.size())
|
||||
{
|
||||
debug(tr("%s region stored in descriptor overlaps the end of opened file").arg(regionName));
|
||||
if (twoChips)
|
||||
debug(tr("Two flash chips installed, so it could be in another flash chip\n"
|
||||
"Make a dump from another flash chip and open it to view information about %1 region").arg(regionName));
|
||||
else
|
||||
debug(tr("One flash chip installed, so it is an error caused by damaged or incomplete dump"));
|
||||
debug(tr("Absence of %1 region assumed\n").arg(regionName));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Calculate region address
|
||||
UINT8* region = calculateAddress16((UINT8*) flashImage.constData(), regionBase);
|
||||
|
||||
// Add tree item
|
||||
QByteArray body = flashImage.mid(regionBase * 0x1000, regionSize);
|
||||
index = addTreeItem(ItemTypes::RegionItem, regionSubtype, QByteArray(), body, index);
|
||||
|
||||
return region;
|
||||
}
|
||||
|
||||
UINT8 UEFITool::parseBios(const QByteArray & bios, QModelIndex & parent)
|
||||
{
|
||||
// Search for first volume
|
||||
INT32 prevVolumeIndex = getNextVolumeIndex(bios);
|
||||
|
||||
// No volumes found
|
||||
if (prevVolumeIndex < 0) {
|
||||
return ERR_VOLUMES_NOT_FOUND;
|
||||
}
|
||||
|
||||
// First volume is not at the beginning of bios space
|
||||
if (prevVolumeIndex > 0) {
|
||||
QByteArray padding = bios.left(prevVolumeIndex);
|
||||
addTreeItem(ItemTypes::PaddingItem, 0, QByteArray(), padding, parent);
|
||||
}
|
||||
|
||||
// Search for and parse all volumes
|
||||
INT32 volumeIndex;
|
||||
UINT32 prevVolumeSize;
|
||||
for (volumeIndex = prevVolumeIndex, prevVolumeSize = 0;
|
||||
volumeIndex >= 0;
|
||||
prevVolumeIndex = volumeIndex, prevVolumeSize = getVolumeSize(bios, volumeIndex), volumeIndex = getNextVolumeIndex(bios, volumeIndex + prevVolumeSize))
|
||||
{
|
||||
// Padding between volumes
|
||||
if (volumeIndex > prevVolumeIndex + prevVolumeSize) {
|
||||
UINT32 size = volumeIndex - prevVolumeIndex - prevVolumeSize;
|
||||
QByteArray padding = bios.mid(prevVolumeIndex + prevVolumeSize, size);
|
||||
addTreeItem(ItemTypes::PaddingItem, 0, QByteArray(), padding, parent);
|
||||
}
|
||||
|
||||
// Populate volume header
|
||||
EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (EFI_FIRMWARE_VOLUME_HEADER*) (bios.constData() + volumeIndex);
|
||||
|
||||
//Check that volume is fully present in input
|
||||
if (volumeIndex + volumeHeader->FvLength > bios.size()) {
|
||||
debug(tr("Volume overlaps the end of input buffer"));
|
||||
return ERR_INVALID_VOLUME;
|
||||
}
|
||||
|
||||
// Check volume revision and alignment
|
||||
UINT32 alignment;
|
||||
if (volumeHeader->Revision == 1) {
|
||||
// Aquire alignment bits
|
||||
bool alignmentCap = volumeHeader->Attributes && EFI_FVB_ALIGNMENT_CAP;
|
||||
bool alignment2 = volumeHeader->Attributes && EFI_FVB_ALIGNMENT_2;
|
||||
bool alignment4 = volumeHeader->Attributes && EFI_FVB_ALIGNMENT_4;
|
||||
bool alignment8 = volumeHeader->Attributes && EFI_FVB_ALIGNMENT_8;
|
||||
bool alignment16 = volumeHeader->Attributes && EFI_FVB_ALIGNMENT_16;
|
||||
bool alignment32 = volumeHeader->Attributes && EFI_FVB_ALIGNMENT_32;
|
||||
bool alignment64 = volumeHeader->Attributes && EFI_FVB_ALIGNMENT_64;
|
||||
bool alignment128 = volumeHeader->Attributes && EFI_FVB_ALIGNMENT_128;
|
||||
bool alignment256 = volumeHeader->Attributes && EFI_FVB_ALIGNMENT_256;
|
||||
bool alignment512 = volumeHeader->Attributes && EFI_FVB_ALIGNMENT_512;
|
||||
bool alignment1k = volumeHeader->Attributes && EFI_FVB_ALIGNMENT_1K;
|
||||
bool alignment2k = volumeHeader->Attributes && EFI_FVB_ALIGNMENT_2K;
|
||||
bool alignment4k = volumeHeader->Attributes && EFI_FVB_ALIGNMENT_4K;
|
||||
bool alignment8k = volumeHeader->Attributes && EFI_FVB_ALIGNMENT_8K;
|
||||
bool alignment16k = volumeHeader->Attributes && EFI_FVB_ALIGNMENT_16K;
|
||||
bool alignment32k = volumeHeader->Attributes && EFI_FVB_ALIGNMENT_32K;
|
||||
bool alignment64k = volumeHeader->Attributes && EFI_FVB_ALIGNMENT_64K;
|
||||
|
||||
// Check alignment setup
|
||||
if (!alignmentCap &&
|
||||
( alignment2 || alignment4 || alignment8 || alignment16
|
||||
|| alignment32 || alignment64 || alignment128 || alignment256
|
||||
|| alignment512 || alignment1k || alignment2k || alignment4k
|
||||
|| alignment8k || alignment16k || alignment32k || alignment64k))
|
||||
debug("Incompatible revision 1 volume alignment setup");
|
||||
|
||||
// Assume that smaller alignment value consumes greater
|
||||
alignment = 0x01;
|
||||
if (alignment2)
|
||||
alignment = 0x02;
|
||||
else if (alignment4)
|
||||
alignment = 0x04;
|
||||
else if (alignment8)
|
||||
alignment = 0x08;
|
||||
else if (alignment16)
|
||||
alignment = 0x10;
|
||||
else if (alignment32)
|
||||
alignment = 0x20;
|
||||
else if (alignment64)
|
||||
alignment = 0x40;
|
||||
else if (alignment128)
|
||||
alignment = 0x80;
|
||||
else if (alignment256)
|
||||
alignment = 0x100;
|
||||
else if (alignment512)
|
||||
alignment = 0x200;
|
||||
else if (alignment1k)
|
||||
alignment = 0x400;
|
||||
else if (alignment2k)
|
||||
alignment = 0x800;
|
||||
else if (alignment4k)
|
||||
alignment = 0x1000;
|
||||
else if (alignment8k)
|
||||
alignment = 0x2000;
|
||||
else if (alignment16k)
|
||||
alignment = 0x4000;
|
||||
else if (alignment32k)
|
||||
alignment = 0x8000;
|
||||
else if (alignment64k)
|
||||
alignment = 0x10000;
|
||||
|
||||
// Check alignment
|
||||
if (volumeIndex % alignment) {
|
||||
debug(tr("Unaligned revision 1 volume"));
|
||||
}
|
||||
}
|
||||
else if (volumeHeader->Revision == 2) {
|
||||
// Aquire alignment
|
||||
alignment = pow(2, (volumeHeader->Attributes & EFI_FVB2_ALIGNMENT) >> 16);
|
||||
|
||||
// Check alignment
|
||||
if (volumeIndex % alignment) {
|
||||
debug(tr("Unaligned revision 2 volume"));
|
||||
}
|
||||
}
|
||||
else
|
||||
debug(tr("Unknown volume revision (%1)").arg(volumeHeader->Revision));
|
||||
|
||||
// Check filesystem GUID to be known
|
||||
// Do not parse volume with unknown FFS, because parsing will fail
|
||||
bool parseCurrentVolume = true;
|
||||
// FFS GUID v1
|
||||
if (QByteArray((const char*) &volumeHeader->FileSystemGuid, sizeof(EFI_GUID)) == EFI_FIRMWARE_FILE_SYSTEM_GUID) {
|
||||
// Code can be added here
|
||||
}
|
||||
// FFS GUID v2
|
||||
else if (QByteArray((const char*) &volumeHeader->FileSystemGuid, sizeof(EFI_GUID)) == EFI_FIRMWARE_FILE_SYSTEM2_GUID) {
|
||||
// Code can be added here
|
||||
}
|
||||
// Other GUID
|
||||
else {
|
||||
//info = info.append(tr("File system: unknown\n"));
|
||||
debug(tr("Unknown file system (%1)").arg(guidToQString(volumeHeader->FileSystemGuid)));
|
||||
parseCurrentVolume = false;
|
||||
}
|
||||
|
||||
// Check attributes
|
||||
// Determine erase polarity
|
||||
bool erasePolarity = volumeHeader->Attributes & EFI_FVB_ERASE_POLARITY;
|
||||
|
||||
// Check header checksum by recalculating it
|
||||
if (!calculateChecksum16((UINT8*) volumeHeader, volumeHeader->HeaderLength)) {
|
||||
debug(tr("Volume header checksum is invalid"));
|
||||
}
|
||||
|
||||
// Check for presence of extended header, only if header revision is not 1
|
||||
UINT32 headerSize;
|
||||
if (volumeHeader->Revision > 1 && volumeHeader->ExtHeaderOffset) {
|
||||
EFI_FIRMWARE_VOLUME_EXT_HEADER* extendedHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER*) ((UINT8*) volumeHeader + volumeHeader->ExtHeaderOffset);
|
||||
headerSize = volumeHeader->ExtHeaderOffset + extendedHeader->ExtHeaderSize;
|
||||
} else {
|
||||
headerSize = volumeHeader->HeaderLength;
|
||||
}
|
||||
|
||||
// Adding tree item
|
||||
QByteArray header = bios.mid(volumeIndex, headerSize);
|
||||
QByteArray body = bios.mid(volumeIndex + headerSize, volumeHeader->FvLength - headerSize);
|
||||
QModelIndex index = addTreeItem(ItemTypes::VolumeItem, 0, header, body, parent);
|
||||
|
||||
// Parse volume
|
||||
if (parseCurrentVolume) {
|
||||
UINT32 result = parseVolume(bios.mid(volumeIndex + headerSize, volumeHeader->FvLength - headerSize), headerSize, volumeHeader->Revision, erasePolarity, index);
|
||||
if (result)
|
||||
debug(tr("Volume parsing failed (%1)").arg(result));
|
||||
}
|
||||
}
|
||||
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
|
||||
INT32 UEFITool::getNextVolumeIndex(const QByteArray & bios, INT32 volumeIndex)
|
||||
{
|
||||
if (volumeIndex < 0)
|
||||
return -1;
|
||||
|
||||
INT32 nextIndex = bios.indexOf(EFI_FV_SIGNATURE, volumeIndex);
|
||||
if (nextIndex < EFI_FV_SIGNATURE_OFFSET) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return nextIndex - EFI_FV_SIGNATURE_OFFSET;
|
||||
}
|
||||
|
||||
UINT32 UEFITool::getVolumeSize(const QByteArray & bios, INT32 volumeIndex)
|
||||
{
|
||||
// Populate volume header
|
||||
EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (EFI_FIRMWARE_VOLUME_HEADER*) (bios.constData() + volumeIndex);
|
||||
|
||||
// Check volume signature
|
||||
if (QByteArray((const char*) &volumeHeader->Signature, sizeof(volumeHeader->Signature)) != EFI_FV_SIGNATURE)
|
||||
return 0;
|
||||
return volumeHeader->FvLength;
|
||||
}
|
||||
|
||||
UINT8 UEFITool::parseVolume(const QByteArray & volume, UINT32 volumeBase, UINT8 revision, bool erasePolarity, QModelIndex & parent)
|
||||
{
|
||||
// Construct empty byte based on erasePolarity value
|
||||
// Native char type is used because QByteArray.count() takes it
|
||||
char empty = erasePolarity ? '\xFF' : '\x00';
|
||||
|
||||
// Search for and parse all files
|
||||
INT32 fileIndex = 0;
|
||||
while (fileIndex >= 0) {
|
||||
EFI_FFS_FILE_HEADER* fileHeader = (EFI_FFS_FILE_HEADER*) (volume.constData() + fileIndex);
|
||||
QByteArray file = volume.mid(fileIndex, uint24ToUint32(fileHeader->Size));
|
||||
QByteArray header = file.left(sizeof(EFI_FFS_FILE_HEADER));
|
||||
|
||||
// We are at empty space in the end of volume
|
||||
if (header.count(empty) == header.size()) {
|
||||
QByteArray body = volume.right(volume.size() - fileIndex);
|
||||
addTreeItem(ItemTypes::PaddingItem, 0, QByteArray(), body, parent);
|
||||
break;
|
||||
}
|
||||
|
||||
// Check header checksum
|
||||
QByteArray tempHeader = header;
|
||||
EFI_FFS_FILE_HEADER* tempFileHeader = (EFI_FFS_FILE_HEADER*) (tempHeader.data());
|
||||
tempFileHeader->IntegrityCheck.Checksum.Header = 0;
|
||||
tempFileHeader->IntegrityCheck.Checksum.File = 0;
|
||||
UINT8 calculated = calculateChecksum8((UINT8*) tempFileHeader, sizeof(EFI_FFS_FILE_HEADER) - 1);
|
||||
if (fileHeader->IntegrityCheck.Checksum.Header != calculated)
|
||||
{
|
||||
debug(tr("%1: stored header checksum %2 differs from calculated %3")
|
||||
.arg(guidToQString(fileHeader->Name))
|
||||
.arg(fileHeader->IntegrityCheck.Checksum.Header, 2, 16, QChar('0'))
|
||||
.arg(calculated, 2, 16, QChar('0')));
|
||||
}
|
||||
|
||||
// Check data checksum, if no tail was found
|
||||
// Data checksum must be calculated
|
||||
if (fileHeader->Attributes & FFS_ATTRIB_CHECKSUM) {
|
||||
UINT32 bufferSize = file.size() - sizeof(EFI_FFS_FILE_HEADER);
|
||||
// Exclude file tail from data checksum calculation
|
||||
if(revision == 1 && fileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT)
|
||||
bufferSize -= sizeof(UINT16);
|
||||
calculated = calculateChecksum8((UINT8*)(file.constData() + sizeof(EFI_FFS_FILE_HEADER)), bufferSize);
|
||||
if (fileHeader->IntegrityCheck.Checksum.File != calculated) {
|
||||
debug(tr("%1: stored data checksum %2 differs from calculated %3")
|
||||
.arg(guidToQString(fileHeader->Name))
|
||||
.arg(fileHeader->IntegrityCheck.Checksum.File, 2, 16, QChar('0'))
|
||||
.arg(calculated, 2, 16, QChar('0')));
|
||||
}
|
||||
}
|
||||
// Data checksum must be one of predefined values
|
||||
else {
|
||||
if (fileHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM &&fileHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM2) {
|
||||
debug(tr("%1: stored data checksum %2 differs from standard value")
|
||||
.arg(guidToQString(fileHeader->Name))
|
||||
.arg(fileHeader->IntegrityCheck.Checksum.File, 2, 16, QChar('0')));
|
||||
}
|
||||
}
|
||||
|
||||
// Check file alignment
|
||||
UINT8 alignmentPower = ffsAlignmentTable[(fileHeader->Attributes & FFS_ATTRIB_DATA_ALIGNMENT) >> 3];
|
||||
UINT32 alignment = pow(2, alignmentPower);
|
||||
if ((volumeBase + fileIndex + sizeof(EFI_FFS_FILE_HEADER)) % alignment) {
|
||||
debug(tr("%1: unaligned file").arg(guidToQString(fileHeader->Name)));
|
||||
}
|
||||
|
||||
// Get file body
|
||||
QByteArray body = file.right(file.size() - sizeof(EFI_FFS_FILE_HEADER));
|
||||
// For files in Revision 1 volumes, check for file tail presence
|
||||
if (revision == 1 && fileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT)
|
||||
{
|
||||
//Check file tail;
|
||||
UINT16* tail = (UINT16*) body.right(sizeof(UINT16)).constData();
|
||||
if (!fileHeader->IntegrityCheck.TailReference == *tail)
|
||||
debug(tr("%1: file tail value %2 is not a bitwise not of %3 stored in file header")
|
||||
.arg(guidToQString(fileHeader->Name))
|
||||
.arg(*tail, 4, 16, QChar('0'))
|
||||
.arg(fileHeader->IntegrityCheck.TailReference, 4, 16, QChar('0')));
|
||||
|
||||
// Remove tail from file body
|
||||
body = body.left(body.size() - sizeof(UINT16));
|
||||
}
|
||||
|
||||
// Parse current file by default
|
||||
bool parseCurrentFile = true;
|
||||
// Raw files can hide volumes inside them
|
||||
// So try to parse them as bios space
|
||||
bool parseAsBios = false;
|
||||
|
||||
// Check file type
|
||||
//!TODO: add more file specific checks
|
||||
switch (fileHeader->Type)
|
||||
{
|
||||
case EFI_FV_FILETYPE_ALL:
|
||||
parseAsBios = true;
|
||||
break;
|
||||
case EFI_FV_FILETYPE_RAW:
|
||||
parseAsBios = true;
|
||||
break;
|
||||
case EFI_FV_FILETYPE_FREEFORM:
|
||||
break;
|
||||
case EFI_FV_FILETYPE_SECURITY_CORE:
|
||||
break;
|
||||
case EFI_FV_FILETYPE_PEI_CORE:
|
||||
break;
|
||||
case EFI_FV_FILETYPE_DXE_CORE:
|
||||
break;
|
||||
case EFI_FV_FILETYPE_PEIM:
|
||||
break;
|
||||
case EFI_FV_FILETYPE_DRIVER:
|
||||
break;
|
||||
case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER:
|
||||
break;
|
||||
case EFI_FV_FILETYPE_APPLICATION:
|
||||
break;
|
||||
case EFI_FV_FILETYPE_SMM:
|
||||
break;
|
||||
case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE:
|
||||
break;
|
||||
case EFI_FV_FILETYPE_COMBINED_SMM_DXE:
|
||||
break;
|
||||
case EFI_FV_FILETYPE_SMM_CORE:
|
||||
break;
|
||||
case EFI_FV_FILETYPE_PAD:
|
||||
parseCurrentFile = false;
|
||||
break;
|
||||
default:
|
||||
parseCurrentFile = false;
|
||||
debug(tr("Unknown file type (%1)").arg(fileHeader->Type, 2, 16, QChar('0')));
|
||||
};
|
||||
|
||||
// Check for empty file
|
||||
if (body.count(empty) == body.size())
|
||||
{
|
||||
// No need to parse empty files
|
||||
parseCurrentFile = false;
|
||||
}
|
||||
|
||||
// Add tree item
|
||||
QModelIndex index = addTreeItem(ItemTypes::FileItem, fileHeader->Type, header, body, parent);
|
||||
|
||||
// Parse file
|
||||
if (parseCurrentFile) {
|
||||
if (parseAsBios) {
|
||||
UINT32 result = parseBios(body, index);
|
||||
if (result && result != ERR_VOLUMES_NOT_FOUND)
|
||||
debug(tr("Parse file as BIOS failed (%1)").arg(result));
|
||||
}
|
||||
else {
|
||||
UINT32 result = parseFile(body, revision, erasePolarity, index);
|
||||
if (result)
|
||||
debug(tr("Parse file as FFS failed (%1)").arg(result));
|
||||
}
|
||||
}
|
||||
|
||||
// Move to next file
|
||||
fileIndex += file.size();
|
||||
fileIndex = ALIGN8(fileIndex);
|
||||
|
||||
// Exit from loop if no files left
|
||||
if (fileIndex >= volume.size())
|
||||
fileIndex = -1;
|
||||
}
|
||||
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
|
||||
UINT8 UEFITool::parseFile(const QByteArray & file, UINT8 revision, bool erasePolarity, QModelIndex & parent)
|
||||
{
|
||||
// Search for and parse all sections
|
||||
INT32 sectionIndex = 0;
|
||||
while(sectionIndex >= 0)
|
||||
{
|
||||
EFI_COMMON_SECTION_HEADER* sectionHeader = (EFI_COMMON_SECTION_HEADER*) (file.constData() + sectionIndex);
|
||||
UINT32 sectionSize = uint24ToUint32(sectionHeader->Size);
|
||||
|
||||
// This declarations must be here because of the nature of switch statement
|
||||
EFI_COMPRESSION_SECTION* compressedSectionHeader;
|
||||
EFI_GUID_DEFINED_SECTION* guidDefinedSectionHeader;
|
||||
QByteArray header;
|
||||
QByteArray body;
|
||||
UINT32 decompressedSize;
|
||||
UINT32 scratchSize;
|
||||
UINT8* decompressed;
|
||||
UINT8* scratch;
|
||||
VOID* data;
|
||||
UINT32 dataSize;
|
||||
QModelIndex index;
|
||||
UINT32 result;
|
||||
bool lzmaHeaderFound;
|
||||
|
||||
switch (sectionHeader->Type)
|
||||
{
|
||||
// Encapsulated sections
|
||||
case EFI_SECTION_COMPRESSION:
|
||||
compressedSectionHeader = (EFI_COMPRESSION_SECTION*) sectionHeader;
|
||||
header = file.mid(sectionIndex, sizeof(EFI_COMPRESSION_SECTION));
|
||||
|
||||
// Try to decompress this section
|
||||
switch (compressedSectionHeader->CompressionType)
|
||||
{
|
||||
case EFI_NOT_COMPRESSED:
|
||||
body = file.mid(sectionIndex + sizeof(EFI_COMPRESSION_SECTION), compressedSectionHeader->UncompressedLength);
|
||||
index = addTreeItem(ItemTypes::SectionItem, SectionSubtypes::CompressionSection, header, body, parent);
|
||||
// Parse stored file
|
||||
result = parseFile(body, revision, erasePolarity, index);
|
||||
if (result)
|
||||
debug(tr("Stored section can not be parsed as file (%1)").arg(result));
|
||||
break;
|
||||
case EFI_STANDARD_COMPRESSION:
|
||||
//Must be Tiano for all revisions, needs checking
|
||||
body = file.mid(sectionIndex + sizeof(EFI_COMPRESSION_SECTION), sectionSize - sizeof(EFI_COMPRESSION_SECTION));
|
||||
index = addTreeItem(ItemTypes::SectionItem, sectionHeader->Type, header, body, parent);
|
||||
|
||||
// Get buffer sizes
|
||||
data = (VOID*) (file.constData() + sectionIndex + sizeof(EFI_COMPRESSION_SECTION));
|
||||
dataSize = uint24ToUint32(sectionHeader->Size) - sizeof(EFI_COMPRESSION_SECTION);
|
||||
if (TianoGetInfo(data, dataSize, &decompressedSize, &scratchSize) != ERR_SUCCESS
|
||||
|| decompressedSize != compressedSectionHeader->UncompressedLength)
|
||||
debug(tr("TianoGetInfo failed"));
|
||||
else {
|
||||
decompressed = new UINT8[decompressedSize];
|
||||
scratch = new UINT8[scratchSize];
|
||||
// Decompress section data
|
||||
if (TianoDecompress(data, dataSize, decompressed, decompressedSize, scratch, scratchSize) != ERR_SUCCESS)
|
||||
debug(tr("TianoDecompress failed"));
|
||||
else
|
||||
{
|
||||
body = QByteArray::fromRawData((const char*) decompressed, decompressedSize);
|
||||
// Parse stored file
|
||||
result = parseFile(body, revision, erasePolarity, index);
|
||||
if (result)
|
||||
debug(tr("Compressed section with Tiano compression can not be parsed as file (%1)").arg(result));
|
||||
}
|
||||
|
||||
delete[] decompressed;
|
||||
delete[] scratch;
|
||||
}
|
||||
break;
|
||||
case EFI_CUSTOMIZED_COMPRESSION:
|
||||
body = file.mid(sectionIndex + sizeof(EFI_COMPRESSION_SECTION), sectionSize - sizeof(EFI_COMPRESSION_SECTION));
|
||||
index = addTreeItem(ItemTypes::SectionItem, sectionHeader->Type, header, body, parent);
|
||||
|
||||
// Get buffer sizes
|
||||
data = (VOID*) (file.constData() + sectionIndex + sizeof(EFI_COMPRESSION_SECTION));
|
||||
dataSize = uint24ToUint32(sectionHeader->Size) - sizeof(EFI_COMPRESSION_SECTION);
|
||||
if (LzmaGetInfo(data, dataSize, &decompressedSize) != ERR_SUCCESS
|
||||
|| decompressedSize != compressedSectionHeader->UncompressedLength)
|
||||
{
|
||||
// Shitty file with some data between COMPRESSED_SECTION_HEADER and LZMA_HEADER
|
||||
// Search for LZMA header in body
|
||||
// Header structure: UINT8 LzmaProperties | UINT32 DictionarySize | UINT64 DecompressedSize
|
||||
// We can't determine first two fiels here, but Decompressed size is known, so search for it
|
||||
INT32 lzmaHeaderIndex = body.indexOf(QByteArray((const char*)&compressedSectionHeader->UncompressedLength,
|
||||
sizeof(compressedSectionHeader->UncompressedLength)).append('\x00').append('\x00').append('\x00').append('\x00'));
|
||||
lzmaHeaderIndex -= LZMA_PROPS_SIZE;
|
||||
// LZMA header not found
|
||||
if (lzmaHeaderIndex < 0)
|
||||
{
|
||||
lzmaHeaderFound = false;
|
||||
debug(tr("Lzma header not found"));
|
||||
}
|
||||
// LZMA header found
|
||||
else if (lzmaHeaderIndex) {
|
||||
data = (VOID*) (file.constData() + sectionIndex + sizeof(EFI_COMPRESSION_SECTION) + lzmaHeaderIndex);
|
||||
dataSize = uint24ToUint32(sectionHeader->Size) - sizeof(EFI_COMPRESSION_SECTION) - lzmaHeaderIndex;
|
||||
// Get buffer sizes again
|
||||
if (LzmaGetInfo(data, dataSize, &decompressedSize) != ERR_SUCCESS
|
||||
|| decompressedSize != compressedSectionHeader->UncompressedLength)
|
||||
{
|
||||
debug(tr("LzmaGetInfo failed on LZMA header"));
|
||||
lzmaHeaderFound = false;
|
||||
}
|
||||
else
|
||||
debug(tr("Padding of size %1 between CompressedSectionHeader and LzmaHeader")
|
||||
.arg(lzmaHeaderIndex));
|
||||
}
|
||||
lzmaHeaderFound = true;
|
||||
}
|
||||
else
|
||||
lzmaHeaderFound = true;
|
||||
// Decompress if header is found
|
||||
if (lzmaHeaderFound) {
|
||||
decompressed = new UINT8[decompressedSize];
|
||||
// Decompress section data
|
||||
if (LzmaDecompress(data, dataSize, decompressed) != ERR_SUCCESS)
|
||||
debug(tr("LzmaDecompress failed"));
|
||||
else
|
||||
{
|
||||
body = QByteArray::fromRawData((const char*) decompressed, decompressedSize);
|
||||
// Parse stored file
|
||||
result = parseFile(body, revision, erasePolarity, index);
|
||||
if (result)
|
||||
debug(tr("Compressed section with LZMA compression can not be parsed as file (%1)").arg(result));
|
||||
}
|
||||
|
||||
delete[] decompressed;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
body = file.mid(sectionIndex + sizeof(EFI_COMPRESSION_SECTION), sectionSize - sizeof(EFI_COMPRESSION_SECTION));
|
||||
index = addTreeItem(ItemTypes::SectionItem, sectionHeader->Type, header, body, parent);
|
||||
debug(tr("Compressed section with unknown compression type found (%1)").arg(compressedSectionHeader->CompressionType));
|
||||
}
|
||||
|
||||
break;
|
||||
case EFI_SECTION_GUID_DEFINED:
|
||||
header = file.mid(sectionIndex, sizeof(EFI_GUID_DEFINED_SECTION));
|
||||
body = file.mid(sectionIndex + sizeof(EFI_GUID_DEFINED_SECTION), sectionSize - sizeof(EFI_GUID_DEFINED_SECTION));
|
||||
index = addTreeItem(ItemTypes::SectionItem, sectionHeader->Type, header, body, parent);
|
||||
// Parse section body as file
|
||||
guidDefinedSectionHeader = (EFI_GUID_DEFINED_SECTION*) (header.constData());
|
||||
body = file.mid(sectionIndex + guidDefinedSectionHeader->DataOffset, sectionSize - guidDefinedSectionHeader->DataOffset);
|
||||
result = parseFile(body, revision, erasePolarity, index);
|
||||
if (result)
|
||||
debug(tr("GUID defined section body can not be parsed as file (%1)").arg(result));
|
||||
break;
|
||||
case EFI_SECTION_DISPOSABLE:
|
||||
header = file.mid(sectionIndex, sizeof(EFI_DISPOSABLE_SECTION));
|
||||
body = file.mid(sectionIndex + sizeof(EFI_DISPOSABLE_SECTION), sectionSize - sizeof(EFI_DISPOSABLE_SECTION));
|
||||
index = addTreeItem(ItemTypes::SectionItem, sectionHeader->Type, header, body, parent);
|
||||
break;
|
||||
// Leaf sections
|
||||
case EFI_SECTION_PE32:
|
||||
header = file.mid(sectionIndex, sizeof(EFI_PE32_SECTION));
|
||||
body = file.mid(sectionIndex + sizeof(EFI_PE32_SECTION), sectionSize - sizeof(EFI_PE32_SECTION));
|
||||
index = addTreeItem(ItemTypes::SectionItem, sectionHeader->Type, header, body, parent);
|
||||
break;
|
||||
case EFI_SECTION_PIC:
|
||||
header = file.mid(sectionIndex, sizeof(EFI_PIC_SECTION));
|
||||
body = file.mid(sectionIndex + sizeof(EFI_PIC_SECTION), sectionSize - sizeof(EFI_PIC_SECTION));
|
||||
index = addTreeItem(ItemTypes::SectionItem, sectionHeader->Type, header, body, parent);
|
||||
break;
|
||||
case EFI_SECTION_TE:
|
||||
header = file.mid(sectionIndex, sizeof(EFI_TE_SECTION));
|
||||
body = file.mid(sectionIndex + sizeof(EFI_TE_SECTION), sectionSize - sizeof(EFI_TE_SECTION));
|
||||
index = addTreeItem(ItemTypes::SectionItem, sectionHeader->Type, header, body, parent);
|
||||
break;
|
||||
case EFI_SECTION_VERSION:
|
||||
header = file.mid(sectionIndex, sizeof(EFI_VERSION_SECTION));
|
||||
body = file.mid(sectionIndex + sizeof(EFI_VERSION_SECTION), sectionSize - sizeof(EFI_VERSION_SECTION));
|
||||
index = addTreeItem(ItemTypes::SectionItem, sectionHeader->Type, header, body, parent);
|
||||
break;
|
||||
case EFI_SECTION_USER_INTERFACE:
|
||||
header = file.mid(sectionIndex, sizeof(EFI_USER_INTERFACE_SECTION));
|
||||
body = file.mid(sectionIndex + sizeof(EFI_USER_INTERFACE_SECTION), sectionSize - sizeof(EFI_USER_INTERFACE_SECTION));
|
||||
index = addTreeItem(ItemTypes::SectionItem, sectionHeader->Type, header, body, parent);
|
||||
break;
|
||||
case EFI_SECTION_COMPATIBILITY16:
|
||||
header = file.mid(sectionIndex, sizeof(EFI_COMPATIBILITY16_SECTION));
|
||||
body = file.mid(sectionIndex + sizeof(EFI_COMPATIBILITY16_SECTION), sectionSize - sizeof(EFI_COMPATIBILITY16_SECTION));
|
||||
index = addTreeItem(ItemTypes::SectionItem, sectionHeader->Type, header, body, parent);
|
||||
break;
|
||||
case EFI_SECTION_FIRMWARE_VOLUME_IMAGE:
|
||||
header = file.mid(sectionIndex, sizeof(EFI_FIRMWARE_VOLUME_IMAGE_SECTION));
|
||||
body = file.mid(sectionIndex + sizeof(EFI_FIRMWARE_VOLUME_IMAGE_SECTION), sectionSize - sizeof(EFI_FIRMWARE_VOLUME_IMAGE_SECTION));
|
||||
index = addTreeItem(ItemTypes::SectionItem, sectionHeader->Type, header, body, parent);
|
||||
// Parse section body as BIOS space
|
||||
result = parseBios(body, index);
|
||||
if (result && result != ERR_VOLUMES_NOT_FOUND)
|
||||
debug(tr("Firmware volume image can not be parsed (%1)").arg(result));
|
||||
break;
|
||||
case EFI_SECTION_FREEFORM_SUBTYPE_GUID:
|
||||
header = file.mid(sectionIndex, sizeof(EFI_FREEFORM_SUBTYPE_GUID_SECTION));
|
||||
body = file.mid(sectionIndex + sizeof(EFI_FREEFORM_SUBTYPE_GUID_SECTION), sectionSize - sizeof(EFI_FREEFORM_SUBTYPE_GUID_SECTION));
|
||||
index = addTreeItem(ItemTypes::SectionItem, sectionHeader->Type, header, body, parent);
|
||||
break;
|
||||
case EFI_SECTION_RAW:
|
||||
header = file.mid(sectionIndex, sizeof(EFI_RAW_SECTION));
|
||||
body = file.mid(sectionIndex + sizeof(EFI_RAW_SECTION), sectionSize - sizeof(EFI_RAW_SECTION));
|
||||
index = addTreeItem(ItemTypes::SectionItem, sectionHeader->Type, header, body, parent);
|
||||
// Parse section body as BIOS space
|
||||
result = parseBios(body, index);
|
||||
if (result && result != ERR_VOLUMES_NOT_FOUND)
|
||||
debug(tr("Raw section can not be parsed as BIOS (%1)").arg(result));
|
||||
break;
|
||||
break;
|
||||
case EFI_SECTION_DXE_DEPEX:
|
||||
header = file.mid(sectionIndex, sizeof(EFI_DXE_DEPEX_SECTION));
|
||||
body = file.mid(sectionIndex + sizeof(EFI_DXE_DEPEX_SECTION), sectionSize - sizeof(EFI_DXE_DEPEX_SECTION));
|
||||
index = addTreeItem(ItemTypes::SectionItem, sectionHeader->Type, header, body, parent);
|
||||
break;
|
||||
case EFI_SECTION_PEI_DEPEX:
|
||||
header = file.mid(sectionIndex, sizeof(EFI_PEI_DEPEX_SECTION));
|
||||
body = file.mid(sectionIndex + sizeof(EFI_PEI_DEPEX_SECTION), sectionSize - sizeof(EFI_PEI_DEPEX_SECTION));
|
||||
index = addTreeItem(ItemTypes::SectionItem, sectionHeader->Type, header, body, parent);
|
||||
break;
|
||||
case EFI_SECTION_SMM_DEPEX:
|
||||
header = file.mid(sectionIndex, sizeof(EFI_SMM_DEPEX_SECTION));
|
||||
body = file.mid(sectionIndex + sizeof(EFI_SMM_DEPEX_SECTION), sectionSize - sizeof(EFI_SMM_DEPEX_SECTION));
|
||||
index = addTreeItem(ItemTypes::SectionItem, sectionHeader->Type, header, body, parent);
|
||||
break;
|
||||
default:
|
||||
debug(tr("Section with unknown type (%1)").arg(sectionHeader->Type, 2, 16, QChar('0')));
|
||||
header = file.mid(sectionIndex, sizeof(EFI_COMMON_SECTION_HEADER));
|
||||
body = file.mid(sectionIndex + sizeof(EFI_COMMON_SECTION_HEADER), sectionSize - sizeof(EFI_COMMON_SECTION_HEADER));
|
||||
index = addTreeItem(ItemTypes::SectionItem, sectionHeader->Type, header, body, parent);
|
||||
}
|
||||
|
||||
// Move to next section
|
||||
sectionIndex += uint24ToUint32(sectionHeader->Size);
|
||||
sectionIndex = ALIGN4(sectionIndex);
|
||||
|
||||
// Exit from loop if no sections left
|
||||
if (sectionIndex >= file.size())
|
||||
sectionIndex = -1;
|
||||
}
|
||||
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
|
84
uefitool.h
Normal file
84
uefitool.h
Normal file
@ -0,0 +1,84 @@
|
||||
/* uefitool.h
|
||||
|
||||
Copyright (c) 2013, Nikolaj Schlej. All rights reserved.
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __UEFITOOL_H__
|
||||
#define __UEFITOOL_H__
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QByteArray>
|
||||
#include <QDragEnterEvent>
|
||||
#include <QDropEvent>
|
||||
#include <QFile>
|
||||
#include <QFileDialog>
|
||||
#include <QFileInfo>
|
||||
#include <QMessageBox>
|
||||
#include <QMimeData>
|
||||
#include <QString>
|
||||
#include <QUrl>
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "treemodel.h"
|
||||
|
||||
#include "basetypes.h"
|
||||
#include "descriptor.h"
|
||||
#include "ffs.h"
|
||||
#include "Tiano\EfiTianoCompress.h"
|
||||
#include "Tiano\EfiTianoDecompress.h"
|
||||
#include "LZMA\LzmaCompress.h"
|
||||
#include "LZMA\LzmaDecompress.h"
|
||||
|
||||
namespace Ui {
|
||||
class UEFITool;
|
||||
}
|
||||
|
||||
class UEFITool : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit UEFITool(QWidget *parent = 0);
|
||||
~UEFITool();
|
||||
|
||||
void openImageFile(QString path);
|
||||
|
||||
private slots:
|
||||
void init();
|
||||
void openImageFile();
|
||||
//void saveImageFile();
|
||||
void populateUi(const QModelIndex ¤t/*, const QModelIndex &previous*/);
|
||||
void resizeTreeViewColums(/*const QModelIndex &index*/);
|
||||
void saveAll();
|
||||
void saveBody();
|
||||
|
||||
private:
|
||||
Ui::UEFITool * ui;
|
||||
TreeModel * treeModel;
|
||||
QModelIndex currentIndex;
|
||||
|
||||
void debug(const QString & text);
|
||||
void dragEnterEvent(QDragEnterEvent* event);
|
||||
void dropEvent(QDropEvent* event);
|
||||
QModelIndex addTreeItem(UINT8 type, UINT8 subtype, const QByteArray & header = QByteArray(), const QByteArray & body = QByteArray(),
|
||||
const QModelIndex & parent = QModelIndex());
|
||||
|
||||
UINT8 parseInputFile(const QByteArray & buffer);
|
||||
UINT8* parseRegion(const QByteArray & flashImage, UINT8 regionSubtype, const UINT16 regionBase, const UINT16 regionLimit, QModelIndex & index);
|
||||
UINT8 parseBios(const QByteArray & bios, QModelIndex & parent = QModelIndex());
|
||||
INT32 getNextVolumeIndex(const QByteArray & bios, INT32 volumeIndex = 0);
|
||||
UINT32 getVolumeSize(const QByteArray & bios, INT32 volumeIndex);
|
||||
UINT8 parseVolume(const QByteArray & volume, UINT32 volumeBase, UINT8 revision, bool erasePolarity, QModelIndex & parent = QModelIndex());
|
||||
UINT8 parseFile(const QByteArray & file, UINT8 revision, bool erasePolarity, QModelIndex & parent = QModelIndex());
|
||||
};
|
||||
|
||||
#endif
|
BIN
uefitool.icns
Normal file
BIN
uefitool.icns
Normal file
Binary file not shown.
BIN
uefitool.ico
Normal file
BIN
uefitool.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 31 KiB |
34
uefitool.pro
Normal file
34
uefitool.pro
Normal file
@ -0,0 +1,34 @@
|
||||
QT += core gui
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||
|
||||
TARGET = UEFITool
|
||||
TEMPLATE = app
|
||||
|
||||
SOURCES += main.cpp \
|
||||
uefitool.cpp \
|
||||
descriptor.cpp \
|
||||
ffs.cpp \
|
||||
treeitem.cpp \
|
||||
treemodel.cpp \
|
||||
LZMA/LzmaCompress.c \
|
||||
LZMA/LzmaDecompress.c \
|
||||
LZMA/Sdk/C/LzFind.c \
|
||||
LZMA/Sdk/C/LzmaDec.c \
|
||||
LZMA/Sdk/C/LzmaEnc.c \
|
||||
Tiano/EfiTianoDecompress.c \
|
||||
Tiano/EfiCompress.c \
|
||||
Tiano/TianoCompress.c
|
||||
HEADERS += uefitool.h \
|
||||
basetypes.h \
|
||||
descriptor.h \
|
||||
ffs.h \
|
||||
treeitem.h \
|
||||
treemodel.h \
|
||||
LZMA/LzmaCompress.h \
|
||||
LZMA/LzmaDecompress.h \
|
||||
Tiano/EfiTianoDecompress.h \
|
||||
Tiano/EfiTianoCompress.h
|
||||
FORMS += uefitool.ui
|
||||
RC_FILE = uefitool.rc
|
||||
|
||||
ICON = uefitool.icns
|
1
uefitool.rc
Normal file
1
uefitool.rc
Normal file
@ -0,0 +1 @@
|
||||
IDI_ICON1 ICON DISCARDABLE "uefitool.ico"
|
211
uefitool.ui
Normal file
211
uefitool.ui
Normal file
@ -0,0 +1,211 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>UEFITool</class>
|
||||
<widget class="QMainWindow" name="UEFITool">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>900</width>
|
||||
<height>600</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="acceptDrops">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>UEFITool 0.2.0</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralWidget">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="1" column="0">
|
||||
<widget class="QGroupBox" name="structureGroupBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Structure</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QTreeView" name="structureTreeView">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Consolas</family>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="indentation">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="headerHidden">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="headerCascadingSectionResizes">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="headerDefaultSectionSize">
|
||||
<number>200</number>
|
||||
</attribute>
|
||||
<attribute name="headerStretchLastSection">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QGroupBox" name="infoGroupBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>216</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Information</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QPlainTextEdit" name="infoEdit">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Consolas</family>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="undoRedoEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="centerOnScroll">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="exportAllButton">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Export...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="exportBodyButton">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Export without header...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="debugGroupBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Debug</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPlainTextEdit" name="debugEdit">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>100</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="baseSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>50</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Consolas</family>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="undoRedoEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="centerOnScroll">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QPushButton" name="fromFileButton">
|
||||
<property name="text">
|
||||
<string>Open BIOS image file...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusBar"/>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
Loading…
Reference in New Issue
Block a user