diff --git a/.idea/runConfigurations/tmtcclient_Binary_Upload_Serial.xml b/.idea/runConfigurations/tmtcclient_Binary_Upload_Serial.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0f71641f824fd4d2ef324b83f038e96cf4a6d467
--- /dev/null
+++ b/.idea/runConfigurations/tmtcclient_Binary_Upload_Serial.xml
@@ -0,0 +1,24 @@
+<component name="ProjectRunConfigurationManager">
+  <configuration default="false" name="tmtcclient Binary Upload Serial" type="PythonConfigurationType" factoryName="Python" folderName="Serial SD-Card and Image">
+    <module name="tmtc" />
+    <option name="INTERPRETER_OPTIONS" value="" />
+    <option name="PARENT_ENVS" value="true" />
+    <envs>
+      <env name="PYTHONUNBUFFERED" value="1" />
+    </envs>
+    <option name="SDK_HOME" value="" />
+    <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
+    <option name="IS_MODULE_SDK" value="true" />
+    <option name="ADD_CONTENT_ROOTS" value="true" />
+    <option name="ADD_SOURCE_ROOTS" value="true" />
+    <EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
+    <option name="SCRIPT_NAME" value="$PROJECT_DIR$/obsw_tmtc_client.py" />
+    <option name="PARAMETERS" value="-m 5 -c 1" />
+    <option name="SHOW_COMMAND_LINE" value="false" />
+    <option name="EMULATE_TERMINAL" value="true" />
+    <option name="MODULE_MODE" value="false" />
+    <option name="REDIRECT_INPUT" value="false" />
+    <option name="INPUT_FILE" value="" />
+    <method v="2" />
+  </configuration>
+</component>
\ No newline at end of file
diff --git a/.idea/runConfigurations/tmtcclient_Clear_SD_Card_.xml b/.idea/runConfigurations/tmtcclient_Clear_SD_Card_.xml
index c9f7b280f41fdd5de1ad7b2474c6eeb0f5a2dd12..0625478e1096c8e4741c5a679e7f1a5106657c74 100644
--- a/.idea/runConfigurations/tmtcclient_Clear_SD_Card_.xml
+++ b/.idea/runConfigurations/tmtcclient_Clear_SD_Card_.xml
@@ -1,5 +1,5 @@
 <component name="ProjectRunConfigurationManager">
-  <configuration default="false" name="tmtcclient Clear SD-Card " type="PythonConfigurationType" factoryName="Python" folderName="Serial SD-Card">
+  <configuration default="false" name="tmtcclient Clear SD-Card " type="PythonConfigurationType" factoryName="Python" folderName="Serial SD-Card and Image">
     <module name="tmtc" />
     <option name="INTERPRETER_OPTIONS" value="" />
     <option name="PARENT_ENVS" value="true" />
