mirror of
				https://github.com/mfulz/qmk_firmware.git
				synced 2025-10-31 13:22:31 +01:00 
			
		
		
		
	Update Mass Storage bootloader so that it can support devices with only 4KB bootloader sections by creating a special AUX section before the real bootloader section to store part of the bootloader code.
This commit is contained in:
		
							parent
							
								
									f8a1dc7424
								
							
						
					
					
						commit
						be33d3a515
					
				| @ -28,6 +28,19 @@ | |||||||
|   this software. |   this software. | ||||||
| */ | */ | ||||||
| 
 | 
 | ||||||
|  | #if AUX_BOOT_SECTION_SIZE > 0 | ||||||
|  | 
 | ||||||
|  | #warning Using a AUX bootloader section in addition to the defined bootloader space (see documentation). | ||||||
|  | 
 | ||||||
|  | ; Trampoline to jump over the AUX bootloader section to the start of the bootloader,
 | ||||||
|  | ; on devices where an AUX bootloader section is used.
 | ||||||
|  | .section .boot_aux_trampoline, "ax" | ||||||
|  | .global Boot_AUX_Trampoline
 | ||||||
|  | Boot_AUX_Trampoline: | ||||||
|  | 	jmp BOOT_START_ADDR | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| ; Trampolines to actual API implementations if the target address is outside the
 | ; Trampolines to actual API implementations if the target address is outside the
 | ||||||
| ; range of a rjmp instruction (can happen with large bootloader sections)
 | ; range of a rjmp instruction (can happen with large bootloader sections)
 | ||||||
