Skip to content

Commit

Permalink
Add support for Ghidra 10.1
Browse files Browse the repository at this point in the history
Thanks to @dev747368 for some fixes.
  • Loading branch information
al3xtjames committed Dec 20, 2021
1 parent 95414ac commit fb77436
Show file tree
Hide file tree
Showing 47 changed files with 706 additions and 659 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ on:
workflow_dispatch:

env:
GHIDRA_VERSION: 10.0.4
GHIDRA_DATE: 20210928
GHIDRA_VERSION: 10.1
GHIDRA_DATE: 20211210

jobs:
build-macos:
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ This was accepted as a [coreboot project for GSoC 2019][2].
- Locates and defines global copies of UEFI table pointers (gBS/gRT/gST/etc)

## Building & Installation
JDK 11 (or newer) and Ghidra 9.1.0 (or newer) are required.
JDK 11 (or newer) and Ghidra 10.1 (or newer) are required.

Ghidra's standard Gradle build system is used. Set the `GHIDRA_INSTALL_DIR`
environment variable before building, or set it as a Gradle property (useful
Expand Down
2 changes: 1 addition & 1 deletion os/osx64/README.txt → os/linux_x86_64/README.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
The "os/osx64" directory is intended to hold macOS (OS X) native binaries
The "os/linux_x86_64" directory is intended to hold Linux native binaries
which this module is dependent upon. This directory may be eliminated for a specific
module if native binaries are not provided for the corresponding platform.
2 changes: 1 addition & 1 deletion os/linux64/README.txt → os/mac_x86_64/README.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
The "os/linux64" directory is intended to hold Linux native binaries
The "os/mac_x86_64" directory is intended to hold macOS (OS X) native binaries
which this module is dependent upon. This directory may be eliminated for a specific
module if native binaries are not provided for the corresponding platform.
2 changes: 1 addition & 1 deletion os/win64/README.txt → os/win_x86_64/README.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
The "os/win64" directory is intended to hold MS Windows native binaries (.exe)
The "os/win_x86_64" directory is intended to hold MS Windows native binaries (.exe)
which this module is dependent upon. This directory may be eliminated for a specific
module if native binaries are not provided for the corresponding platform.
4 changes: 2 additions & 2 deletions src/main/java/firmware/cbfs/CBFSCompressionAttribute.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@
*/
public class CBFSCompressionAttribute extends CBFSFileAttribute {
// Original header fields
int compressionType;
long uncompressedSize;
private final int compressionType;
private final long uncompressedSize;

/**
* Constructs a CBFSCompressionAttribute from a specified BinaryReader.
Expand Down
81 changes: 50 additions & 31 deletions src/main/java/firmware/cbfs/CBFSFile.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,16 @@
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Formatter;

import ghidra.app.util.bin.ByteArrayProvider;
import ghidra.app.util.bin.ByteProvider;
import ghidra.formats.gfilesystem.FSUtilities;
import ghidra.formats.gfilesystem.FileCache;
import ghidra.formats.gfilesystem.FileSystemService;
import ghidra.formats.gfilesystem.fileinfo.FileAttributeType;
import ghidra.formats.gfilesystem.fileinfo.FileAttributes;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
import org.apache.commons.compress.compressors.lz4.FramedLZ4CompressorInputStream;
import org.apache.commons.compress.compressors.lzma.LZMACompressorInputStream;

Expand Down Expand Up @@ -49,15 +57,15 @@
*/
public class CBFSFile {
// Original header fields
private byte[] signature;
private int size;
private int type;
private long attributesOffset;
private long offset;
private String name;
private final byte[] signature;
private final int size;
private final int type;
private final long attributesOffset;
private final long offset;
private final String name;

private CBFSFileAttribute attribute;
private byte[] data;
private final byte[] data;

/**
* Constructs a CBFSFile from a specified BinaryReader.
Expand Down Expand Up @@ -91,25 +99,30 @@ public CBFSFile(BinaryReader reader) throws IOException {
}

/**
* Returns an InputStream for the contents of the current file. Compressed files will be
* Returns a ByteProvider for the contents of the current file. Compressed files will be
* wrapped in a CompressorInputStream for transparent extraction.
*
* @return an InputStream for the contents of the current file
* @return a ByteProvider for the contents of the current file
*/
public InputStream getData() throws IOException {
ByteArrayInputStream dataInputStream = new ByteArrayInputStream(data);

public ByteProvider getByteProvider() throws IOException, CancelledException {
// Extract the file if compression is used (specified in a compression attribute).
if (attribute != null && attribute instanceof CBFSCompressionAttribute) {
switch (((CBFSCompressionAttribute) attribute).getCompressionType()) {
case CBFSConstants.CompressionAlgorithm.LZMA:
return new LZMACompressorInputStream(dataInputStream);
case CBFSConstants.CompressionAlgorithm.LZ4:
return new FramedLZ4CompressorInputStream(dataInputStream);
InputStream is = new ByteArrayInputStream(data);

int compressionType = ((CBFSCompressionAttribute) attribute).getCompressionType();
switch (compressionType) {
case CBFSConstants.CompressionAlgorithm.LZMA: is = new LZMACompressorInputStream(is); break;
case CBFSConstants.CompressionAlgorithm.LZ4: is = new FramedLZ4CompressorInputStream(is); break;
default: throw new IOException("Unsupported CBFS compression type: " + compressionType);
}
}

return dataInputStream;
FileCache.FileCacheEntryBuilder tmpFileBuilder = FileSystemService.getInstance().createTempFile(-1);
FSUtilities.streamCopy(is, tmpFileBuilder, TaskMonitor.DUMMY);
FileCache.FileCacheEntry fce = tmpFileBuilder.finish();
return FileSystemService.getInstance().getNamedTempFile(fce, name);
} else {
return new ByteArrayProvider(data);
}
}

/**
Expand Down Expand Up @@ -148,24 +161,30 @@ public int length() {
return size;
}

@Override
public String toString() {
Formatter formatter = new Formatter();
formatter.format("CBFS file name: %s\n", name);
formatter.format("CBFS file size: 0x%X\n", size);
formatter.format("CBFS file type: %s (0x%X)\n", CBFSConstants.FileType.toString(type),
type);
/**
* Returns FileAttributes for the current file.
*
* @return FileAttributes for the current file
*/
public FileAttributes getFileAttributes() {
FileAttributes attributes = new FileAttributes();
attributes.add(FileAttributeType.NAME_ATTR, name);
attributes.add("File Type", CBFSConstants.FileType.toString(type));
if (attribute != null && attribute instanceof CBFSCompressionAttribute) {
switch (((CBFSCompressionAttribute) attribute).getCompressionType()) {
case CBFSConstants.CompressionAlgorithm.LZMA:
formatter.format("CBFS file attribute: Compressed (LZMA)");
break;
attributes.add("Compression Type", "LZMA");
case CBFSConstants.CompressionAlgorithm.LZ4:
formatter.format("CBFS file attribute: Compressed (LZ4)");
attributes.add("Compression Type", "LZ4");
attributes.add(FileAttributeType.COMPRESSED_SIZE_ATTR, size);
break;
default:
attributes.add(FileAttributeType.SIZE_ATTR, Long.valueOf(size));
}
} else {
attributes.add(FileAttributeType.SIZE_ATTR, Long.valueOf(size));
}

return formatter.toString();
return attributes;
}
}
6 changes: 3 additions & 3 deletions src/main/java/firmware/cbfs/CBFSFileAttribute.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@
*/
public class CBFSFileAttribute {
// Original header fields
private int tag;
private int size;
private byte[] data;
private final int tag;
private final int size;
private final byte[] data;

/**
* Constructs a FlashMapArea from a specified BinaryReader.
Expand Down
53 changes: 27 additions & 26 deletions src/main/java/firmware/cbfs/CBFSFileSystem.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,23 @@
package firmware.cbfs;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.ByteProvider;
import ghidra.app.util.bin.ByteProviderWrapper;
import ghidra.formats.gfilesystem.*;
import ghidra.formats.gfilesystem.annotations.FileSystemInfo;
import ghidra.formats.gfilesystem.fileinfo.FileAttributes;
import ghidra.util.Msg;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;

@FileSystemInfo(type = "cbfs", description = "Coreboot File System", factory = CBFSFileSystemFactory.class)
public class CBFSFileSystem implements GFileSystem {
private final FSRLRoot fsFSRL;
private FileSystemIndexHelper<CBFSFile> fsih;
private FileSystemRefManager refManager = new FileSystemRefManager(this);
private final FileSystemIndexHelper<CBFSFile> fsih;
private final FileSystemRefManager refManager = new FileSystemRefManager(this);
private ByteProvider provider;

public CBFSFileSystem(FSRLRoot fsFSRL) {
Expand Down Expand Up @@ -60,7 +61,7 @@ public void mount(ByteProvider provider, TaskMonitor monitor) throws IOException
reader.align(header.getAlignment());
String name = cbfsFile.getName().length() > 0 ? cbfsFile.getName().replace('/', '_') : "(empty)";
Msg.debug(this, String.format("%s size = 0x%X, data offset = 0x%X, type = %s", name, cbfsFile.length(),
cbfsFile.getOffset(), CBFSConstants.FileType.toString(cbfsFile.getType())));
cbfsFile.getOffset(), CBFSConstants.FileType.toString(cbfsFile.getType())));

// Ignore empty CBFS files (used for padding).
if (cbfsFile.getType() == CBFSConstants.FileType.NULL) {
Expand All @@ -72,13 +73,19 @@ public void mount(ByteProvider provider, TaskMonitor monitor) throws IOException
}

@Override
public String getName() {
return fsFSRL.getContainer().getName();
public GFile lookup(String path) {
return fsih.lookup(path);
}

@Override
public FSRLRoot getFSRL() {
return fsFSRL;
public void close() throws IOException {
refManager.onClose();
if (provider != null) {
provider.close();
provider = null;
}

fsih.clear();
}

@Override
Expand All @@ -87,25 +94,20 @@ public boolean isClosed() {
}

@Override
public FileSystemRefManager getRefManager() {
return refManager;
public ByteProvider getByteProvider(GFile file, TaskMonitor monitor) throws IOException, CancelledException {
CBFSFile cbfsFile = fsih.getMetadata(file);
return new ByteProviderWrapper(cbfsFile.getByteProvider(), file.getFSRL());
}

@Override
public void close() throws IOException {
refManager.onClose();
if (provider != null) {
provider.close();
provider = null;
}

fsih.clear();
public FileAttributes getFileAttributes(GFile file, TaskMonitor monitor) {
CBFSFile cbfsFile = fsih.getMetadata(file);
return cbfsFile.getFileAttributes();
}

@Override
public String getInfo(GFile file, TaskMonitor monitor) {
CBFSFile cbfsFile = fsih.getMetadata(file);
return (cbfsFile != null) ? cbfsFile.toString() : null;
public FSRLRoot getFSRL() {
return fsFSRL;
}

@Override
Expand All @@ -114,13 +116,12 @@ public List<GFile> getListing(GFile directory) {
}

@Override
public GFile lookup(String path) throws IOException {
return fsih.lookup(path);
public String getName() {
return fsFSRL.getContainer().getName();
}

@Override
public InputStream getInputStream(GFile file, TaskMonitor monitor) throws IOException, CancelledException {
CBFSFile cbfsFile = fsih.getMetadata(file);
return cbfsFile.getData();
public FileSystemRefManager getRefManager() {
return refManager;
}
}
33 changes: 16 additions & 17 deletions src/main/java/firmware/cbfs/CBFSFileSystemFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,31 +16,24 @@

package firmware.cbfs;

import java.io.File;
import java.io.IOException;

import ghidra.app.util.bin.ByteProvider;
import ghidra.formats.gfilesystem.FSRL;
import ghidra.formats.gfilesystem.FSRLRoot;
import ghidra.formats.gfilesystem.FileSystemService;
import ghidra.formats.gfilesystem.factory.GFileSystemFactoryFull;
import ghidra.formats.gfilesystem.factory.GFileSystemFactoryByteProvider;
import ghidra.formats.gfilesystem.factory.GFileSystemProbeBytesOnly;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
import utilities.util.ArrayUtilities;

public class CBFSFileSystemFactory implements GFileSystemFactoryFull<CBFSFileSystem>, GFileSystemProbeBytesOnly {
public class CBFSFileSystemFactory implements GFileSystemFactoryByteProvider<CBFSFileSystem>,
GFileSystemProbeBytesOnly {
@Override
public CBFSFileSystem create(FSRL containerFSRL, FSRLRoot targetFSRL, ByteProvider byteProvider, File containerFile,
FileSystemService fsService, TaskMonitor monitor) throws IOException, CancelledException {
CBFSFileSystem fs = new CBFSFileSystem(targetFSRL);
try {
fs.mount(byteProvider, monitor);
return fs;
} catch (IOException ioe) {
fs.close();
throw ioe;
}
public boolean probeStartBytes(FSRL containerFSRL, byte[] startBytes) {
return ArrayUtilities.arrayRangesEquals(CBFSConstants.CBFS_FILE_SIGNATURE, 0, startBytes, 0,
CBFSConstants.CBFS_FILE_SIGNATURE.length);
}

@Override
Expand All @@ -49,9 +42,15 @@ public int getBytesRequired() {
}

@Override
public boolean probeStartBytes(FSRL containerFSRL, byte[] startBytes) {
return ArrayUtilities.arrayRangesEquals(CBFSConstants.CBFS_FILE_SIGNATURE, 0, startBytes, 0,
CBFSConstants.CBFS_FILE_SIGNATURE.length);
public CBFSFileSystem create(FSRLRoot fsrlRoot, ByteProvider byteProvider, FileSystemService fsService,
TaskMonitor monitor) throws IOException, CancelledException {
CBFSFileSystem fs = new CBFSFileSystem(fsrlRoot);
try {
fs.mount(byteProvider, monitor);
return fs;
} catch (IOException ioe) {
fs.close();
throw ioe;
}
}

}
Loading

0 comments on commit fb77436

Please sign in to comment.