Skip to content

Add flashing for SD-616F/T#267

Merged
superg merged 16 commits intosuperg:mainfrom
MoriGM:main
Aug 2, 2025
Merged

Add flashing for SD-616F/T#267
superg merged 16 commits intosuperg:mainfrom
MoriGM:main

Conversation

@MoriGM
Copy link
Contributor

@MoriGM MoriGM commented Jul 23, 2025

Summary by CodeRabbit

  • New Features

    • Added support for flashing SD616 drives with a new command and flashing method.
    • Expanded firmware flashing capabilities to handle multiple device variants.
  • Improvements

    • Updated command descriptions and help output for clearer guidance.
    • Enhanced modularity and flexibility of firmware flashing operations.
    • Improved consistency in command naming and operation codes for firmware flashing.

Copy link
Owner

@superg superg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this is basically MT1339 flasher with different block size and 'custom' END marker.

Instead of copying functionality I suggest to reuse already available routines and just do firmware file preprocessing like I explained in the detailed comments.

Please talk to me if something is unclear, also let me know if you would rather have me separate out the function myself, I can prepare it for you so you just reuse it.

Comment on lines +35 to +39
memcpy(&shifted_firmware_data, &firmware_data[0], block_size);
memcpy(&shifted_firmware_data[block_size], &firmware_data[(block_size)-0x400], 0x400);
memcpy(&shifted_firmware_data[block_size + 0x400], &firmware_data[block_size], block_size - 0x800);
memcpy(&shifted_firmware_data[block_size * 2], &firmware_data[(block_size * 2) - 0x800], 0x800);
memcpy(&shifted_firmware_data[block_size * 2 + 0x800], &firmware_data[block_size + 0x400], block_size - 0xc00);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be simplified to:

memcpy(&shifted_firmware_data[0], &firmware_data[0], block_size);
memcpy(&shifted_firmware_data[block_size], &firmware_data[block_size - 0x400], block_size - 0x400);
memcpy(&shifted_firmware_data[block_size * 2], &firmware_data[block_size * 2 - 0x800], 0x800);
memcpy(&shifted_firmware_data[block_size * 2 + 0x800], &firmware_data[block_size + 0x400], block_size - 0xc00);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the not needed copy

Comment on lines +41 to +58
uint32_t offset = 0;
while(offset < shifted_firmware_data.size())
{
uint32_t offset_next = offset + block_size;

LOGC_RF("[{:3}%] flashing: [{:08X} .. {:08X})", 100 * offset / (uint32_t)shifted_firmware_data.size(), offset, offset + read_size);

FLASH_SD616_Mode mode = offset == 0 ? FLASH_SD616_Mode::START : (offset_next < shifted_firmware_data.size() ? FLASH_SD616_Mode::CONTINUE : FLASH_SD616_Mode::END);

SPTD::Status status = cmd_flash_sd616(*ctx.sptd, &shifted_firmware_data[offset], read_size, 0x01, mode);
if(status.status_code)
throw_line("failed to flash firmware, SCSI ({})", SPTD::StatusMessage(status));

offset = offset_next;
}

LOGC_RF("");
LOGC("flashing success");
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a copy-paste of mt1339 flashing, instead of duplicating the code, separate out the code from redumper_flash_mt1339() function into another function in the same file and reuse this function, something like:

#include <span>

//...

export void flash_mt1339(SPTD &sptd, const std::span<const uint8_t> firmware_data, uint32_t block_size, FLASH_MT1339_Mode end_mode)
{
    uint32_t offset = 0;
    while(offset < firmware_data.size())
    {
        uint32_t size = std::min(block_size, (uint32_t)(firmware_data.size() - offset));
        uint32_t offset_next = offset + size;

        LOGC_RF("[{:3}%] flashing: [{:08X} .. {:08X})", 100 * offset / (uint32_t)firmware_data.size(), offset, offset + size);

        FLASH_MT1339_Mode mode = offset == 0 ? FLASH_MT1339_Mode::START : (offset_next < firmware_data.size() ? FLASH_MT1339_Mode::CONTINUE : end_mode);

        SPTD::Status status = cmd_flash_mt1339(sptd, &firmware_data[offset], size, 0x01, mode);
        if(status.status_code)
            throw_line("failed to flash firmware, SCSI ({})", SPTD::StatusMessage(status));

        offset = offset_next;
    }

    LOGC_RF("");
    LOGC("flashing success");
}

