Skip to content

Commit

Permalink
unlocking support in GUI (#31)
Browse files Browse the repository at this point in the history
* unlocking support in GUI
  • Loading branch information
bri3d authored Dec 11, 2021
1 parent 4435ead commit 867e391
Show file tree
Hide file tree
Showing 5 changed files with 191 additions and 105 deletions.
2 changes: 1 addition & 1 deletion VW_Flash.py
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ def wrap_callback_function(flasher_step, flasher_status, flasher_progress):
flash_info.box_code_location[5][0] : flash_info.box_code_location[5][1]
].decode()
)
if file_box_code.strip() != flash_info.patch_box_code.strip():
if file_box_code.strip() != flash_info.patch_box_code.split("_")[0].strip():
logger.error(
f"Boxcode mismatch for unlocking. Got box code {file_box_code} but expected {flash_info.patch_box_code}"
)
Expand Down
287 changes: 185 additions & 102 deletions VW_Flash_GUI.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,9 +163,11 @@ def __init__(self, parent):
self.module_choice.Bind(wx.EVT_CHOICE, self.on_module_changed)

available_actions = [
"Calibration flash",
"Calibration Flash Unlocked",
"FlashPack ZIP flash",
"Full Flash (BIN/FRF)",
"Full Flash Unlocked (BIN/FRF)",
"Unlock ECU (FRF)",
"Flash Stock (Re-Lock) / Unmodified BIN/FRF",
]
self.action_choice = wx.Choice(self, choices=available_actions)
self.action_choice.SetSelection(0)
Expand Down Expand Up @@ -255,110 +257,175 @@ def on_read_dtcs(self, event):
for dtc in dtcs
]

def flash_unlock(self, selected_file):
if module_selection_is_dsg(self.module_choice.GetSelection()):
self.feedback_text.AppendText("SKIPPED: Unlocking is unnecessary for DSG\n")
return

input_bytes = Path(self.row_obj_dict[selected_file]).read_bytes()
if str.endswith(self.row_obj_dict[selected_file], ".frf"):
self.feedback_text.AppendText("Extracting FRF for unlock...\n")
(flash_data, allowed_boxcodes,) = extract_flash.extract_flash_from_frf(
input_bytes,
self.flash_info,
is_dsg=module_selection_is_dsg(self.module_choice.GetSelection()),
)
self.input_blocks = {}
for i in self.flash_info.block_names_frf.keys():
filename = self.flash_info.block_names_frf[i]
self.input_blocks[filename] = constants.BlockData(
i, flash_data[filename]
)

cal_block = self.input_blocks[self.flash_info.block_names_frf[5]]
file_box_code = str(
cal_block.block_bytes[
self.flash_info.box_code_location[5][
0
] : self.flash_info.box_code_location[5][1]
].decode()
)
if (
file_box_code.strip()
!= self.flash_info.patch_box_code.split("_")[0].strip()
):
self.feedback_text.AppendText(
f"Boxcode mismatch for unlocking. Got box code {file_box_code} but expected {self.flash_info.patch_box_code}. Please don't try to be clever. Supply the correct file and the process will work."
)
return

self.input_blocks["UNLOCK_PATCH"] = constants.BlockData(
self.flash_info.patch_block_index + 5,
Path(self.flash_info.patch_filename).read_bytes(),
)
key_order = list(
map(lambda i: self.flash_info.block_names_frf[i], [1, 2, 3, 4, 5])
)
key_order.insert(4, "UNLOCK_PATCH")
input_blocks_with_patch = {k: self.input_blocks[k] for k in key_order}
self.input_blocks = input_blocks_with_patch
self.flash_bin(get_info=False)
else:
self.feedback_text.AppendText(
"File did not appear to be a valid FRF. Unlocking is possible only with a specific FRF file for your ECU family.\n"
)

def flash_bin_file(self, selected_file, patch_cboot=False):
input_bytes = Path(self.row_obj_dict[selected_file]).read_bytes()
if str.endswith(self.row_obj_dict[selected_file], ".frf"):
self.feedback_text.AppendText("Extracting FRF...\n")
(flash_data, allowed_boxcodes,) = extract_flash.extract_flash_from_frf(
input_bytes,
self.flash_info,
is_dsg=module_selection_is_dsg(self.module_choice.GetSelection()),
)
self.input_blocks = {}
for i in self.flash_info.block_names_frf.keys():
filename = self.flash_info.block_names_frf[i]
self.input_blocks[filename] = constants.BlockData(
i, flash_data[filename]
)
self.flash_bin(get_info=False, should_patch_cboot=patch_cboot)
elif len(input_bytes) == self.flash_info.binfile_size:
self.input_blocks = binfile.blocks_from_bin(
self.row_obj_dict[selected_file], self.flash_info
)
self.flash_bin(get_info=False, should_patch_cboot=patch_cboot)
else:
self.feedback_text.AppendText(
"File did not appear to be a valid BIN or FRF\n"
)

