Skip to content

Commit

Permalink
option_rom: Add support for compressed EFI images
Browse files Browse the repository at this point in the history
This commit also adds basic support for loading JNI libraries from the
os/platform directory.
  • Loading branch information
al3xtjames committed Jun 4, 2019
1 parent add750a commit c853f0d
Show file tree
Hide file tree
Showing 12 changed files with 1,241 additions and 10 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@ gradle/
.project
.pydevproject
.classpath

*.dll
*.dylib
*.so
13 changes: 13 additions & 0 deletions LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Copyright 2019 Alex James <[email protected]>.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
20 changes: 15 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,11 @@ This was accepted as a [coreboot project][2] for GSoC 2019.
### PCI option ROM loader
- Implements a FS loader for PCI option ROMs (handles hybrid ROMs,
e.g. legacy x86 + UEFI)
- Loads uncompressed UEFI executables from PCI option ROMs
- Loads UEFI executables from PCI option ROMs (including compressed images)
- Calculates entry point address for legacy x86 option ROMs (still needs to be
manually loaded as a raw real-mode binary)
- TODO: Write loader for legacy x86 option ROMs (automatically select
real-mode x86)
- TODO: Implement support for compressed UEFI executables

## Planned functionality / TODO
### Firmware image loader
Expand All @@ -30,21 +29,32 @@ Ghidra's standard Gradle build system is used. Set the `GHIDRA_INSTALL_DIR`
environment variable before building:

```bash
export GHIDRA_INSTALL_DIR="/path/to/ghidra"
gradle
$ export GHIDRA_INSTALL_DIR="/path/to/ghidra"
$ gradle
```

The module ZIP will be output to `dist/`. Use **File > Install Extensions** and
select the green plus to browse to the extension. Restart Ghidra when prompted.

## Usage

### PCI option ROM loader
Add a PCI option ROM to a Ghidra project. When prompted to select an import
mode, select **File system**. The images contained within the option ROM will
be displayed, and can be imported for analysis. Information for each image can
be displayed by selecting **Get Info** in the right-click menu for an image.

## License
Apache 2.0, with some exceptions:

- `src/efidecompress/c/efidecompress.c`: BSD

## Credits
`src/efidecompress/c/efidecompress.c` is a lightly modified version of
[Decompress.c][4] from uefi-firmware-parser (which itself is derived from
[the original in EDK2 BaseTools][5]).

[1]: https://ghidra-sre.org/
[2]: https://summerofcode.withgoogle.com/projects/#6413737605464064
[3]: https://github.com/danse-macabre/ida-efitools
[4]: https://github.com/theopolis/uefi-firmware-parser/blob/21106baf019db9dcd046a3c01ee7b32212de45a5/uefi_firmware/compression/Tiano/Decompress.c
[5]: https://github.com/tianocore/edk2/blob/2e351cbe8e190271b3716284fc1076551d005472/BaseTools/Source/C/Common/Decompress.c
60 changes: 58 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// Builds a Ghidra Extension for a given Ghidra installation.
//
// An absolute path to the Ghidra installation directory must be supplied either by setting the
// An absolute path to the Ghidra installation directory must be supplied either by setting the
// GHIDRA_INSTALL_DIR environment variable or Gradle project property:
//
// > export GHIDRA_INSTALL_DIR=<Absolute path to Ghidra>
// > export GHIDRA_INSTALL_DIR=<Absolute path to Ghidra>
// > gradle
//
// or
Expand All @@ -14,6 +14,54 @@
// application.gradle.version property in <GHIDRA_INSTALL_DIR>/Ghidra/application.properties
// for the correction version of Gradle to use for the Ghidra installation you specify.

apply plugin: 'c'
model {
components {
efidecompress(NativeLibrarySpec) {
sources {
c {
source {
srcDir 'src/efidecompress/c'
include 'efidecompress.c'
}
}
}

binaries.all {
if (targetPlatform.operatingSystem.macOsX) {
cCompiler.args '-I', "${org.gradle.internal.jvm.Jvm.current().javaHome}/include"
cCompiler.args '-I', "${org.gradle.internal.jvm.Jvm.current().javaHome}/include/darwin"
cCompiler.args '-mmacosx-version-min=10.4'
linker.args '-mmacosx-version-min=10.4'
} else if (targetPlatform.operatingSystem.linux) {
cCompiler.args '-I', "${org.gradle.internal.jvm.Jvm.current().javaHome}/include"
cCompiler.args '-I', "${org.gradle.internal.jvm.Jvm.current().javaHome}/include/linux"
cCompiler.args '-D_FILE_OFFSET_BITS=64'
} else if (targetPlatform.operatingSystem.windows) {
// TODO: test Windows JNI library support
cCompiler.args "-I${org.gradle.internal.jvm.Jvm.current().javaHome}/include"
cCompiler.args "-I${org.gradle.internal.jvm.Jvm.current().javaHome}/include/win32"
linker.args "Shlwapi.lib", "Advapi32.lib"
}
}
}
}
}

import org.apache.tools.ant.taskdefs.condition.Os;

task copyLibrary(type: Copy) {
if (Os.isFamily(Os.FAMILY_MAC)) {
from file("$buildDir/libs/efidecompress/shared/libefidecompress.dylib") into "$projectDir/os/osx64"
} else if (Os.isFamily(Os.FAMILY_UNIX)) {
from file("$buildDir/libs/efidecompress/shared/libefidecompress.so") into "$projectDir/os/linux64"
} else if (Os.isFamily(Os.FAMILY_WINDOWS)) {
from file("$buildDir/libs/efidecompress/shared/libefidecompress/win32.dll") into file("$projectDir/os/win64/efidecompress.dll")
}
}

copyLibrary.dependsOn 'efidecompressSharedLibrary'

//----------------------START "DO NOT MODIFY" SECTION------------------------------
def ghidraInstallDir

Expand All @@ -31,3 +79,11 @@ else {
throw new GradleException("GHIDRA_INSTALL_DIR is not defined!")
}
//----------------------END "DO NOT MODIFY" SECTION-------------------------------

buildExtension.dependsOn 'copyLibrary'

clean {
delete "$projectDir/os/linux64/libefidecompress.libefidecompress.so"
delete "$projectDir/os/osx64/libefidecompress.dylib"
delete "$projectDir/os/win64/libefidecompress.dll"
}
3 changes: 3 additions & 0 deletions os/linux64/README.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
The "os/linux64" 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.
3 changes: 3 additions & 0 deletions os/osx64/README.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
The "os/osx64" 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.
3 changes: 3 additions & 0 deletions os/win64/README.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
The "os/win64" 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.
Loading

0 comments on commit c853f0d

Please sign in to comment.