| .section .apitable_trampolines, "ax" | .section .apitable_trampolines, "ax" | ||||||
|  | |||||||
| @ -61,6 +61,25 @@ USB_ClassInfo_MS_Device_t Disk_MS_Interface = | |||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | void Application_Jump_Check(void) | ||||||
|  | { | ||||||
|  | 	bool JumpToApplication = false; | ||||||
|  | 
 | ||||||
|  | 	#if (BOARD == BOARD_LEONARDO) | ||||||
|  | 		/* Enable pull-up on the IO13 pin so we can use it to select the mode */ | ||||||
|  | 		PORTC |=  (1 << 7); | ||||||
|  | 		Delay_MS(10); | ||||||
|  | 		JumpToApplication |= ((PINC & (1 << 7)) != 0); | ||||||
|  | 		PORTC &= ~(1 << 7); | ||||||
|  | 	#endif | ||||||
|  | 
 | ||||||
|  | 	if (JumpToApplication) | ||||||
|  | 	{ | ||||||
|  | 		// cppcheck-suppress constStatement
 | ||||||
|  | 		((void (*)(void))0x0000)(); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /** Main program entry point. This routine configures the hardware required by the application, then
 | /** Main program entry point. This routine configures the hardware required by the application, then
 | ||||||
|  *  enters a loop to run the application tasks in sequence. |  *  enters a loop to run the application tasks in sequence. | ||||||
|  */ |  */ | ||||||
| @ -85,9 +104,6 @@ static void SetupHardware(void) | |||||||
| 	MCUSR &= ~(1 << WDRF); | 	MCUSR &= ~(1 << WDRF); | ||||||
| 	wdt_disable(); | 	wdt_disable(); | ||||||
| 
 | 
 | ||||||
| 	/* Disable clock division */ |  | ||||||
| 	clock_prescale_set(clock_div_1); |  | ||||||
| 
 |  | ||||||
| 	/* Relocate the interrupt vector table to the bootloader section */ | 	/* Relocate the interrupt vector table to the bootloader section */ | ||||||
| 	MCUCR = (1 << IVCE); | 	MCUCR = (1 << IVCE); | ||||||
| 	MCUCR = (1 << IVSEL); | 	MCUCR = (1 << IVSEL); | ||||||
|  | |||||||
| @ -39,7 +39,6 @@ | |||||||
| 	/* Includes: */ | 	/* Includes: */ | ||||||
| 		#include <avr/io.h> | 		#include <avr/io.h> | ||||||
| 		#include <avr/wdt.h> | 		#include <avr/wdt.h> | ||||||
| 		#include <avr/power.h> |  | ||||||
| 		#include <avr/interrupt.h> | 		#include <avr/interrupt.h> | ||||||
| 		#include <string.h> | 		#include <string.h> | ||||||
| 
 | 
 | ||||||
| @ -67,14 +66,18 @@ | |||||||
| 		#define LEDMASK_USB_BUSY          LEDS_LED2 | 		#define LEDMASK_USB_BUSY          LEDS_LED2 | ||||||
| 
 | 
 | ||||||
| 	/* Function Prototypes: */ | 	/* Function Prototypes: */ | ||||||
| 		static void SetupHardware(void); | 		int main(void) AUX_BOOT_SECTION; | ||||||
| 
 | 
 | ||||||
| 		void EVENT_USB_Device_Connect(void); | 		static void SetupHardware(void) AUX_BOOT_SECTION; | ||||||
| 		void EVENT_USB_Device_Disconnect(void); |  | ||||||
| 		void EVENT_USB_Device_ConfigurationChanged(void); |  | ||||||
| 		void EVENT_USB_Device_ControlRequest(void); |  | ||||||
| 
 | 
 | ||||||
| 		bool CALLBACK_MS_Device_SCSICommandReceived(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); | 		void Application_Jump_Check(void) ATTR_INIT_SECTION(3); | ||||||
|  | 
 | ||||||
|  | 		void EVENT_USB_Device_Connect(void) AUX_BOOT_SECTION; | ||||||
|  | 		void EVENT_USB_Device_Disconnect(void) AUX_BOOT_SECTION; | ||||||
|  | 		void EVENT_USB_Device_ConfigurationChanged(void) AUX_BOOT_SECTION; | ||||||
|  | 		void EVENT_USB_Device_ControlRequest(void) AUX_BOOT_SECTION; | ||||||
|  | 
 | ||||||
|  | 		bool CALLBACK_MS_Device_SCSICommandReceived(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) AUX_BOOT_SECTION; | ||||||
| 
 | 
 | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -12,6 +12,8 @@ | |||||||
|  * |  * | ||||||
|  *  \li Series 7 USB AVRs (AT90USBxxx7) |  *  \li Series 7 USB AVRs (AT90USBxxx7) | ||||||
|  *  \li Series 6 USB AVRs (AT90USBxxx6) |  *  \li Series 6 USB AVRs (AT90USBxxx6) | ||||||
|  |  *  \li Series 4 USB AVRs (ATMEGAxxU4) - <i>See \ref SSec_Aux_Space</i> | ||||||
|  |  *  \li Series 2 USB AVRs (AT90USBxx2, ATMEGAxxU2) - <i>See \ref SSec_Aux_Space</i> | ||||||
|  * |  * | ||||||
|  *  \section Sec_Info USB Information: |  *  \section Sec_Info USB Information: | ||||||
|  * |  * | ||||||
| @ -49,7 +51,7 @@ | |||||||
|  *  firmware image file, to load firmware onto the AVR. |  *  firmware image file, to load firmware onto the AVR. | ||||||
|  * |  * | ||||||
|  *  Out of the box this bootloader builds for the AT90USB1287 with an 8KB bootloader section size, and will fit |  *  Out of the box this bootloader builds for the AT90USB1287 with an 8KB bootloader section size, and will fit | ||||||
|  *  into 8KB of bootloader space. If you wish to alter this size and/or change the AVR model, you will need to |  *  into 6KB of bootloader space. If you wish to alter this size and/or change the AVR model, you will need to | ||||||
|  *  edit the MCU, FLASH_SIZE_KB and BOOT_SECTION_SIZE_KB values in the accompanying makefile. |  *  edit the MCU, FLASH_SIZE_KB and BOOT_SECTION_SIZE_KB values in the accompanying makefile. | ||||||
|  * |  * | ||||||
|  *  When the bootloader is running, the board's LED(s) will flash at regular intervals to distinguish the |  *  When the bootloader is running, the board's LED(s) will flash at regular intervals to distinguish the | ||||||
| @ -100,6 +102,22 @@ | |||||||
|  *  #define BOOTLOADER_ADDRESS_LENGTH          4 |  *  #define BOOTLOADER_ADDRESS_LENGTH          4 | ||||||
|  *  \endcode |  *  \endcode | ||||||
|  * |  * | ||||||
|  |  *  From the application the API support of the bootloader can be detected by reading the FLASH memory bytes located at address | ||||||
|  |  *  \c BOOTLOADER_MAGIC_SIGNATURE_START and comparing them to the value \c BOOTLOADER_MAGIC_SIGNATURE. The class of bootloader | ||||||
|  |  *  can be determined by reading the FLASH memory bytes located at address \c BOOTLOADER_CLASS_SIGNATURE_START and comparing them | ||||||
|  |  *  to the value \c BOOTLOADER_MASS_STORAGE_SIGNATURE. The start address of the bootloader can be retrieved by reading the bytes | ||||||
|  |  *  of FLASH memory starting from address \c BOOTLOADER_ADDRESS_START. | ||||||
|  |  * | ||||||
|  |  *  \subsection SSec_Aux_Space Auxiliary Bootloader Section | ||||||
|  |  *  To make the bootloader function on smaller devices (those with a physical bootloader section of smaller than 6KB) a second | ||||||
|  |  *  section of memory (called the <i>Auxiliary Bootloader Section</i>) is added before the start of the real bootloader section, | ||||||
|  |  *  and is filled with a portion of the bootloader code. This allows smaller devices to run the bootloader, at the cost of an | ||||||
|  |  *  additional portion of the device's FLASH (the bootloader section size in KB subtracted from the 6KB total size). A small | ||||||
|  |  *  trampoline is inserted at the start of the auxiliary section so that the bootloader will run normally in the case of a blank | ||||||
|  |  *  application section. | ||||||
|  |  * | ||||||
|  |  *  On devices supporting a 8KB bootloader section size, the AUX section is not created in the final binary. | ||||||
|  |  * | ||||||
|  *  \subsection SSec_API_MemLayout Device Memory Map |  *  \subsection SSec_API_MemLayout Device Memory Map | ||||||
|  *  The following illustration indicates the final memory map of the device when loaded with the bootloader. |  *  The following illustration indicates the final memory map of the device when loaded with the bootloader. | ||||||
|  * |  * | ||||||
| @ -121,6 +139,16 @@ | |||||||
|  *  |                            | |  *  |                            | | ||||||
|  *  |                            | |  *  |                            | | ||||||
|  *  |                            | |  *  |                            | | ||||||
|  |  *  |                            | | ||||||
|  |  *  +----------------------------+ FLASHEND - BOOT_SECTION_SIZE - BOOT_AUX_SECTION_SIZE | ||||||
|  |  *  | Booloader Start Trampoline | | ||||||
|  |  *  | (Not User App. Accessible) | | ||||||
|  |  *  +----------------------------+ FLASHEND - BOOT_SECTION_SIZE - BOOT_AUX_SECTION_SIZE + 4 | ||||||
|  |  *  |                            | | ||||||
|  |  *  |     Auxiliary Bootloader   | | ||||||
|  |  *  |  Space for Smaller Devices | | ||||||
|  |  *  | (Not User App. Accessible) | | ||||||
|  |  *  |                            | | ||||||
|  *  +----------------------------+ FLASHEND - BOOT_SECTION_SIZE |  *  +----------------------------+ FLASHEND - BOOT_SECTION_SIZE | ||||||
|  *  |                            | |  *  |                            | | ||||||
|  *  |   Bootloader Application   | |  *  |   Bootloader Application   | | ||||||
| @ -138,12 +166,6 @@ | |||||||
|  *  +----------------------------+ FLASHEND |  *  +----------------------------+ FLASHEND | ||||||
|  *  \endverbatim |  *  \endverbatim | ||||||
|  * |  * | ||||||
|  *  Bootloaders reporting a device release revision number of 1.00 or greater are bootloader API enabled. From the application |  | ||||||
|  *  the API support of the bootloader can be detected by reading the FLASH memory bytes located at address \c BOOTLOADER_MAGIC_SIGNATURE_START |  | ||||||
|  *  and comparing them to the value \c BOOTLOADER_MAGIC_SIGNATURE. The class of bootloader can be determined by reading the |  | ||||||
|  *  FLASH memory bytes located at address \c BOOTLOADER_CLASS_SIGNATURE_START and comparing them to the value \c BOOTLOADER_MASS_STORAGE_SIGNATURE. |  | ||||||
|  *  The start address of the bootloader can be retrieved by reading the bytes of FLASH memory starting from address \c BOOTLOADER_ADDRESS_START. |  | ||||||
|  * |  | ||||||
|  *  \section Sec_Options Project Options |  *  \section Sec_Options Project Options | ||||||
|  * |  * | ||||||
|  *  The following defines can be found in this demo, which can control the demo behaviour when defined, or changed in value. |  *  The following defines can be found in this demo, which can control the demo behaviour when defined, or changed in value. | ||||||
|  | |||||||
| @ -69,7 +69,7 @@ | |||||||
| 		#define USE_RAM_DESCRIPTORS | 		#define USE_RAM_DESCRIPTORS | ||||||
| //		#define USE_FLASH_DESCRIPTORS
 | //		#define USE_FLASH_DESCRIPTORS
 | ||||||
| //		#define USE_EEPROM_DESCRIPTORS
 | //		#define USE_EEPROM_DESCRIPTORS
 | ||||||
| //		#define NO_INTERNAL_SERIAL
 | 		#define NO_INTERNAL_SERIAL | ||||||
| 		#define FIXED_CONTROL_ENDPOINT_SIZE      8 | 		#define FIXED_CONTROL_ENDPOINT_SIZE      8 | ||||||
| 		#define DEVICE_STATE_AS_GPIOR            0 | 		#define DEVICE_STATE_AS_GPIOR            0 | ||||||
| 		#define FIXED_NUM_CONFIGURATIONS         1 | 		#define FIXED_NUM_CONFIGURATIONS         1 | ||||||
|  | |||||||
| @ -60,7 +60,7 @@ const USB_Descriptor_Device_t DeviceDescriptor = | |||||||
| 
 | 
 | ||||||
| 	.ManufacturerStrIndex   = NO_DESCRIPTOR, | 	.ManufacturerStrIndex   = NO_DESCRIPTOR, | ||||||
| 	.ProductStrIndex        = NO_DESCRIPTOR, | 	.ProductStrIndex        = NO_DESCRIPTOR, | ||||||
| 	.SerialNumStrIndex      = USE_INTERNAL_SERIAL, | 	.SerialNumStrIndex      = NO_DESCRIPTOR, | ||||||
| 
 | 
 | ||||||
| 	.NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS | 	.NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS | ||||||
| }; | }; | ||||||
| @ -124,17 +124,6 @@ const USB_Descriptor_Configuration_t ConfigurationDescriptor = | |||||||
| 		} | 		} | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /** Language descriptor structure. This descriptor, located in FLASH memory, is returned when the host requests
 |  | ||||||
|  *  the string descriptor with index 0 (the first index). It is actually an array of 16-bit integers, which indicate |  | ||||||
|  *  via the language ID table available at USB.org what languages the device supports for its string descriptors. |  | ||||||
|  */ |  | ||||||
| const USB_Descriptor_String_t LanguageString = |  | ||||||
| { |  | ||||||
| 	.Header                 = {.Size = USB_STRING_LEN(1), .Type = DTYPE_String}, |  | ||||||
| 
 |  | ||||||
| 	.UnicodeString          = {LANGUAGE_ID_ENG} |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| /** This function is called by the library when in device mode, and must be overridden (see library "USB Descriptors"
 | /** This function is called by the library when in device mode, and must be overridden (see library "USB Descriptors"
 | ||||||
|  *  documentation) by the application code so that the address and size of a requested descriptor can be given |  *  documentation) by the application code so that the address and size of a requested descriptor can be given | ||||||
|  *  to the USB library. When the device receives a Get Descriptor request on the control endpoint, this function |  *  to the USB library. When the device receives a Get Descriptor request on the control endpoint, this function | ||||||
| @ -146,29 +135,20 @@ uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, | |||||||
|                                     const void** const DescriptorAddress) |                                     const void** const DescriptorAddress) | ||||||
| { | { | ||||||
| 	const uint8_t DescriptorType = (wValue >> 8); | 	const uint8_t DescriptorType = (wValue >> 8); | ||||||
| 	const uint8_t  DescriptorNumber = (wValue & 0xFF); |  | ||||||
| 
 | 
 | ||||||
| 	const void* Address = NULL; | 	const void* Address = NULL; | ||||||
| 	uint16_t    Size    = NO_DESCRIPTOR; | 	uint16_t    Size    = NO_DESCRIPTOR; | ||||||
| 
 | 
 | ||||||
| 	switch (DescriptorType) | 	/* If/Else If chain compiles slightly smaller than a switch case */ | ||||||
|  | 	if (DescriptorType == DTYPE_Device) | ||||||
| 	{ | 	{ | ||||||
| 		case DTYPE_Device: |  | ||||||
| 		Address = &DeviceDescriptor; | 		Address = &DeviceDescriptor; | ||||||
| 		Size    = sizeof(USB_Descriptor_Device_t); | 		Size    = sizeof(USB_Descriptor_Device_t); | ||||||
| 			break; | 	} | ||||||
| 		case DTYPE_Configuration: | 	else if (DescriptorType == DTYPE_Configuration) | ||||||
|  | 	{ | ||||||
| 		Address = &ConfigurationDescriptor; | 		Address = &ConfigurationDescriptor; | ||||||
| 		Size    = sizeof(USB_Descriptor_Configuration_t); | 		Size    = sizeof(USB_Descriptor_Configuration_t); | ||||||
| 			break; |  | ||||||
| 		case DTYPE_String: |  | ||||||
| 			if (!(DescriptorNumber)) |  | ||||||
| 			{ |  | ||||||
| 					Address = &LanguageString; |  | ||||||
| 					Size    = pgm_read_byte(&LanguageString.Header.Size); |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			break; |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	*DescriptorAddress = Address; | 	*DescriptorAddress = Address; | ||||||
|  | |||||||
| @ -70,7 +70,7 @@ | |||||||
| 		uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, | 		uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, | ||||||
| 		                                    const uint8_t wIndex, | 		                                    const uint8_t wIndex, | ||||||
| 		                                    const void** const DescriptorAddress) | 		                                    const void** const DescriptorAddress) | ||||||
| 		                                    ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3); | 		                                    ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3) AUX_BOOT_SECTION; | ||||||
| 
 | 
 | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -104,9 +104,6 @@ bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) | |||||||
