-
Notifications
You must be signed in to change notification settings - Fork 16
General improvements to the tool #7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,17 +1,56 @@ | ||
| efm8load.py | ||
| === | ||
| # efm8load.py | ||
|
|
||
| A python-only implementation of the efm8 bootloader protocol | ||
| A python-only implementation of the efm8 bootloader protocol. | ||
| Check out http://fishpepper.de/2016/10/15/efm8-bootloader-flash-tool-efm8load-py/ for more info. | ||
|
|
||
| see http://fishpepper.de/2016/10/15/efm8-bootloader-flash-tool-efm8load-py/ for more info | ||
|
|
||
| Status: | ||
| - tested on EFM8BB10F8G: identify, write, verify and read are working | ||
| ## Status | ||
| | Microcontroller Unit (MCU) | Identify | Read | Write | | ||
| | - | - | - | - | | ||
| | EFM8BB10F8G | 🟢 | 🟢 | 🟢 | | ||
| | EFM8BB52F32G | 🟢 | 🟢 | 🟡 | | ||
|
|
||
| Usage: | ||
| - connect rs232 (3.3V level!) to the RX and TX pins of your MCU | ||
| - empty targets boot right into the bootloader (flash[0] = 0xFF -> bootloader) | ||
| - flashed targets need the C2D pin pulled low during powerup to enter bootloader mode | ||
| 🟢 = Working, | ||
| 🟡 = Not tested, | ||
| 🔴 = Not working | ||
|
|
||
| TODO: | ||
| add a protection to stop users from overwriting the bootloader area | ||
|
|
||
| ## Info | ||
| - Connect the MCU to the rs232: | ||
| * MCU RXD to TXD | ||
| * MCU TXD to RXD | ||
| * MCU 3v3 to 3v3 **or** MCU 5v to 5v **(⚠️Do not mix 5v with 3v3! Check the datasheet for V<sub>VDD</sub> and `Voltage on VDD supply pin`⚠️)** | ||
| * MCU GND to GND | ||
| * MCU C2D to GND | ||
| - Empty targets boot right into the bootloader (flash[0] = 0xFF -> bootloader) | ||
|
|
||
|
|
||
| ## Requirements | ||
| - python3 + pip | ||
| - USB to UART Bridge Controller (e.g. CP2102) | ||
| - CP210x USB to UART Bridge VCP Drivers | ||
| - C2D Pin **must** be pulled low (connected to GND) during powerup to enter the bootload mode (Review section `5.3.1 Entering Bootload Mode` [documents/an945-efm8-factory-bootloader-user-guide.pdf](documents/an945-efm8-factory-bootloader-user-guide.pdf) for the right Pin numbers) | ||
|
|
||
|
|
||
| ## Setup | ||
| ```bash | ||
| # Install the necessary packages | ||
| pip install -r requirements.txt | ||
| ``` | ||
|
|
||
| ## Usage | ||
| ```bash | ||
| # Identify the chip | ||
| python efm8load.py -p <COM_PORT> -i | ||
|
|
||
| # Dump the flash memory to file | ||
| python efm8load.py -p <COM_PORT> -r dumped_flash.hex | ||
|
|
||
| # ⚠️Upload/Write file to flash memory⚠️ | ||
| python efm8load.py -p <COM_PORT> -w dumped_flash.hex | ||
| ``` | ||
|
|
||
|
|
||
| ## TODO | ||
| - Add a protection to stop users from overwriting the bootloader area | ||
| - Information about decompiling the dumped flash memory | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i would drop this, add the dumps directory to the toplevel gitignore instead |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| * | ||
| !.gitignore |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,13 +21,12 @@ | |
|
|
||
| import crcmod | ||
| import serial | ||
| from tqdm import tqdm | ||
| from collections import Counter | ||
| from intelhex import IntelHex | ||
|
|
||
|
|
||
| # make sure to install the python3 modules for serial, crcmod, and pip3: | ||
| # make sure to install the python modules for pyserial, tqdm, crcmod, intelhex: | ||
| # sudo apt intstall python3-crcmod python3-serial python3-pip | ||
| # if you are missing the intelhex package, you can install it afterwars by | ||
| # pip3 install intelhex --user | ||
|
|
||
| class COMMAND: | ||
| IDENTIFY = 0x30 | ||
|
|
@@ -81,6 +80,9 @@ class EFM8Loader: | |
| }], | ||
| 0x34 : ["EFM8BB3", { | ||
| 0x01: ["EFM8BB31F64G-QFN32" , 64*1024, 512, 512], | ||
| }], | ||
| 0x39 : ["EFM8BB5", { | ||
| 0x08: ["EFM8BB52F32G-QFN32" , 15*2048, 2048, 2048], | ||
| }] | ||
| } | ||
|
|
||
|
|
@@ -271,30 +273,41 @@ def download(self, filename): | |
| #the bootloader protocol does not allow reading flash | ||
| #however it allows to verify written bytes | ||
| #we will exploit this feature to dump the flash contents | ||
| #for now assume 8kb flash | ||
| flash_size = 8 * 1024 | ||
|
|
||
| ih = IntelHex() | ||
| for address in range(flash_size): | ||
| #test one byte by byte | ||
| #first check 0x00 | ||
| byte = 0 | ||
| if (self.verify(address, [byte]) == RESPONSE.ACK): | ||
| ih[address] = byte | ||
| else: | ||
| #now start with 0xFF (empty flash) | ||
| for byte in range(0xFF, -1, -1): | ||
| if (self.verify(address, [byte]) == RESPONSE.ACK): | ||
| #success, the flash content on this address euals <byte> | ||
| ih[address] = byte | ||
| break | ||
| print("\r> flash[0x%04X] = 0x%02X" % (address, byte), end="") | ||
| sys.stdout.flush() | ||
|
|
||
| print("\n> finished") | ||
| # generate list with all possible hex adress values | ||
| byte_list = Counter() | ||
| for byte in range(0xFF, -1, -1): | ||
| byte_list[byte] += 1 | ||
|
|
||
|
|
||
| for address in tqdm( | ||
| range(self.flash_size), | ||
| desc="Dumping Flash", | ||
| unit=" Bytes", | ||
| ascii=" #", | ||
| smoothing=0.01, | ||
| dynamic_ncols=True, | ||
| unit_scale=True, | ||
| ): | ||
| sorted_byte_list = byte_list.most_common() | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what is the sorting good for? speedup if there are many equal values? |
||
| for curr_byte in sorted_byte_list: | ||
| byte=curr_byte[0] | ||
| if (self.verify(address, [byte]) == RESPONSE.ACK): | ||
| #success, the flash content on this address equals <byte> | ||
| ih[address] = byte | ||
| byte_list[byte] += 1 | ||
| break | ||
| #print(" flash[0x%04X] = 0x%02X" % (address, byte)) | ||
| print("\n> finished dumping") | ||
|
|
||
| #done, all flash contents have been read, now store this to the file | ||
| ih.write_hex_file(filename) | ||
| #done, all flash contents have been read, now store this to the files | ||
| ih.tofile("dumps/" + filename, format='hex') | ||
| ih.tofile("dumps/" + filename + ".bin", format='bin') | ||
|
Comment on lines
+306
to
+307
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i would not prepend dumps here, you can always pass dumps/file.hex as commandline param. e.g. i use it to dump to /tmp/dump.hex |
||
|
|
||
| print("\n> dump written to disk successfully") | ||
| print("\n> done") | ||
|
|
||
| def upload(self, filename): | ||
| print("> uploading file '%s'" % (filename)) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| crcmod==1.7 | ||
| intelhex==2.3.0 | ||
| pyserial==3.5 | ||
| tqdm==4.66.4 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i would drop the line about decompiling, its not the scope of this tool