+#define OPCODE_CALL 0xe8
+#define OPCODE_JMP 0xe9
+
+static void bcj_filter ( void *data, size_t len ) {
+ struct {
+ uint8_t opcode;
+ int32_t target;
+ } __attribute__ (( packed )) *jump;
+ ssize_t limit = ( len - sizeof ( *jump ) );
+ ssize_t offset;
+
+ /* liblzma does include an x86 BCJ filter, but it's hideously
+ * convoluted and undocumented. This BCJ filter is
+ * substantially simpler and achieves the same compression (at
+ * the cost of requiring the decompressor to know the size of
+ * the decompressed data, which we already have in iPXE).
+ */
+ for ( offset = 0 ; offset <= limit ; offset++ ) {
+ jump = ( data + offset );
+
+ /* Skip instructions that are not followed by a rel32 address */
+ if ( ( jump->opcode != OPCODE_CALL ) &&
+ ( jump->opcode != OPCODE_JMP ) )
+ continue;
+
+ /* Convert rel32 address to an absolute address. To
+ * avoid false positives (which damage the compression
+ * ratio), we should check that the jump target is
+ * within the range [0,limit).
+ *
+ * Some output values would then end up being mapped
+ * from two distinct input values, making the
+ * transformation irreversible. To solve this, we
+ * transform such values back into the part of the
+ * range which would otherwise correspond to no input
+ * values.
+ */
+ if ( ( jump->target >= -offset ) &&
+ ( jump->target < ( limit - offset ) ) ) {
+ /* Convert relative addresses in the range
+ * [-offset,limit-offset) to absolute
+ * addresses in the range [0,limit).
+ */
+ jump->target += offset;
+ } else if ( ( jump->target >= ( limit - offset ) ) &&
+ ( jump->target < limit ) ) {
+ /* Convert positive numbers in the range
+ * [limit-offset,limit) to negative numbers in
+ * the range [-offset,0).
+ */
+ jump->target -= limit;
+ }
+ offset += sizeof ( jump->target );
+ };
+}
+