Now, in your code you call it:

import drive.flash.mt1339;

//...

flash_mt1339(*ctx.sptd, shifted_firmware_data, block_size, FLASH_MT1339_Mode::END_SAMSUNG);

And in original redumper_flash_mt1339() code you call it:

flash_mt1339(*ctx.sptd, firmware_data, 0xFC00, FLASH_MT1339_Mode::END);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reworked as two functions calling the flash function

scsi/cmd.ixx Outdated
return sptd.sendCommand(&cdb, sizeof(cdb), (void *)data, data_size, true);
}

export SPTD::Status cmd_flash_sd616(SPTD &sptd, const uint8_t *data, uint32_t data_size, uint8_t unknown1, FLASH_SD616_Mode mode)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is not needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was removed

scsi/mmc.ixx Outdated
PLEXTOR_RESET = 0xEE,
ASUS_READ_CACHE = 0xF1,
MT1339_FLASH_FIRMWARE = 0xFF
SAMSUNG_FLASH_FIRMWARE = 0xFF
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Revert this change, it's still MT1339.

Copy link
Contributor

@Deterous Deterous Jul 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For what it's worth, other Samsung drives (Kreon has MT1309e) have been able to be flashed using the flash::mt1339 command.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From what I looked into. Samsung used FF for flashing while LiteOn used DF an HL used FD for flashing the MT1339.
This only works for flashing Samsung drives.

scsi/mmc.ixx Outdated
{
START = 0x00,
CONTINUE = 0xFF,
END = 0x02
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this enum and add END_SAMSUNG = 0x02 to FLASH_MT1339_Mode enum.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is now one enum

scsi/mmc.ixx Outdated
END = 0x02
};

export struct CDB12_FlashSD616
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this struct.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed it

constexpr uint32_t block_size = 0x10000;
uint32_t read_size = 0xFFFF;

std::array<uint8_t, 0x30000> shifted_firmware_data{};
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please change this to std::vector, otherwise it's ~200Kb on the stack.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is now a vector

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jul 30, 2025

Walkthrough

This change refactors and generalizes the firmware flashing logic for MT1339 and SD616 drives. It renames modules and types from "mt1339" to "tsst", introduces a modular flashing function supporting multiple end modes, and adds a new flashing routine for SD616 drives. Command registration, help text, and related SCSI command structures are updated accordingly.

Changes

Cohort / File(s) Change Summary
CMake Indentation
CMakeLists.txt
Corrected indentation for the drive/flash_mt1339.ixx entry in target_sources(redumper). No functional changes.
Command Help Text
options.ixx
Updated help text for the "flash::mt1339" command and added a new "flash::sd616" command with descriptions.
Command Registration & Imports
redumper.ixx
Changed import from drive.flash.mt1339 to drive.flash.tsst. Registered new command "flash::sd616" with its handler.
SCSI Command Refactor
scsi/cmd.ixx, scsi/mmc.ixx
Renamed SCSI flash command types and enums from "mt1339" to "tsst", updated operation codes, and added a new mode for SD616.
Drive Flash Logic Modularization
drive/flash_mt1339.ixx
Renamed module to drive.flash.tsst. Refactored flashing logic into a reusable function. Added support for SD616 flashing with data rearrangement. Exported new flashing functions.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Redumper
    participant DriveFlashTsst
    participant SPTD
    participant SCSI

    User->>Redumper: Selects "flash::mt1339" or "flash::sd616" command
    Redumper->>DriveFlashTsst: Calls redumper_flash_mt1339 or redumper_flash_sd616
    alt MT1339
        DriveFlashTsst->>DriveFlashTsst: Calls flash_mt1339 (block_size=0xFC00, end_mode=END)
    else SD616
        DriveFlashTsst->>DriveFlashTsst: Rearranges firmware data
        DriveFlashTsst->>DriveFlashTsst: Calls flash_mt1339 (block_size=0x10000, end_mode=END_SAMSUNG)
    end
    loop For each firmware block
        DriveFlashTsst->>SPTD: Issue flash command (cmd_flash_tsst)
        SPTD->>SCSI: Send command
        SCSI-->>SPTD: Status
        SPTD-->>DriveFlashTsst: Status
        DriveFlashTsst-->>Redumper: Progress/Error
    end
    Redumper-->>User: Completion/Error message
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