| 		case SCSI_CMD_READ_CAPACITY_10: | 		case SCSI_CMD_READ_CAPACITY_10: | ||||||
| 			CommandSuccess = SCSI_Command_Read_Capacity_10(MSInterfaceInfo); | 			CommandSuccess = SCSI_Command_Read_Capacity_10(MSInterfaceInfo); | ||||||
| 			break; | 			break; | ||||||
| 		case SCSI_CMD_SEND_DIAGNOSTIC: |  | ||||||
| 			CommandSuccess = SCSI_Command_Send_Diagnostic(MSInterfaceInfo); |  | ||||||
| 			break; |  | ||||||
| 		case SCSI_CMD_WRITE_10: | 		case SCSI_CMD_WRITE_10: | ||||||
| 			CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_WRITE); | 			CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_WRITE); | ||||||
| 			break; | 			break; | ||||||
| @ -116,6 +113,7 @@ bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) | |||||||
| 		case SCSI_CMD_MODE_SENSE_6: | 		case SCSI_CMD_MODE_SENSE_6: | ||||||
| 			CommandSuccess = SCSI_Command_ModeSense_6(MSInterfaceInfo); | 			CommandSuccess = SCSI_Command_ModeSense_6(MSInterfaceInfo); | ||||||
| 			break; | 			break; | ||||||
|  | 		case SCSI_CMD_SEND_DIAGNOSTIC: | ||||||
| 		case SCSI_CMD_START_STOP_UNIT: | 		case SCSI_CMD_START_STOP_UNIT: | ||||||
| 		case SCSI_CMD_TEST_UNIT_READY: | 		case SCSI_CMD_TEST_UNIT_READY: | ||||||
| 		case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL: | 		case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL: | ||||||
| @ -227,33 +225,6 @@ static bool SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInt | |||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** Command processing for an issued SCSI SEND DIAGNOSTIC command. This command performs a quick check of the Dataflash ICs on the
 |  | ||||||