diff --git a/.idea/runConfigurations/tmtcclient_Copy_Bootloader.xml b/.idea/runConfigurations/tmtcclient_Copy_Bootloader.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d91be384b7b6603e6fbb013d2d72767e64c340c3
--- /dev/null
+++ b/.idea/runConfigurations/tmtcclient_Copy_Bootloader.xml
@@ -0,0 +1,24 @@
+<component name="ProjectRunConfigurationManager">
+  <configuration default="false" name="tmtcclient Copy Bootloader" type="PythonConfigurationType" factoryName="Python" folderName="Serial SD-Card and Image">
+    <module name="tmtc" />
+    <option name="INTERPRETER_OPTIONS" value="" />
+    <option name="PARENT_ENVS" value="true" />
+    <envs>
+      <env name="PYTHONUNBUFFERED" value="1" />
+    </envs>
+    <option name="SDK_HOME" value="" />
+    <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
+    <option name="IS_MODULE_SDK" value="true" />
+    <option name="ADD_CONTENT_ROOTS" value="true" />
+    <option name="ADD_SOURCE_ROOTS" value="true" />
+    <EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
+    <option name="SCRIPT_NAME" value="$PROJECT_DIR$/obsw_tmtc_client.py" />
+    <option name="PARAMETERS" value="-m 3 -s Img -o A11S -c 1 -t 4" />
+    <option name="SHOW_COMMAND_LINE" value="false" />
+    <option name="EMULATE_TERMINAL" value="true" />
+    <option name="MODULE_MODE" value="false" />
+    <option name="REDIRECT_INPUT" value="false" />
+    <option name="INPUT_FILE" value="" />
+    <method v="2" />
+  </configuration>
+</component>
\ No newline at end of file
diff --git a/.idea/runConfigurations/tmtcclient_Create_File_Struct_AT91.xml b/.idea/runConfigurations/tmtcclient_Create_File_Struct_AT91.xml
new file mode 100644
index 0000000000000000000000000000000000000000..cc27520bd0fab79801e5e6cb318253da46476c3c
--- /dev/null
+++ b/.idea/runConfigurations/tmtcclient_Create_File_Struct_AT91.xml
@@ -0,0 +1,24 @@
+<component name="ProjectRunConfigurationManager">
+  <configuration default="false" name="tmtcclient Create File Struct AT91" type="PythonConfigurationType" factoryName="Python" folderName="Serial SD-Card and Image">
+    <module name="tmtc" />
+    <option name="INTERPRETER_OPTIONS" value="" />
+    <option name="PARENT_ENVS" value="true" />
+    <envs>
+      <env name="PYTHONUNBUFFERED" value="1" />
+    </envs>
+    <option name="SDK_HOME" value="" />
+    <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
+    <option name="IS_MODULE_SDK" value="true" />
+    <option name="ADD_CONTENT_ROOTS" value="true" />
+    <option name="ADD_SOURCE_ROOTS" value="true" />
+    <EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
+    <option name="SCRIPT_NAME" value="$PROJECT_DIR$/obsw_tmtc_client.py" />
+    <option name="PARAMETERS" value="-m 3 -s SD -o C0A -c 1 -t 2.5" />
+    <option name="SHOW_COMMAND_LINE" value="false" />
+    <option name="EMULATE_TERMINAL" value="true" />
+    <option name="MODULE_MODE" value="false" />
+    <option name="REDIRECT_INPUT" value="false" />
+    <option name="INPUT_FILE" value="" />
+    <method v="2" />
+  </configuration>
+</component>
\ No newline at end of file
diff --git a/.idea/runConfigurations/tmtcclient_Format_SD_Card_.xml b/.idea/runConfigurations/tmtcclient_Format_SD_Card_.xml
index 229b06b851947d5850bb82a02c78a3da28fa5313..050cb977f81f9aebbc5e2509619b6e5bf3a54821 100644
--- a/.idea/runConfigurations/tmtcclient_Format_SD_Card_.xml
+++ b/.idea/runConfigurations/tmtcclient_Format_SD_Card_.xml
@@ -1,5 +1,5 @@
 <component name="ProjectRunConfigurationManager">
-  <configuration default="false" name="tmtcclient Format SD-Card " type="PythonConfigurationType" factoryName="Python" folderName="Serial SD-Card">
+  <configuration default="false" name="tmtcclient Format SD-Card " type="PythonConfigurationType" factoryName="Python" folderName="Serial SD-Card and Image">
     <module name="tmtc" />
     <option name="INTERPRETER_OPTIONS" value="" />
     <option name="PARENT_ENVS" value="true" />
diff --git a/.idea/runConfigurations/tmtcclient_Print_SD_Card.xml b/.idea/runConfigurations/tmtcclient_Print_SD_Card.xml
index 79c0da72a6bb2fa29d3653604b005826903eeb0d..5c359f03920f2de984dfbd0496d6ca80534ebfb2 100644
--- a/.idea/runConfigurations/tmtcclient_Print_SD_Card.xml
+++ b/.idea/runConfigurations/tmtcclient_Print_SD_Card.xml
@@ -1,5 +1,5 @@
 <component name="ProjectRunConfigurationManager">
-  <configuration default="false" name="tmtcclient Print SD-Card" type="PythonConfigurationType" factoryName="Python" folderName="Serial SD-Card">
+  <configuration default="false" name="tmtcclient Print SD-Card" type="PythonConfigurationType" factoryName="Python" folderName="Serial SD-Card and Image">
     <module name="tmtc" />
     <option name="INTERPRETER_OPTIONS" value="" />
     <option name="PARENT_ENVS" value="true" />
diff --git a/config/obsw_config.py b/config/obsw_config.py
index 929e19062d4ea75864b8da507bea34145d6a621b..0bc83a5bd8f598c4e073be6b56874cbd5b2b459d 100644
--- a/config/obsw_config.py
+++ b/config/obsw_config.py
@@ -27,6 +27,7 @@ THERMAL_SENSOR_DEVICE_ID = bytearray([0x44, 0x11, 0x54, 0x00])
 GYRO_DEVICE_ID = bytearray([0x44, 0x11, 0x55, 0x00])
 TEST_TASK_ID = bytearray([0x42, 0x69, 0x42, 0x69])
 SD_CARD_HANDLER_ID = bytearray([0x4D, 0x00, 0x73, 0xAD])
+SW_IMAGE_HANDLER_ID = bytearray([0x4D, 0x00, 0x90, 0x00])
 INTERNAL_ERROR_REPORTER_ID = bytearray([0x53, 0x04, 0x00, 0x00])
 
 # Commands
@@ -155,7 +156,7 @@ def set_globals(args):
     else:
         G_SERVICE = args.service
 