Poem

A bunny with firmware, so clever and bright,
Hopped through the code in the soft glowing light.
With blocks rearranged and new modes in its paw,
It flashed SD616 with a bug-free hurrah!
Now TSST and friends can all take a spin—
This rabbit’s refactor is ready to win!
🐇✨

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d596c31 and f1d5cab.

📒 Files selected for processing (1)
  • drive/flash_mt1339.ixx (4 hunks)
🔇 Additional comments (5)
drive/flash_mt1339.ixx (5)

5-9: LGTM! Module refactoring supports generalization.

The module rename from mt1339 to tsst and addition of <span> and <vector> headers appropriately support the generalization to handle multiple TSST drive types.


24-49: Excellent refactoring to support multiple drive types.

The generalized function design is well-implemented:

  • Modern std::span parameter for firmware data
  • Configurable block size and end mode for different drive variants
  • Dynamic mode selection maintains correct state transitions
  • Preserved error handling and progress logging

51-54: Clean backward compatibility wrapper.

The wrapper preserves the original MT1339 interface while leveraging the new generic implementation. Parameters (block size 0xFC00, END mode) are appropriate for MT1339 drives.


60-61: Good fix for bounds checking.

The exact size validation addresses the previous concern about potential out-of-bounds access. The 128KB requirement is clearly enforced.


69-69: Appropriate parameters for SD616 flashing.

The block size (0x10000) and END_SAMSUNG mode are correctly configured for SD616 drive requirements.

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (7)
scsi/mmc.ixx (3)

31-31: Address previous review feedback on operation code naming.

A previous review comment suggested reverting this change to MT1339_FLASH_FIRMWARE. While the response mentioned Samsung using different operation codes (FF vs DF/FD), please clarify if this rename is necessary or if the existing MT1339 constant should be reused.


836-841: Address previous review feedback on enum consolidation.

A previous review comment suggested removing this enum and adding END_SAMSUNG = 0x02 to the existing FLASH_MT1339_Mode enum instead. Please clarify if separate enums are necessary or if consolidation is preferred.


843-854: Address previous review feedback on struct consolidation.

A previous review comment suggested removing this struct. Please clarify if the different field layout (particularly the unknown1 field placement) necessitates a separate struct or if the existing CDB12_FlashMT1339 can be reused.

drive/flash_sd616.ixx (3)

34-34: Move large array from stack to heap.

Using std::array<uint8_t, 0x30000> puts ~192KB on the stack, which should be avoided.

-std::array<uint8_t, 0x30000> shifted_firmware_data{};
+std::vector<uint8_t> shifted_firmware_data(0x30000);

35-39: Simplify and fix the data rearrangement logic.

The current memcpy operations can be simplified and some appear incorrect compared to the suggested implementation in past reviews.

-memcpy(&shifted_firmware_data, &firmware_data[0], block_size);
-memcpy(&shifted_firmware_data[block_size], &firmware_data[(block_size)-0x400], 0x400);
-memcpy(&shifted_firmware_data[block_size + 0x400], &firmware_data[block_size], block_size - 0x800);
-memcpy(&shifted_firmware_data[block_size * 2], &firmware_data[(block_size * 2) - 0x800], 0x800);
-memcpy(&shifted_firmware_data[block_size * 2 + 0x800], &firmware_data[block_size + 0x400], block_size - 0xc00);
+memcpy(&shifted_firmware_data[0], &firmware_data[0], block_size);
+memcpy(&shifted_firmware_data[block_size], &firmware_data[block_size - 0x400], block_size - 0x400);
+memcpy(&shifted_firmware_data[block_size * 2], &firmware_data[block_size * 2 - 0x800], 0x800);
+memcpy(&shifted_firmware_data[block_size * 2 + 0x800], &firmware_data[block_size + 0x400], block_size - 0xc00);

41-58: Extract common flashing logic to avoid code duplication.

This flashing loop duplicates logic from the MT1339 implementation. Consider extracting the common functionality as suggested in previous reviews.

The past review comment suggested creating a shared flash_mt1339 function that both implementations could use, with different end modes and block sizes. This would reduce code duplication and improve maintainability.

scsi/cmd.ixx (1)

557-565: Consider the previous review feedback about necessity.