|  *  board, and indicates if they are present and functioning correctly. Only the Self-Test portion of the diagnostic command is |  | ||||||
|  *  supported. |  | ||||||
|  * |  | ||||||
|  *  \param[in] MSInterfaceInfo  Pointer to the Mass Storage class interface structure that the command is associated with |  | ||||||
|  * |  | ||||||
|  *  \return Boolean true if the command completed successfully, false otherwise. |  | ||||||
|  */ |  | ||||||
| static bool SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) |  | ||||||
| { |  | ||||||
| 	/* Check to see if the SELF TEST bit is not set */ |  | ||||||
| 	if (!(MSInterfaceInfo->State.CommandBlock.SCSICommandData[1] & (1 << 2))) |  | ||||||
| 	{ |  | ||||||
| 		/* Only self-test supported - update SENSE key and fail the command */ |  | ||||||
| 		SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST, |  | ||||||
| 		               SCSI_ASENSE_INVALID_FIELD_IN_CDB, |  | ||||||
| 		               SCSI_ASENSEQ_NO_QUALIFIER); |  | ||||||
| 
 |  | ||||||
| 		return false; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	/* Succeed the command and update the bytes transferred counter */ |  | ||||||
| 	MSInterfaceInfo->State.CommandBlock.DataTransferLength = 0; |  | ||||||
| 
 |  | ||||||
| 	return true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /** Command processing for an issued SCSI READ (10) or WRITE (10) command. This command reads in the block start address
 | /** Command processing for an issued SCSI READ (10) or WRITE (10) command. This command reads in the block start address
 | ||||||
|  *  and total number of blocks to process, then calls the appropriate low-level Dataflash routine to handle the actual |  *  and total number of blocks to process, then calls the appropriate low-level Dataflash routine to handle the actual | ||||||
|  *  reading and writing of the data. |  *  reading and writing of the data. | ||||||
|  | |||||||
| @ -42,7 +42,6 @@ | |||||||
| 
 | 
 | ||||||
| 		#include <LUFA/Drivers/USB/USB.h> | 		#include <LUFA/Drivers/USB/USB.h> | ||||||
| 
 | 
 | ||||||
| 		#include "../BootloaderMassStorage.h" |  | ||||||
| 		#include "../Descriptors.h" | 		#include "../Descriptors.h" | ||||||
| 		#include "VirtualFAT.h" | 		#include "VirtualFAT.h" | ||||||
| 
 | 
 | ||||||
| @ -69,16 +68,15 @@ | |||||||
| 		#define DEVICE_TYPE_BLOCK   0x00 | 		#define DEVICE_TYPE_BLOCK   0x00 | ||||||
| 
 | 
 | ||||||
| 	/* Function Prototypes: */ | 	/* Function Prototypes: */ | ||||||
| 		bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); | 		bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) AUX_BOOT_SECTION; | ||||||
| 
 | 
 | ||||||