def flash_flashpack(self, selected_file: str):
# We're expecting a "FlashPack" ZIP
with ZipFile(self.row_obj_dict[selected_file], "r") as zip_archive:
if "file_list.json" not in zip_archive.namelist():
self.feedback_text.AppendText(
"SKIPPING: No file listing found in archive\n"
)

else:
with zip_archive.open("file_list.json") as file_list_json:
file_list = json.load(file_list_json)

self.input_blocks = {}
for filename in file_list:
self.input_blocks[filename] = simos_flash_utils.BlockData(
int(file_list[filename]), zip_archive.read(filename)
)

self.flash_bin(get_info=False)

def flash_cal(self, selected_file: str):
# Flash a Calibration block only
self.input_blocks = {}

if module_selection_is_dsg(self.module_choice.GetSelection()):
# Populate DSG Driver block from a fixed file name for now.
dsg_driver_path = path.join(self.options["cal"], "FD_2.DRIVER.bin")
self.feedback_text.AppendText(
"Loading DSG Driver from: " + dsg_driver_path + "\n"
)
self.input_blocks["FD_2.DRIVER.bin"] = constants.BlockData(
dq250mqb.block_name_to_int["DRIVER"],
Path(dsg_driver_path).read_bytes(),
)
self.input_blocks[self.row_obj_dict[selected_file]] = constants.BlockData(
dq250mqb.block_name_to_int["CAL"],
Path(self.row_obj_dict[selected_file]).read_bytes(),
)
else:
input_bytes = Path(self.row_obj_dict[selected_file]).read_bytes()
if len(input_bytes) == self.flash_info.binfile_size:
self.feedback_text.AppendText(
"Extracting Calibration from full binary...\n"
)
input_blocks = binfile.blocks_from_bin(
self.row_obj_dict[selected_file], self.flash_info
)
# Filter to only CAL block.
self.input_blocks = {
k: v
for k, v in input_blocks.items()
if v.block_number == simosshared.block_name_to_int["CAL"]
}
else:
self.input_blocks[
self.row_obj_dict[selected_file]
] = constants.BlockData(
simosshared.block_name_to_int["CAL"],
input_bytes,
)

self.flash_bin()

def on_flash(self, event):
selected_file = self.list_ctrl.GetFirstSelected()
logger.critical("Selected: " + str(self.row_obj_dict[selected_file]))

if selected_file == -1:
print("Select a file to flash")
self.feedback_text.AppendText("SKIPPING: Select a file to flash!\n")
else:
if self.action_choice.GetSelection() == 0:
# Flash a Calibration block only
self.input_blocks = {}
choice = self.action_choice.GetSelection()
if choice == 0:
# "Flash Calibration"
self.flash_cal(selected_file)

if module_selection_is_dsg(self.module_choice.GetSelection()):
# Populate DSG Driver block from a fixed file name for now.
dsg_driver_path = path.join(self.options["cal"], "FD_2.DRIVER.bin")
self.feedback_text.AppendText(
"Loading DSG Driver from: " + dsg_driver_path + "\n"
)
self.input_blocks["FD_2.DRIVER.bin"] = constants.BlockData(
dq250mqb.block_name_to_int["DRIVER"],
Path(dsg_driver_path).read_bytes(),
)
self.input_blocks[
self.row_obj_dict[selected_file]
] = constants.BlockData(
dq250mqb.block_name_to_int["CAL"],
Path(self.row_obj_dict[selected_file]).read_bytes(),
)
else:
input_bytes = Path(self.row_obj_dict[selected_file]).read_bytes()
if len(input_bytes) == self.flash_info.binfile_size:
self.feedback_text.AppendText(
"Extracting Calibration from full binary...\n"
)
input_blocks = binfile.blocks_from_bin(
self.row_obj_dict[selected_file], self.flash_info
)
# Filter to only CAL block.
self.input_blocks = {
k: v
for k, v in input_blocks.items()
if v.block_number == simosshared.block_name_to_int["CAL"]
}
else:
self.input_blocks[
self.row_obj_dict[selected_file]
] = constants.BlockData(
simosshared.block_name_to_int["CAL"],
input_bytes,
)

self.flash_bin()

elif self.action_choice.GetSelection() == 1:
# We're expecting a "FlashPack" ZIP
with ZipFile(self.row_obj_dict[selected_file], "r") as zip_archive:
if "file_list.json" not in zip_archive.namelist():
self.feedback_text.AppendText(
"No file listing found in archive\n"
)

else:
with zip_archive.open("file_list.json") as file_list_json:
file_list = json.load(file_list_json)

self.input_blocks = {}
for filename in file_list:
self.input_blocks[filename] = simos_flash_utils.BlockData(
int(file_list[filename]), zip_archive.read(filename)
)

self.flash_bin(get_info=False)

elif self.action_choice.GetSelection() == 2:
# We're expecting a "full BIN" file or an FRF as input