-    G_OP_CODE = args.op_code
+    G_OP_CODE = str(args.op_code)
     if G_OP_CODE.isdigit():
         G_OP_CODE = int(G_OP_CODE)
     else:
diff --git a/tc/obsw_image_handler.py b/tc/obsw_image_handler.py
new file mode 100644
index 0000000000000000000000000000000000000000..4d678b0f6342fc992a3ec2f7881b49da0722a1a9
--- /dev/null
+++ b/tc/obsw_image_handler.py
@@ -0,0 +1,40 @@
+from tmtc_core.tc.obsw_pus_tc_base import PusTelecommand, Deque
+from  tc.obsw_tc_service8 import make_action_id
+from tmtc_core.utility.obsw_logger import get_logger
+from config.obsw_config import SW_IMAGE_HANDLER_ID
+
+LOGGER = get_logger()
+
+
+def generate_copy_bl_sdc_to_flash_packet(ssc: int, from_fram: bool = False,
+                                         object_id: bytearray = SW_IMAGE_HANDLER_ID):
+    app_data = bytearray(object_id)
+    app_data += make_action_id(11)
+    app_data.append(from_fram)
+    return PusTelecommand(service=8, subservice=128, ssc=ssc, app_data=app_data)
+
+
+# Slot values: 0 -> Slot 0, 1 -> Slot 1, 2 -> Update Slot
+def generate_copy_obsw_sdc_to_flash_packet(ssc:int, slot: int,
+                                           object_id: bytearray = SW_IMAGE_HANDLER_ID):
+    app_data = bytearray(object_id)
+    app_data += make_action_id(4)
+    if slot != 0 or slot != 1 or slot != 2:
+        LOGGER.error("generate_copy_obsw_sdc_to_flash_packet: Invalid slot number!")
+        return None
+    app_data.append(slot)
+    return PusTelecommand(service=8, subservice=128, ssc=ssc, app_data=app_data)
+
+
+def generate_img_handler_packet(service_queue: Deque, op_code: int):
+    # Action ID 4 (Copy SDC to Flash, Software Update Image)
+    if op_code == "A4U":
+        service_queue.appendleft(("print", "Generating command to copy SDC OBSW to flash."))
+        command = generate_copy_obsw_sdc_to_flash_packet(ssc=0, slot=2)
+        service_queue.appendleft(command.pack_command_tuple())
+
+    # Action ID 11 (Copy bootloader from SDC to flash
+    elif op_code == "A11S":
+        service_queue.appendleft(("print", "Generating command to copy SDC bootloader to flash."))
+        command = generate_copy_bl_sdc_to_flash_packet(0)
+        service_queue.appendleft(command.pack_command_tuple())
diff --git a/tc/obsw_pus_tc_packer.py b/tc/obsw_pus_tc_packer.py
index 3dc996bda5149e03082fde21639416999df47e7b..a6f2597fa6ec74e0d635dc70a08c4586efe25b1f 100644
--- a/tc/obsw_pus_tc_packer.py
+++ b/tc/obsw_pus_tc_packer.py
@@ -18,6 +18,7 @@ from tc.obsw_tc_service23_sdcard import pack_service23_commands_into
 from tc.obsw_tc_service20 import pack_service20_test_into
 from tc.obsw_tc_service200 import pack_mode_data, pack_service200_test_into
 from tc.obsw_tc_service5_17 import pack_service5_test_into, pack_service17_test_into
+from tc.obsw_image_handler import generate_img_handler_packet
 from tc.obsw_tc_gps import pack_gps_test_into
 
 from tmtc_core.utility.obsw_logger import get_logger
@@ -53,6 +54,8 @@ class ServiceQueuePacker:
             return pack_service200_test_into(service_queue)
         if service == "Dummy":
             return pack_dummy_device_test_into(service_queue)
+        if service == "Img":
+            return generate_img_handler_packet(service_queue, op_code)
         if service == "GPS0":
             # Object ID: GPS Device
             object_id = g.GPS0_DEVICE_ID
diff --git a/tc/obsw_tc_service23_sdcard.py b/tc/obsw_tc_service23_sdcard.py
index d149523d1974a47efb400c13ca2e87715957407d..d0ac6fad0d23475ed39e5779dac0ae668e7b0e63 100644
--- a/tc/obsw_tc_service23_sdcard.py
+++ b/tc/obsw_tc_service23_sdcard.py
@@ -61,6 +61,10 @@ class FileTransferHelper:
         self.object_id = object_id
         self.tc_queue = tc_queue
         self.file_data = bytearray()
+        self.number_of_packets = 0
+        self.number_of_append_packets = 0
+        self.number_of_create_packets = 1
+        self.number_of_delete_packets = 0
         self.local_filename = ""
         # This will generate a telecommand to delete the old file, if it exists
         self.delete_old_file = False