| 		#if defined(INCLUDE_FROM_SCSI_C) | 		#if defined(INCLUDE_FROM_SCSI_C) | ||||||
| 			static bool SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); | 			static bool SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) AUX_BOOT_SECTION; | ||||||
| 			static bool SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); | 			static bool SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) AUX_BOOT_SECTION; | ||||||
| 			static bool SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); | 			static bool SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) AUX_BOOT_SECTION; | ||||||
| 			static bool SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); |  | ||||||
| 			static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo, | 			static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo, | ||||||
| 			                                      const bool IsDataRead); | 			                                      const bool IsDataRead) AUX_BOOT_SECTION; | ||||||
| 			static bool SCSI_Command_ModeSense_6(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); | 			static bool SCSI_Command_ModeSense_6(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) AUX_BOOT_SECTION; | ||||||
| 		#endif | 		#endif | ||||||
| 
 | 
 | ||||||
| #endif | #endif | ||||||
|  | |||||||
| @ -151,26 +151,28 @@ static void WriteVirtualBlock(const uint16_t BlockNumber) | |||||||
| 
 | 
 | ||||||
| 	if ((BlockNumber >= 4) && (BlockNumber < (4 + FILE_SECTORS(FIRMWARE_FILE_SIZE_BYTES)))) | 	if ((BlockNumber >= 4) && (BlockNumber < (4 + FILE_SECTORS(FIRMWARE_FILE_SIZE_BYTES)))) | ||||||
| 	{ | 	{ | ||||||
|  | 		#if (FLASHEND > 0xFFFF) | ||||||
| 		uint32_t WriteFlashAddress = (uint32_t)(BlockNumber - 4) * SECTOR_SIZE_BYTES; | 		uint32_t WriteFlashAddress = (uint32_t)(BlockNumber - 4) * SECTOR_SIZE_BYTES; | ||||||
|  | 		#else | ||||||
|  | 		uint16_t WriteFlashAddress = (uint16_t)(BlockNumber - 4) * SECTOR_SIZE_BYTES; | ||||||
|  | 		#endif | ||||||
| 
 | 
 | ||||||
| 		for (uint16_t i = 0; i < SECTOR_SIZE_BYTES; i += 2) | 		for (uint16_t i = 0; i < SECTOR_SIZE_BYTES; i += 2) | ||||||
| 		{ | 		{ | ||||||
| 			if ((WriteFlashAddress % SPM_PAGESIZE) == 0) | 			if ((WriteFlashAddress % SPM_PAGESIZE) == 0) | ||||||
| 			{ | 			{ | ||||||
| 				/* Erase the given FLASH page, ready to be programmed */ | 				/* Erase the given FLASH page, ready to be programmed */ | ||||||
| 				boot_page_erase(WriteFlashAddress); | 				BootloaderAPI_ErasePage(WriteFlashAddress); | ||||||
| 				boot_spm_busy_wait(); |  | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			/* Write the next data word to the FLASH page */ | 			/* Write the next data word to the FLASH page */ | ||||||
| 			boot_page_fill(WriteFlashAddress, (BlockBuffer[i + 1] << 8) | BlockBuffer[i]); | 			BootloaderAPI_FillWord(WriteFlashAddress, (BlockBuffer[i + 1] << 8) | BlockBuffer[i]); | ||||||
| 			WriteFlashAddress += 2; | 			WriteFlashAddress += 2; | ||||||
| 
 | 
 | ||||||
| 			if ((WriteFlashAddress % SPM_PAGESIZE) == 0) | 			if ((WriteFlashAddress % SPM_PAGESIZE) == 0) | ||||||
| 			{ | 			{ | ||||||
| 				/* Write the filled FLASH page to memory */ | 				/* Write the filled FLASH page to memory */ | ||||||
| 				boot_page_write(WriteFlashAddress - SPM_PAGESIZE); | 				BootloaderAPI_WritePage(WriteFlashAddress - SPM_PAGESIZE); | ||||||
| 				boot_spm_busy_wait(); |  | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| @ -219,10 +221,17 @@ static void ReadVirtualBlock(const uint16_t BlockNumber) | |||||||
| 		default: /* Blocks 4 onwards: Data allocation section */ | 		default: /* Blocks 4 onwards: Data allocation section */ | ||||||
| 			if ((BlockNumber >= 4) && (BlockNumber < (4 + FILE_SECTORS(FIRMWARE_FILE_SIZE_BYTES)))) | 			if ((BlockNumber >= 4) && (BlockNumber < (4 + FILE_SECTORS(FIRMWARE_FILE_SIZE_BYTES)))) | ||||||
| 			{ | 			{ | ||||||
|  | 				#if (FLASHEND > 0xFFFF) | ||||||
| 				uint32_t ReadFlashAddress = (uint32_t)(BlockNumber - 4) * SECTOR_SIZE_BYTES; | 				uint32_t ReadFlashAddress = (uint32_t)(BlockNumber - 4) * SECTOR_SIZE_BYTES; | ||||||
| 
 | 
 | ||||||
| 				for (uint16_t i = 0; i < SECTOR_SIZE_BYTES; i++) | 				for (uint16_t i = 0; i < SECTOR_SIZE_BYTES; i++) | ||||||
| 				  BlockBuffer[i] = pgm_read_byte_far(ReadFlashAddress++); | 				  BlockBuffer[i] = pgm_read_byte_far(ReadFlashAddress++); | ||||||
|  | 				#else | ||||||
|  | 				uint16_t ReadFlashAddress = (uint16_t)(BlockNumber - 4) * SECTOR_SIZE_BYTES; | ||||||
|  | 
 | ||||||
|  | 				for (uint16_t i = 0; i < SECTOR_SIZE_BYTES; i++) | ||||||
|  | 				  BlockBuffer[i] = pgm_read_byte(ReadFlashAddress++); | ||||||
|  | 				#endif | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			break; | 			break; | ||||||
|  | |||||||
| @ -37,9 +37,11 @@ | |||||||
| 
 | 
 | ||||||
| 		#include <LUFA/Drivers/USB/USB.h> | 		#include <LUFA/Drivers/USB/USB.h> | ||||||
| 
 | 
 | ||||||
|  | 		#include "../BootloaderAPI.h" | ||||||
|  | 
 | ||||||
| 	/* Macros: */ | 	/* Macros: */ | ||||||
| 		/** Size of the virtual FIRMWARE.BIN file in bytes. */ | 		/** Size of the virtual FIRMWARE.BIN file in bytes. */ | ||||||
| 		#define FIRMWARE_FILE_SIZE_BYTES  (FLASHEND - (FLASHEND - BOOT_START_ADDR)) | 		#define FIRMWARE_FILE_SIZE_BYTES  (FLASHEND - (FLASHEND - BOOT_START_ADDR) - AUX_BOOT_SECTION_SIZE) | ||||||
| 
 | 
 | ||||||
| 		/** Number of sectors that comprise a single logical disk cluster. */ | 		/** Number of sectors that comprise a single logical disk cluster. */ | ||||||
| 		#define SECTOR_PER_CLUSTER        4 | 		#define SECTOR_PER_CLUSTER        4 | ||||||
| @ -144,16 +146,16 @@ | |||||||
| 		#if defined(INCLUDE_FROM_VIRTUAL_FAT_C) | 		#if defined(INCLUDE_FROM_VIRTUAL_FAT_C) | ||||||
| 			static void UpdateFAT12ClusterEntry(uint8_t* const FATTable, | 			static void UpdateFAT12ClusterEntry(uint8_t* const FATTable, | ||||||
| 			                                    const uint16_t Index, | 			                                    const uint16_t Index, | ||||||
| 			                                    const uint16_t ChainEntry); | 			                                    const uint16_t ChainEntry) AUX_BOOT_SECTION; | ||||||
| 			static void WriteVirtualBlock(const uint16_t BlockNumber); | 			static void WriteVirtualBlock(const uint16_t BlockNumber) AUX_BOOT_SECTION; | ||||||
| 			static void ReadVirtualBlock(const uint16_t BlockNumber); | 			static void ReadVirtualBlock(const uint16_t BlockNumber) AUX_BOOT_SECTION; | ||||||
| 		#endif | 		#endif | ||||||
| 
 | 
 | ||||||
| 		void VirtualFAT_WriteBlocks(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo, | 		void VirtualFAT_WriteBlocks(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo, | ||||||
| 		                            const uint32_t BlockAddress, | 		                            const uint32_t BlockAddress, | ||||||
| 		                            uint16_t TotalBlocks); | 		                            uint16_t TotalBlocks) AUX_BOOT_SECTION; | ||||||
| 
 | 
 | ||||||
| 		void VirtualFAT_ReadBlocks(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo, | 		void VirtualFAT_ReadBlocks(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo, | ||||||
| 		                           const uint32_t BlockAddress, | 		                           const uint32_t BlockAddress, | ||||||
| 		                           uint16_t TotalBlocks); | 		                           uint16_t TotalBlocks) AUX_BOOT_SECTION; | ||||||
| #endif | #endif | ||||||
|  | |||||||
| @ -27,20 +27,33 @@ LD_FLAGS     = -Wl,--section-start=.text=$(BOOT_START_OFFSET) $(BOOT_API_LD_FLAG | |||||||
| # match the target's total FLASH size and the bootloader size set in the
 | # match the target's total FLASH size and the bootloader size set in the
 | ||||||
| # device's fuses.
 | # device's fuses.
 | ||||||
| FLASH_SIZE_KB         = 128 | FLASH_SIZE_KB         = 128 | ||||||
| BOOT_SECTION_SIZE_KB  = 8 | BOOT_SECTION_SIZE_KB  = 4 | ||||||
| 
 | 
 | ||||||
| # Bootloader address calculation formulas
 | # Bootloader address calculation formulas
 | ||||||
| # Do not modify these macros, but rather modify the dependent values above.
 | # Do not modify these macros, but rather modify the dependent values above.
 | ||||||
| CALC_ADDRESS_IN_HEX   = $(shell printf "0x%X" $$(( $(1) )) ) | CALC_ADDRESS_IN_HEX   = $(shell printf "0x%X" $$(( $(1) )) ) | ||||||
| BOOT_START_OFFSET     = $(call CALC_ADDRESS_IN_HEX, ($(FLASH_SIZE_KB) - $(BOOT_SECTION_SIZE_KB)) * 1024 ) | BOOT_START_OFFSET     = $(call CALC_ADDRESS_IN_HEX, ($(FLASH_SIZE_KB) - $(BOOT_SECTION_SIZE_KB)) * 1024 ) | ||||||
| BOOT_SEC_OFFSET       = $(call CALC_ADDRESS_IN_HEX, ($(FLASH_SIZE_KB) * 1024) - $(strip $(1)) ) | BOOT_SEC_OFFSET       = $(call CALC_ADDRESS_IN_HEX, ($(FLASH_SIZE_KB) * 1024) - ($(strip $(1))) ) | ||||||
| 
 | 
 | ||||||
| # Bootloader linker section flags for relocating the API table sections to
 | # Bootloader linker section flags for relocating the API table sections to
 | ||||||
| # known FLASH addresses - these should not normally be user-edited.
 | # known FLASH addresses - these should not normally be user-edited.
 | ||||||
| BOOT_SECTION_LD_FLAG  = -Wl,--section-start=.apitable_$(strip $(1))=$(call BOOT_SEC_OFFSET, $(3)) -Wl,--undefined=BootloaderAPI_$(strip $(2)) | BOOT_SECTION_LD_FLAG  = -Wl,--section-start=$(strip $(1))=$(call BOOT_SEC_OFFSET, $(3)) -Wl,--undefined=$(strip $(2)) | ||||||
| BOOT_API_LD_FLAGS     = $(call BOOT_SECTION_LD_FLAG, trampolines, Trampolines, 96) | BOOT_API_LD_FLAGS     = $(call BOOT_SECTION_LD_FLAG, .apitable_trampolines, BootloaderAPI_Trampolines, 96) | ||||||
| BOOT_API_LD_FLAGS    += $(call BOOT_SECTION_LD_FLAG, jumptable,   JumpTable,   32) | BOOT_API_LD_FLAGS    += $(call BOOT_SECTION_LD_FLAG, .apitable_jumptable,   BootloaderAPI_JumpTable,   32) | ||||||
| BOOT_API_LD_FLAGS    += $(call BOOT_SECTION_LD_FLAG, signatures,  Signatures,  8) | BOOT_API_LD_FLAGS    += $(call BOOT_SECTION_LD_FLAG, .apitable_signatures,  BootloaderAPI_Signatures,  8) | ||||||
|  | 
 | ||||||
|  | # Check if the bootloader needs an AUX section, located before the real bootloader section to store some of the
 | ||||||
|  | # bootloader code. This is required for 32KB and smaller devices, where the actual bootloader is 6KB but the maximum
 | ||||||
|  | # bootloader section size is 4KB. The actual usable application space will be reduced by 6KB for these devices.
 | ||||||
|  | ifeq ($(BOOT_SECTION_SIZE_KB),8) | ||||||
|  |   CC_FLAGS           += -DAUX_BOOT_SECTION='' -DAUX_BOOT_SECTION_SIZE=0 | ||||||
|  | else | ||||||
|  |   AUX_BOOT_SECTION_KB = (6 - $(BOOT_SECTION_SIZE_KB)) | ||||||
|  | 
 | ||||||
|  |   CC_FLAGS           += -DAUX_BOOT_SECTION='__attribute__((section(".boot_aux")))' -DAUX_BOOT_SECTION_SIZE='($(AUX_BOOT_SECTION_KB) * 1024)' | ||||||
|  |   LD_FLAGS           += -Wl,--section-start=.boot_aux=$(call BOOT_SEC_OFFSET, (($(BOOT_SECTION_SIZE_KB) + $(AUX_BOOT_SECTION_KB)) * 1024 - 16)) | ||||||
|  |   LD_FLAGS           += $(call BOOT_SECTION_LD_FLAG, .boot_aux_trampoline, Boot_AUX_Trampoline, ($(BOOT_SECTION_SIZE_KB) + $(AUX_BOOT_SECTION_KB)) * 1024) | ||||||
|  | endif | ||||||
| 
 | 
 | ||||||
| # Default target
 | # Default target
 | ||||||
| all: | all: | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Dean Camera
						Dean Camera