A past review comment indicated this function is not needed. However, this appears to be the main feature for SD-616F/T flashing support as mentioned in the PR objectives. Please verify if this function is actually required or if the flashing can be handled through the existing cmd_flash_mt1339 function.

🧹 Nitpick comments (1)
drive/flash_sd616.ixx (1)

46-46: Use consistent variable in logging.

The logging uses read_size but should probably use block_size for clarity and consistency.

-LOGC_RF("[{:3}%] flashing: [{:08X} .. {:08X})", 100 * offset / (uint32_t)shifted_firmware_data.size(), offset, offset + read_size);
+LOGC_RF("[{:3}%] flashing: [{:08X} .. {:08X})", 100 * offset / (uint32_t)shifted_firmware_data.size(), offset, offset + block_size);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ec4c85e and 3d5eabc.

📒 Files selected for processing (6)
  • CMakeLists.txt (1 hunks)
  • drive/flash_sd616.ixx (1 hunks)
  • options.ixx (1 hunks)
  • redumper.ixx (2 hunks)
  • scsi/cmd.ixx (1 hunks)
  • scsi/mmc.ixx (2 hunks)
🔇 Additional comments (6)
options.ixx (1)

355-355: LGTM!

The help text addition follows the established pattern and clearly describes the new Samsung SD-616F/T drive firmware flasher command.

CMakeLists.txt (1)

140-140: LGTM!

The build configuration correctly includes the new flash_sd616.ixx module file, following the established pattern for similar modules.

redumper.ixx (2)

30-30: LGTM!

The import statement correctly includes the new drive.flash.sd616 module following the established pattern.


152-152: LGTM!

The command registration follows the same pattern as the MT1339 flasher with appropriate settings: requires drive but not ready state, no auto-selection, and no image name requirements, which are all correct for a firmware flashing operation.

drive/flash_sd616.ixx (1)

27-29: LGTM!

The firmware reading and size validation logic is correct and appropriate for the expected 0x20000 byte firmware size.

scsi/cmd.ixx (1)

547-555: LGTM! Good refactoring of the flash command.

The renaming to SAMSUNG_FLASH_FIRMWARE and explicit field initialization improve code clarity and maintainability.

Comment on lines +31 to +32
constexpr uint32_t block_size = 0x10000;
uint32_t read_size = 0xFFFF;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix variable inconsistency.

The read_size variable is set to 0xFFFF but block_size is 0x10000. This inconsistency could lead to issues as they're used in different places.

 constexpr uint32_t block_size = 0x10000;
-uint32_t read_size = 0xFFFF;

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In drive/flash_sd616.ixx around lines 31 to 32, the variable read_size is set to
0xFFFF while block_size is 0x10000, causing inconsistency. To fix this, set
read_size to the same value as block_size (0x10000) to ensure consistent usage
and avoid potential issues.


FLASH_SD616_Mode mode = offset == 0 ? FLASH_SD616_Mode::START : (offset_next < shifted_firmware_data.size() ? FLASH_SD616_Mode::CONTINUE : FLASH_SD616_Mode::END);

SPTD::Status status = cmd_flash_sd616(*ctx.sptd, &shifted_firmware_data[offset], read_size, 0x01, mode);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Use block_size instead of read_size in flash command.

The command should use block_size (0x10000) rather than read_size (0xFFFF) for consistency with the block-based processing.

-SPTD::Status status = cmd_flash_sd616(*ctx.sptd, &shifted_firmware_data[offset], read_size, 0x01, mode);
+SPTD::Status status = cmd_flash_sd616(*ctx.sptd, &shifted_firmware_data[offset], block_size, 0x01, mode);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
SPTD::Status status = cmd_flash_sd616(*ctx.sptd, &shifted_firmware_data[offset], read_size, 0x01, mode);
SPTD::Status status = cmd_flash_sd616(*ctx.sptd, &shifted_firmware_data[offset], block_size, 0x01, mode);
🤖 Prompt for AI Agents
In drive/flash_sd616.ixx at line 50, replace the use of read_size with
block_size in the call to cmd_flash_sd616 to ensure the flash command uses the
correct block size (0x10000) instead of the inconsistent read_size (0xFFFF).
This aligns the command with the block-based processing approach.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
drive/flash_tsst.ixx (2)

32-34: Consider using named constants for magic numbers.

The magic numbers 0xFC00 should be defined as named constants to improve code maintainability and readability.