input_bytes = Path(self.row_obj_dict[selected_file]).read_bytes()
if str.endswith(self.row_obj_dict[selected_file], ".frf"):
self.feedback_text.AppendText("Extracting FRF...\n")
(
flash_data,
allowed_boxcodes,
) = extract_flash.extract_flash_from_frf(
input_bytes,
self.flash_info,
is_dsg=module_selection_is_dsg(
self.module_choice.GetSelection()
),
)
self.input_blocks = {}
for i in self.flash_info.block_names_frf.keys():
filename = self.flash_info.block_names_frf[i]
self.input_blocks[filename] = constants.BlockData(
i, flash_data[filename]
)
self.flash_bin(get_info=False)
elif len(input_bytes) == self.flash_info.binfile_size:
self.input_blocks = binfile.blocks_from_bin(
self.row_obj_dict[selected_file], self.flash_info
)
self.flash_bin(get_info=False)
else:
self.feedback_text.AppendText(
"File did not appear to be a valid BIN or FRF\n"
)
elif choice == 1:
# "Flash Flashpack"
self.flash_flashpack(selected_file)

elif choice == 2:
# Flash BIN/FRF (unlocked)
self.flash_bin_file(selected_file, patch_cboot=True)

elif choice == 3:
# "Unlock flash"
self.flash_unlock(selected_file)

elif choice == 4:
# Flash to stock
self.flash_bin_file(selected_file, patch_cboot=False)

def update_bin_listing(self, event=None):
self.list_ctrl.ClearAll()
Expand All @@ -367,18 +434,34 @@ def update_bin_listing(self, event=None):
self.list_ctrl.InsertColumn(1, "Modify Time", width=140)

if self.action_choice.GetSelection() == 0:
# Calibration Flash
bins = glob.glob(self.current_folder_path + "/*.bin")
self.options["cal"] = self.current_folder_path
elif self.action_choice.GetSelection() == 1:
# Flashpack
bins = glob.glob(self.current_folder_path + "/*.zip")
self.options["flashpacks"] = self.current_folder_path
elif self.action_choice.GetSelection() == 2:
# Full BIN/FRF Unlocked
bins = glob.glob(self.current_folder_path + "/*.bin")
bins.extend(glob.glob(self.current_folder_path + "/*.frf"))
self.options["bins"] = self.current_folder_path
elif self.action_choice.GetSelection() == 3:
# Unlock ECU
bins = glob.glob(
self.current_folder_path
+ "/*"
+ self.flash_info.patch_box_code
+ "*.frf"
)
self.options["bins"] = self.current_folder_path
elif self.action_choice.GetSelection() == 4:
# Unmodified flash
bins = glob.glob(self.current_folder_path + "/*.bin")
bins.extend(glob.glob(self.current_folder_path + "/*.frf"))
self.options["bins"] = self.current_folder_path

write_config(self.options)

bins.sort(key=path.getmtime, reverse=True)

bin_objects = []
Expand Down Expand Up @@ -417,7 +500,7 @@ def update_callback(self, **kwargs):
else:
wx.CallAfter(self.threaded_callback, kwargs["logger_status"], "0", 0)

def flash_bin(self, get_info=True):
def flash_bin(self, get_info=True, should_patch_cboot=False):
(interface, interface_path) = split_interface_name(self.options["interface"])
if module_selection_is_dsg(self.module_choice.GetSelection()):
flash_utils = dsg_flash_utils
Expand Down Expand Up @@ -487,7 +570,7 @@ def flash_bin(self, get_info=True):
self.input_blocks,
self.update_callback,
interface,
False,
should_patch_cboot,
interface_path,
),
)
Expand Down
2 changes: 1 addition & 1 deletion lib/modules/simos18.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ def s18_block_transfer_sizes_patch(block_number: int, address: int) -> int:
s18_iv,
s18_block_transfer_sizes_patch,
block_names_frf_s18,
"8V0906259H",
"8V0906259H__0001",
4,
internal_path("docs", "patch.bin"),
block_identifiers_simos,
Expand Down
2 changes: 1 addition & 1 deletion lib/modules/simos1810.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ def s1810_block_transfer_sizes_patch(block_number: int, address: int) -> int:
s1810_iv,
s1810_block_transfer_sizes_patch,
block_names_frf_s1810,
"5G0906259Q", # Patch boxcode
"5G0906259Q__0005", # Patch boxcode
2, # Patch blocknumber
internal_path("docs", "patch_1810.bin"), # patch data
block_identifiers_simos,
Expand Down
3 changes: 3 additions & 0 deletions lib/patch_cboot.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ def patch_cboot(cboot_binary: bytes):
if third_address != -1:
print("Too many matches")
return cboot_binary
elif first_address == -1 or second_address == -1:
print("Could not find needle for CBOOT patching. Already patched?")
return cboot_binary
else:
cboot_binary[first_address : first_address + len(needle_bytes)] = patch_bytes
cboot_binary[second_address : second_address + len(needle_bytes)] = patch_bytes
Expand Down

0 comments on commit 867e391

Please sign in to comment.