-
Notifications
You must be signed in to change notification settings - Fork 47
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
zlib compression is used in some AMI-based firmwares for AMD CPUs. Implement the Compressor interface and unit-tests for it. Information about the ZLIB section header taken from UEFITool which added support in the A63 release.[^1][^2] [^1]: https://github.com/LongSoft/UEFITool/releases/tag/A63 [^2]: LongSoft/UEFITool@8d5659c92b08 Signed-off-by: Julian Prein <[email protected]>
- Loading branch information
Showing
4 changed files
with
99 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
// Copyright 2023 the LinuxBoot Authors. All rights reserved | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
package compression | ||
|
||
import ( | ||
"bytes" | ||
"compress/zlib" | ||
"encoding/binary" | ||
"errors" | ||
"io" | ||
) | ||
|
||
const ( | ||
zlibCompressionLevel = 9 | ||
zlibSectionHeaderSize = 256 | ||
zlibSizeOffset = 20 | ||
) | ||
|
||
// ZLIB implements Compressor and uses the zlib package from the standard | ||
// library | ||
type ZLIB struct{} | ||
|
||
// Name returns the type of compression employed. | ||
func (c *ZLIB) Name() string { | ||
return "ZLIB" | ||
} | ||
|
||
// Decode decodes a byte slice of ZLIB data. | ||
func (c *ZLIB) Decode(encodedData []byte) ([]byte, error) { | ||
if len(encodedData) < 256 { | ||
return nil, errors.New("Zlib.Decode: missing section header") | ||
} | ||
|
||
// Check size in ZLIB section header | ||
size := binary.LittleEndian.Uint32( | ||
encodedData[zlibSizeOffset : zlibSizeOffset+4], | ||
) | ||
if size != uint32(len(encodedData)-zlibSectionHeaderSize) { | ||
return nil, errors.New("ZLIB.Decode: size mismatch") | ||
} | ||
|
||
// Remove section header | ||
r, err := zlib.NewReader( | ||
bytes.NewBuffer(encodedData[zlibSectionHeaderSize:]), | ||
) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
decodedData, err := io.ReadAll(r) | ||
r.Close() | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return decodedData, nil | ||
} | ||
|
||
// Encode encodes a byte slice with ZLIB. | ||
func (c *ZLIB) Encode(decodedData []byte) ([]byte, error) { | ||
var encodedData bytes.Buffer | ||
|
||
w, err := zlib.NewWriterLevel(&encodedData, zlibCompressionLevel) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
_, err = w.Write(decodedData) | ||
w.Close() | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
// Add ZLIB section header containing the compressed size and zero padding. | ||
zlib_header := make([]byte, zlibSectionHeaderSize) | ||
binary.LittleEndian.PutUint32( | ||
zlib_header[zlibSizeOffset:], | ||
uint32(len(encodedData.Bytes())), | ||
) | ||
return append(zlib_header, encodedData.Bytes()[:]...), nil | ||
} |