@@ -90,13 +94,14 @@ class FileTransferHelper:
         """
         self.max_file_data_size = max_file_data_size
 
-    def queue_size(self):
-        return len(self.tc_queue)
+    def file_size(self):
+        return len(self.file_data)
 
     def generate_packets(self, ssc: int):
         if self.transfer_mode == self.TransferMode.DELETE_OLD:
             command = generate_rm_file_srv23_2_packet(self.target_filename, self.target_repository,
                                                       ssc, self.object_id)
+            self.number_of_delete_packets = 1
             ssc += 1
             self.tc_queue.appendleft(command.pack_command_tuple())
         elif self.transfer_mode == self.TransferMode.RENAME_OLD:
@@ -132,6 +137,8 @@ class FileTransferHelper:
         else:
             self.__generate_append_to_file_packets_automatically(
                 rest_of_data, self.max_size_of_app_data, ssc)
+        self.number_of_packets = self.number_of_append_packets + self.number_of_create_packets +\
+                                 self.number_of_delete_packets
 
     def __generate_append_to_file_packets_automatically(
             self, data: bytearray, size_of_data_blocks: int, init_ssc: int):
@@ -170,10 +177,11 @@ class FileTransferHelper:
 
         for i in range(number_of_packets):
             header.append(packet_sequence_number >> 8)
+            self.number_of_append_packets += 1
             header.append(0xFF & packet_sequence_number)
             header += data[i * size_of_data_blocks:(i + 1) * size_of_data_blocks]
 
-            commands = PusTelecommand(service=23, subservice=128, ssc=init_ssc + i,
+            commands = PusTelecommand(service=23, subservice=130, ssc=init_ssc + i,
                                       app_data=header)
             self.tc_queue.appendleft(commands.pack_command_tuple())
 
@@ -183,7 +191,7 @@ class FileTransferHelper:
         header.append(packet_sequence_number >> 8)
         header.append(0xFF & packet_sequence_number)
         header += data[number_of_packets * size_of_data_blocks:len(data)]
-        commands = PusTelecommand(service=23, subservice=128, ssc=init_ssc + packet_sequence_number,
+        commands = PusTelecommand(service=23, subservice=130, ssc=init_ssc + packet_sequence_number,
                                   app_data=header)
         self.tc_queue.appendleft(commands.pack_command_tuple())
 
diff --git a/utility/obsw_binary_uploader.py b/utility/obsw_binary_uploader.py
index d5b394cc6ae311f24144091f4522819c4296a79c..7f34b79ac2a466c4799c3cb0dc5912daed2d0263 100644
--- a/utility/obsw_binary_uploader.py
+++ b/utility/obsw_binary_uploader.py
@@ -48,7 +48,7 @@ def perform_file_upload(com_if: CommunicationInterface, tmtc_printer: TmTcPrinte
         iobc_prompt = False
 
     bootloader_prompt = input("Bootloader (0) or Software Image (1)? [0/1]: ")
-    if bootloader_prompt == 0:
+    if str(bootloader_prompt) == "0":
         bootloader_prompt = True
     else:
         bootloader_prompt = False
@@ -98,24 +98,28 @@ def perform_file_upload(com_if: CommunicationInterface, tmtc_printer: TmTcPrinte
     file_transfer_helper.set_data_from_file(file_path)
     file_transfer_helper.set_to_delete_old_file()
     file_transfer_helper.generate_packets(init_ssc)
-    print_string = str(file_transfer_helper.queue_size()) + " packets generated.."
+    print_string = "BinaryUploader: Detected file size: " + str(file_transfer_helper.file_size())
+    LOGGER.info(print_string)
+    print_string = "BinaryUploader: " + str(file_transfer_helper.number_of_packets) + \
+                   " packets generated with " + \
+                   str(file_transfer_helper.number_of_append_packets) + " append packets."
     LOGGER.info(print_string)
 
     idx = 1
     while tc_queue:
         (tc_packet, tc_info) = tc_queue.pop()
         if not isinstance(tc_packet, str):
-            print_string = "Sending packet " + str(idx)
             idx += 1
+            print_string = "Sending packet " + str(idx) + ".."
             LOGGER.info(print_string)
-            print("Sending packet with length " + str(len(tc_packet)) + " ..")
             com_if.send_telecommand(tc_packet, tc_info)
         elif tc_packet == "print":
             LOGGER.info(tc_info)
 
-        time.sleep(0.5)
+        time.sleep(0.8)
         tm_list = com_if.receive_telemetry()
         for tm_packet in tm_list:
             # gotta configure tm listener for this to work..
             tmtc_printer.print_telemetry(tm_packet)
-    LOGGER.info("All binary packets sent!")
+    print_string = "BinaryUploader: All binary packets were sent!"
+    LOGGER.info(print_string)