+    constexpr uint32_t DEFAULT_BLOCK_SIZE = 0xFC00;
+    constexpr uint32_t DEFAULT_READ_SIZE = 0xFC00;
+    
-    uint32_t block_size = 0xFC00;
-    uint32_t read_size = 0xFC00;
+    uint32_t block_size = DEFAULT_BLOCK_SIZE;
+    uint32_t read_size = DEFAULT_READ_SIZE;

36-39: Enhance error message with actual firmware size information.

The error message could be more helpful by including the actual firmware size and expected sizes.

-        throw_line("incorrect firmware size");
+        throw_line("incorrect firmware size: {} bytes, expected 0x20000 (128KB) or 0x40000 (256KB)", firmware_data.size());
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3d5eabc and 33d660d.

⛔ Files ignored due to path filters (1)
  • example.bin is excluded by !**/*.bin
📒 Files selected for processing (7)
  • CMakeLists.txt (1 hunks)
  • drive/flash_mt1339.ixx (0 hunks)
  • drive/flash_tsst.ixx (1 hunks)
  • options.ixx (1 hunks)
  • redumper.ixx (2 hunks)
  • scsi/cmd.ixx (1 hunks)
  • scsi/mmc.ixx (2 hunks)
💤 Files with no reviewable changes (1)
  • drive/flash_mt1339.ixx
✅ Files skipped from review due to trivial changes (2)
  • CMakeLists.txt
  • options.ixx
🚧 Files skipped from review as they are similar to previous changes (3)
  • redumper.ixx
  • scsi/mmc.ixx
  • scsi/cmd.ixx
🔇 Additional comments (3)
drive/flash_tsst.ixx (3)

1-21: LGTM! Clean module structure and comprehensive imports.

The module declaration follows C++20 conventions properly, and the imports cover all necessary dependencies for SCSI operations, file I/O, and logging.


57-73: LGTM! Well-structured flashing loop with proper error handling.

The main flashing loop is well-implemented with:

  • Proper bounds checking using std::min
  • Clear progress reporting with percentage and address ranges
  • Appropriate mode selection logic
  • Good error handling with descriptive SCSI status messages
  • Safe offset advancement

75-79: LGTM! Clean success handling and function termination.

The success logging and return statement are appropriate and maintain consistency with the function's error handling pattern.

Comment on lines +41 to +55
if(firmware_data.size() == 0x20000)
{
block_size = 0x10000;
read_size = 0xFFFF;
end_mode = FLASH_Tsst_Mode::END_128KB;

std::vector<uint8_t> shifted_firmware_data{};
shifted_firmware_data.resize(0x30000);
std::copy(firmware_data.begin(), std::next(firmware_data.begin(), block_size), shifted_firmware_data.begin());
std::copy(std::next(firmware_data.begin(), block_size), std::next(firmware_data.begin(), (block_size * 2) - 0x800), std::next(shifted_firmware_data.begin(), block_size + 0x400));
std::copy(std::next(firmware_data.begin(), (block_size * 2) - 0x800), std::next(firmware_data.begin(), (block_size * 2)), std::next(shifted_firmware_data.begin(), block_size * 2));
std::copy(std::next(firmware_data.begin(), block_size + 0x400), std::next(firmware_data.begin(), (block_size * 2) - 0x800), std::next(shifted_firmware_data.begin(), (block_size * 2) + 0x800));

firmware_data = shifted_firmware_data;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Critical: Verify firmware rearrangement logic and add documentation.

This complex data rearrangement logic lacks documentation and uses multiple magic numbers. The specific offset calculations and copy operations need verification to ensure correctness.

Please verify the firmware rearrangement logic is correct and add documentation explaining:

  1. Why the 128KB firmware needs to be rearranged into 192KB
  2. The purpose of each copy operation and offset calculation
  3. The meaning of magic numbers (0x800, 0x400, etc.)

Consider refactoring with named constants:

+    constexpr uint32_t FIRMWARE_128KB_BLOCK_SIZE = 0x10000;
+    constexpr uint32_t FIRMWARE_128KB_READ_SIZE = 0xFFFF;
+    constexpr uint32_t SHIFTED_FIRMWARE_SIZE = 0x30000;
+    constexpr uint32_t SEGMENT_OFFSET_800 = 0x800;
+    constexpr uint32_t SEGMENT_OFFSET_400 = 0x400;
+    
     if(firmware_data.size() == 0x20000)
     {
-        block_size = 0x10000;
-        read_size = 0xFFFF;
+        block_size = FIRMWARE_128KB_BLOCK_SIZE;
+        read_size = FIRMWARE_128KB_READ_SIZE;
         end_mode = FLASH_Tsst_Mode::END_128KB;
 
         std::vector<uint8_t> shifted_firmware_data{};
-        shifted_firmware_data.resize(0x30000);
+        shifted_firmware_data.resize(SHIFTED_FIRMWARE_SIZE);
         // Add comments explaining each copy operation

Run this script to verify the rearrangement doesn't cause buffer overflows:


🏁 Script executed:

#!/bin/bash
# Verify the firmware rearrangement logic bounds
echo "Analyzing firmware rearrangement bounds:"
echo "Original firmware size: 0x20000 (131072 bytes)"
echo "Shifted firmware size: 0x30000 (196608 bytes)"
echo "Block size: 0x10000 (65536 bytes)"
echo ""
echo "Copy operations analysis:"
echo "1. Copy [0, 0x10000) to [0, 0x10000) - OK"
echo "2. Copy [0x10000, 0x1F800) to [0x10400, 0x1FC00) - Need verification"
echo "3. Copy [0x1F800, 0x20000) to [0x20000, 0x20800) - Need verification" 
echo "4. Copy [0x10400, 0x1F800) to [0x20800, 0x2FC00) - Need verification"

Length of output: 977


Critical: Document and refactor 128 KB firmware rearrangement in drive/flash_tsst.ixx

The four std::copy operations have been verified to stay within the 0x30000 buffer, but the logic remains opaque and littered with magic numbers. Please:

  • Extract all magic values into constexpr–named constants for block size, read size, total buffer size, and segment offsets.
  • Add a doc-comment above the if (firmware_data.size() == …) explaining:
    1. Why 128 KB firmware is expanded to 192 KB.
    2. What each segment represents.
    3. The rationale behind each offset (0x800, 0x400, etc.).
  • Precede each std::copy with an inline comment mapping source and destination ranges.

drive/flash_tsst.ixx:41–55

Suggested diff:

+constexpr uint32_t FIRMWARE_128KB_BLOCK_SIZE = 0x10000;
+constexpr uint32_t FIRMWARE_128KB_READ_SIZE  = 0xFFFF;
+constexpr uint32_t SHIFTED_FIRMWARE_SIZE     = 0x30000;
+constexpr uint32_t SEGMENT_GAP_SMALL         = 0x400;
+constexpr uint32_t SEGMENT_GAP_LARGE         = 0x800;
+
+// Transform 128 KB layout into 192 KB with interleaved padding:
+if (firmware_data.size() == FIRMWARE_128KB_BLOCK_SIZE * 2)
+{
+    block_size = FIRMWARE_128KB_BLOCK_SIZE;
+    read_size  = FIRMWARE_128KB_READ_SIZE;
+    end_mode   = FLASH_Tsst_Mode::END_128KB;
+
+    std::vector<uint8_t> shifted_firmware_data(SHIFTED_FIRMWARE_SIZE);
+    // 1) Copy first 0x10000 bytes to [0x00000…0x10000)
+    std::copy(firmware_data.begin(),
+              firmware_data.begin() + block_size,
+              shifted_firmware_data.begin());
+
+    // 2) Copy next (2*block_size – SEGMENT_GAP_LARGE) bytes to [0x10400…0x1FC00)
+    std::copy(firmware_data.begin() + block_size,
+              firmware_data.begin() + (block_size * 2) - SEGMENT_GAP_LARGE,
+              shifted_firmware_data.begin() + block_size + SEGMENT_GAP_SMALL);
+
+    // 3) Copy last SEGMENT_GAP_LARGE bytes of original to [0x20000…0x20800)
+    std::copy(firmware_data.begin() + (block_size * 2) - SEGMENT_GAP_LARGE,
+              firmware_data.begin() + (block_size * 2),
+              shifted_firmware_data.begin() + (block_size * 2));
+
+    // 4) Fill the gap: copy from [0x10400…0x1F800) into [0x20800…0x2FC00)
+    std::copy(firmware_data.begin() + block_size + SEGMENT_GAP_SMALL,
+              firmware_data.begin() + (block_size * 2) - SEGMENT_GAP_LARGE,
+              shifted_firmware_data.begin() + (block_size * 2) + SEGMENT_GAP_LARGE);
+
+    firmware_data = std::move(shifted_firmware_data);
+}
🤖 Prompt for AI Agents
In drive/flash_tsst.ixx around lines 41 to 55, refactor the 128 KB firmware
rearrangement by replacing all magic numbers with clearly named constexpr
constants for block size, read size, total buffer size, and segment offsets. Add
a detailed doc-comment above the if statement explaining why the 128 KB firmware
is expanded to 192 KB, describing what each segment represents, and clarifying
the rationale behind each offset like 0x800 and 0x400. Additionally, add inline
comments before each std::copy call to explicitly map the source and destination
ranges being copied to improve code clarity and maintainability.

Copy link
Owner

@superg superg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've just looked over it:

  1. we shouldn't delete flash::mt1339 command as it will require README and redump.org wiki updates
  2. you cannot make decision on how to flash based on the firmware file size, that would be a critical mistake if you try to flash 128Kb drive with 256Kb firmware because if there are no any protection mechanisms in place, you will brick the drive.

Please make the changes exactly how I asked in the first review, I will tidy it up and make renames as I see fit.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
drive/flash_mt1339.ixx (1)

6-6: Remove unused include

The <iostream> header appears to be unused in this module. All logging is performed through the imported utils.logger module.

-#include <iostream>
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e89219a and 0620527.

📒 Files selected for processing (5)
  • CMakeLists.txt (1 hunks)
  • drive/flash_mt1339.ixx (4 hunks)
  • options.ixx (1 hunks)
  • redumper.ixx (3 hunks)
  • scsi/mmc.ixx (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • CMakeLists.txt
  • options.ixx
  • redumper.ixx
  • scsi/mmc.ixx
🔇 Additional comments (3)
drive/flash_mt1339.ixx (3)

27-52: Well-structured refactoring for multi-device support

The generalization of the flashing logic with configurable block size and end mode parameters enables support for multiple device variants while maintaining clean, reusable code.


54-57: LGTM! Maintains backward compatibility

The wrapper function preserves the original interface while leveraging the new generic implementation.


64-64: Verify uninitialized buffer region is intentional

The buffer is allocated with 0x30000 bytes but only 0x2FF00 bytes are written, leaving the last 0x100 bytes uninitialized (zero). Please confirm this padding is intentional for SD616 devices.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0620527 and d596c31.

📒 Files selected for processing (2)
  • drive/flash_mt1339.ixx (4 hunks)
  • options.ixx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • options.ixx
🔇 Additional comments (4)
drive/flash_mt1339.ixx (4)

4-12: LGTM! Module refactoring aligns with generalization.

The additional includes support the new data manipulation operations in redumper_flash_sd616, and the module rename from mt1339 to tsst appropriately reflects the generalization to support multiple TSST drive types.


27-52: Excellent refactoring! Generic function improves code reusability.

The extraction of common flashing logic into a parameterized function is well-designed. The dynamic mode selection correctly handles the three phases (START, CONTINUE, end_mode), and the use of std::span provides safe access to firmware data without copying.


54-57: LGTM! Clean wrapper preserves backward compatibility.

The thin wrapper approach maintains the existing interface while leveraging the new generic implementation. The parameters (0xFC00 block size, END mode) match the original hardcoded behavior.


63-64: Good! Bounds checking addresses previous security concern.

The exact size validation properly addresses the previous review comment about missing bounds checking, preventing potential out-of-bounds access.

Comment on lines +66 to +72
std::vector<uint8_t> shifted_firmware_data{};
shifted_firmware_data.resize(0x30000);
std::copy(firmware_data.begin(), std::next(firmware_data.begin(), block_size), shifted_firmware_data.begin());
std::copy(std::next(firmware_data.begin(), block_size), std::next(firmware_data.begin(), (block_size * 2) - 0x800), std::next(shifted_firmware_data.begin(), block_size + 0x400));
std::copy(std::next(firmware_data.begin(), (block_size * 2) - 0x800), std::next(firmware_data.begin(), (block_size * 2)), std::next(shifted_firmware_data.begin(), block_size * 2));
std::copy(std::next(firmware_data.begin(), block_size + 0x400), std::next(firmware_data.begin(), (block_size * 2) - 0x800), std::next(shifted_firmware_data.begin(), (block_size * 2) + 0x800));
return flash_mt1339(*ctx.sptd, shifted_firmware_data, block_size, FLASH_Tsst_Mode::END_SAMSUNG);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add documentation for complex data rearrangement logic.

The firmware data rearrangement using multiple std::copy operations with magic numbers (0x800, 0x400) is difficult to understand without context. Consider adding comments explaining:

  1. Why SD616 requires this specific 128KB → 192KB transformation
  2. What each copy operation accomplishes
  3. The meaning of the magic offsets
+    // SD616 requires firmware data to be rearranged from 128KB to 192KB format:
+    // - First 64KB block: copy as-is
+    // - Second 64KB block: split and rearrange with specific offsets
     std::vector<uint8_t> shifted_firmware_data{};
     shifted_firmware_data.resize(0x30000);
+    
+    // Copy first 64KB block unchanged
     std::copy(firmware_data.begin(), std::next(firmware_data.begin(), block_size), shifted_firmware_data.begin());
+    // Copy second block segment with offset adjustments for SD616 format
     std::copy(std::next(firmware_data.begin(), block_size), std::next(firmware_data.begin(), (block_size * 2) - 0x800), std::next(shifted_firmware_data.begin(), block_size + 0x400));
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
std::vector<uint8_t> shifted_firmware_data{};
shifted_firmware_data.resize(0x30000);
std::copy(firmware_data.begin(), std::next(firmware_data.begin(), block_size), shifted_firmware_data.begin());
std::copy(std::next(firmware_data.begin(), block_size), std::next(firmware_data.begin(), (block_size * 2) - 0x800), std::next(shifted_firmware_data.begin(), block_size + 0x400));
std::copy(std::next(firmware_data.begin(), (block_size * 2) - 0x800), std::next(firmware_data.begin(), (block_size * 2)), std::next(shifted_firmware_data.begin(), block_size * 2));
std::copy(std::next(firmware_data.begin(), block_size + 0x400), std::next(firmware_data.begin(), (block_size * 2) - 0x800), std::next(shifted_firmware_data.begin(), (block_size * 2) + 0x800));
return flash_mt1339(*ctx.sptd, shifted_firmware_data, block_size, FLASH_Tsst_Mode::END_SAMSUNG);
// SD616 requires firmware data to be rearranged from 128KB to 192KB format:
// - First 64KB block: copy as-is
// - Second 64KB block: split and rearrange with specific offsets
std::vector<uint8_t> shifted_firmware_data{};
shifted_firmware_data.resize(0x30000);
// Copy first 64KB block unchanged
std::copy(firmware_data.begin(),
std::next(firmware_data.begin(), block_size),
shifted_firmware_data.begin());
// Copy second block segment with offset adjustments for SD616 format
std::copy(std::next(firmware_data.begin(), block_size),
std::next(firmware_data.begin(), (block_size * 2) - 0x800),
std::next(shifted_firmware_data.begin(), block_size + 0x400));
std::copy(std::next(firmware_data.begin(), (block_size * 2) - 0x800),
std::next(firmware_data.begin(), (block_size * 2)),
std::next(shifted_firmware_data.begin(), block_size * 2));
std::copy(std::next(firmware_data.begin(), block_size + 0x400),
std::next(firmware_data.begin(), (block_size * 2) - 0x800),
std::next(shifted_firmware_data.begin(), (block_size * 2) + 0x800));
return flash_mt1339(*ctx.sptd,
shifted_firmware_data,
block_size,
FLASH_Tsst_Mode::END_SAMSUNG);
🤖 Prompt for AI Agents
In drive/flash_mt1339.ixx around lines 66 to 72, the multiple std::copy
operations rearranging firmware_data use unexplained magic numbers and complex
indexing, making the logic hard to understand. Add clear comments explaining why
the SD616 requires this specific 128KB to 192KB transformation, describe the
purpose of each std::copy call, and clarify the meaning of the magic offsets
like 0x800 and 0x400 to improve code readability and maintainability.

@superg superg merged commit 0946425 into superg:main Aug 2, 2025
8 checks passed
@coderabbitai coderabbitai bot mentioned this pull request Aug 2, 2025
This was referenced Dec 6, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants