1
0
Fork 0

Squashed 'tmk_core/' changes from caca2c0..dc0e46e

dc0e46e Rename LUFA to LUFA-git
3bfa7fa Remove LUFA-120730
215b764 Merge commit 'afa0f22a9299686fd88f58ce09c5b521ac917e8f' as 'protocol/lufa/LUFA'
afa0f22 Squashed 'protocol/lufa/LUFA/' content from commit def7fca
c0c42fa Remove submodule of LUFA
30f897d Merge commit '87ced33feb74e79c3281dda36eb6d6d153399b41' as 'protocol/usb_hid/USB_Host_Shield_2.0'
87ced33 Squashed 'protocol/usb_hid/USB_Host_Shield_2.0/' content from commit aab4a69
14f6d49 Remove submodule of USB_Host_Shield_2.0

git-subtree-dir: tmk_core
git-subtree-split: dc0e46eaa4367d4e218f8816e3c117895820f07c
This commit is contained in:
tmk 2015-05-13 11:13:10 +09:00
parent 4d116a04e9
commit f6d56675f9
1575 changed files with 421901 additions and 63190 deletions

View file

@ -0,0 +1,76 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaims all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* Bootloader user application API functions.
*/
#include "BootloaderAPI.h"
void BootloaderAPI_ErasePage(const uint32_t Address)
{
boot_page_erase_safe(Address);
boot_spm_busy_wait();
boot_rww_enable();
}
void BootloaderAPI_WritePage(const uint32_t Address)
{
boot_page_write_safe(Address);
boot_spm_busy_wait();
boot_rww_enable();
}
void BootloaderAPI_FillWord(const uint32_t Address, const uint16_t Word)
{
boot_page_fill_safe(Address, Word);
}
uint8_t BootloaderAPI_ReadSignature(const uint16_t Address)
{
return boot_signature_byte_get(Address);
}
uint8_t BootloaderAPI_ReadFuse(const uint16_t Address)
{
return boot_lock_fuse_bits_get(Address);
}
uint8_t BootloaderAPI_ReadLock(void)
{
return boot_lock_fuse_bits_get(GET_LOCK_BITS);
}
void BootloaderAPI_WriteLock(const uint8_t LockBits)
{
boot_lock_bits_set_safe(LockBits);
}

View file

@ -0,0 +1,63 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaims all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* Header file for BootloaderAPI.c.
*/
#ifndef _BOOTLOADER_API_H_
#define _BOOTLOADER_API_H_
/* Includes: */
#include <avr/io.h>
#include <avr/boot.h>
#include <stdbool.h>
#include <LUFA/Common/Common.h>
/* Macros: */
#if AUX_BOOT_SECTION_SIZE > 0
#define AUX_BOOT_SECTION __attribute__((section(".boot_aux")))
#else
#define AUX_BOOT_SECTION
#endif
/* Function Prototypes: */
void BootloaderAPI_ErasePage(const uint32_t Address);
void BootloaderAPI_WritePage(const uint32_t Address);
void BootloaderAPI_FillWord(const uint32_t Address, const uint16_t Word);
uint8_t BootloaderAPI_ReadSignature(const uint16_t Address);
uint8_t BootloaderAPI_ReadFuse(const uint16_t Address);
uint8_t BootloaderAPI_ReadLock(void);
void BootloaderAPI_WriteLock(const uint8_t LockBits);
#endif

View file

@ -0,0 +1,102 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaims all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
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
; range of a rjmp instruction (can happen with large bootloader sections)
.section .apitable_trampolines, "ax"
.global BootloaderAPI_Trampolines
BootloaderAPI_Trampolines:
BootloaderAPI_ErasePage_Trampoline:
jmp BootloaderAPI_ErasePage
BootloaderAPI_WritePage_Trampoline:
jmp BootloaderAPI_WritePage
BootloaderAPI_FillWord_Trampoline:
jmp BootloaderAPI_FillWord
BootloaderAPI_ReadSignature_Trampoline:
jmp BootloaderAPI_ReadSignature
BootloaderAPI_ReadFuse_Trampoline:
jmp BootloaderAPI_ReadFuse
BootloaderAPI_ReadLock_Trampoline:
jmp BootloaderAPI_ReadLock
BootloaderAPI_WriteLock_Trampoline:
jmp BootloaderAPI_WriteLock
BootloaderAPI_UNUSED1:
ret
BootloaderAPI_UNUSED2:
ret
BootloaderAPI_UNUSED3:
ret
BootloaderAPI_UNUSED4:
ret
BootloaderAPI_UNUSED5:
ret
; API function jump table
.section .apitable_jumptable, "ax"
.global BootloaderAPI_JumpTable
BootloaderAPI_JumpTable:
rjmp BootloaderAPI_ErasePage_Trampoline
rjmp BootloaderAPI_WritePage_Trampoline
rjmp BootloaderAPI_FillWord_Trampoline
rjmp BootloaderAPI_ReadSignature_Trampoline
rjmp BootloaderAPI_ReadFuse_Trampoline
rjmp BootloaderAPI_ReadLock_Trampoline
rjmp BootloaderAPI_WriteLock_Trampoline
rjmp BootloaderAPI_UNUSED1 ; UNUSED ENTRY 1
rjmp BootloaderAPI_UNUSED2 ; UNUSED ENTRY 2
rjmp BootloaderAPI_UNUSED3 ; UNUSED ENTRY 3
rjmp BootloaderAPI_UNUSED4 ; UNUSED ENTRY 4
rjmp BootloaderAPI_UNUSED5 ; UNUSED ENTRY 5
; Bootloader table signatures and information
.section .apitable_signatures, "ax"
.global BootloaderAPI_Signatures
BootloaderAPI_Signatures:
.long BOOT_START_ADDR ; Start address of the bootloader
.word 0xDF30 ; Signature for the MS class bootloader, V1
.word 0xDCFB ; Signature for a LUFA class bootloader

View file

@ -0,0 +1,238 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaims all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* Main source file for the Mass Storage class bootloader. This file contains the complete bootloader logic.
*/
#define INCLUDE_FROM_BOOTLOADER_MASSSTORAGE_C
#include "BootloaderMassStorage.h"
/** LUFA Mass Storage Class driver interface configuration and state information. This structure is
* passed to all Mass Storage Class driver functions, so that multiple instances of the same class
* within a device can be differentiated from one another.
*/
USB_ClassInfo_MS_Device_t Disk_MS_Interface =
{
.Config =
{
.InterfaceNumber = INTERFACE_ID_MassStorage,
.DataINEndpoint =
{
.Address = MASS_STORAGE_IN_EPADDR,
.Size = MASS_STORAGE_IO_EPSIZE,
.Banks = 1,
},
.DataOUTEndpoint =
{
.Address = MASS_STORAGE_OUT_EPADDR,
.Size = MASS_STORAGE_IO_EPSIZE,
.Banks = 1,
},
.TotalLUNs = 1,
},
};
/** Flag to indicate if the bootloader should be running, or should exit and allow the application code to run
* via a soft reset. When cleared, the bootloader will abort, the USB interface will shut down and the application
* started via a forced watchdog reset.
*/
bool RunBootloader = true;
/** Magic lock for forced application start. If the HWBE fuse is programmed and BOOTRST is unprogrammed, the bootloader
* will start if the /HWB line of the AVR is held low and the system is reset. However, if the /HWB line is still held
* low when the application attempts to start via a watchdog reset, the bootloader will re-start. If set to the value
* \ref MAGIC_BOOT_KEY the special init function \ref Application_Jump_Check() will force the application to start.
*/
uint16_t MagicBootKey ATTR_NO_INIT;
/** Indicates if the bootloader is allowed to exit immediately if \ref RunBootloader is \c false. During shutdown all
* pending commands must be processed before jumping to the user-application, thus this tracks the main program loop
* iterations since a SCSI command from the host was received.
*/
static uint8_t TicksSinceLastCommand = 0;
/** Special startup routine to check if the bootloader was started via a watchdog reset, and if the magic application
* start key has been loaded into \ref MagicBootKey. If the bootloader started via the watchdog and the key is valid,
* this will force the user application to start via a software jump.
*/
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);
/* If IO13 is not jumpered to ground, start the user application instead */
JumpToApplication |= ((PINC & (1 << 7)) != 0);
/* Disable pull-up after the check has completed */
PORTC &= ~(1 << 7);
#elif ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))
/* Disable JTAG debugging */
JTAG_DISABLE();
/* Enable pull-up on the JTAG TCK pin so we can use it to select the mode */
PORTF |= (1 << 4);
Delay_MS(10);
/* If the TCK pin is not jumpered to ground, start the user application instead */
JumpToApplication |= ((PINF & (1 << 4)) != 0);
/* Re-enable JTAG debugging */
JTAG_ENABLE();
#endif
/* If the reset source was the bootloader and the key is correct, clear it and jump to the application */
if ((MCUSR & (1 << WDRF)) && (MagicBootKey == MAGIC_BOOT_KEY))
{
MagicBootKey = 0;
JumpToApplication = true;
}
if (JumpToApplication)
{
// cppcheck-suppress constStatement
((void (*)(void))0x0000)();
}
}
/** Main program entry point. This routine configures the hardware required by the application, then
* enters a loop to run the application tasks in sequence.
*/
int main(void)
{
SetupHardware();
LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
GlobalInterruptEnable();
while (RunBootloader || TicksSinceLastCommand++ < 0xFF)
{
MS_Device_USBTask(&Disk_MS_Interface);
USB_USBTask();
}
/* Disconnect from the host - USB interface will be reset later along with the AVR */
USB_Detach();
/* Unlock the forced application start mode of the bootloader if it is restarted */
MagicBootKey = MAGIC_BOOT_KEY;
/* Enable the watchdog and force a timeout to reset the AVR */
wdt_enable(WDTO_250MS);
for (;;);
}
/** Configures the board hardware and chip peripherals for the demo's functionality. */
static void SetupHardware(void)
{
/* Disable watchdog if enabled by bootloader/fuses */
MCUSR &= ~(1 << WDRF);
wdt_disable();
/* Disable clock division */
clock_prescale_set(clock_div_1);
/* Relocate the interrupt vector table to the bootloader section */
MCUCR = (1 << IVCE);
MCUCR = (1 << IVSEL);
/* Hardware Initialization */
LEDs_Init();
USB_Init();
/* Bootloader active LED toggle timer initialization */
TIMSK1 = (1 << TOIE1);
TCCR1B = ((1 << CS11) | (1 << CS10));
}
/** ISR to periodically toggle the LEDs on the board to indicate that the bootloader is active. */
ISR(TIMER1_OVF_vect, ISR_BLOCK)
{
LEDs_ToggleLEDs(LEDS_LED1 | LEDS_LED2);
}
/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs. */
void EVENT_USB_Device_Connect(void)
{
/* Indicate USB enumerating */
LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);
}
/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via
* the status LEDs and stops the Mass Storage management task.
*/
void EVENT_USB_Device_Disconnect(void)
{
/* Indicate USB not ready */
LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
}
/** Event handler for the library USB Configuration Changed event. */
void EVENT_USB_Device_ConfigurationChanged(void)
{
bool ConfigSuccess = true;
/* Setup Mass Storage Data Endpoints */
ConfigSuccess &= MS_Device_ConfigureEndpoints(&Disk_MS_Interface);
/* Indicate endpoint configuration success or failure */
LEDs_SetAllLEDs(ConfigSuccess ? LEDMASK_USB_READY : LEDMASK_USB_ERROR);
}
/** Event handler for the library USB Control Request reception event. */
void EVENT_USB_Device_ControlRequest(void)
{
MS_Device_ProcessControlRequest(&Disk_MS_Interface);
}
/** Mass Storage class driver callback function the reception of SCSI commands from the host, which must be processed.
*
* \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface configuration structure being referenced
*/
bool CALLBACK_MS_Device_SCSICommandReceived(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
{
bool CommandSuccess;
LEDs_SetAllLEDs(LEDMASK_USB_BUSY);
CommandSuccess = SCSI_DecodeSCSICommand(MSInterfaceInfo);
LEDs_SetAllLEDs(LEDMASK_USB_READY);
/* Signal that a command was processed, must not exit bootloader yet */
TicksSinceLastCommand = 0;
return CommandSuccess;
}

View file

@ -0,0 +1,99 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaims all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* Header file for BootloaderMassStorage.c.
*/
#ifndef _BOOTLOADER_MASS_STORAGE_H_
#define _BOOTLOADER_MASS_STORAGE_H_
/* Includes: */
#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/power.h>
#include <avr/interrupt.h>
#include <string.h>
#include "Descriptors.h"
#include "Config/AppConfig.h"
#include "Lib/SCSI.h"
#include <LUFA/Drivers/Board/LEDs.h>
#include <LUFA/Drivers/USB/USB.h>
#include <LUFA/Platform/Platform.h>
/* Preprocessor Checks: */
#if !defined(__OPTIMIZE_SIZE__)
#error This bootloader requires that it be optimized for size, not speed, to fit into the target device. Change optimization settings and try again.
#endif
/* Macros: */
/** LED mask for the library LED driver, to indicate that the USB interface is not ready. */
#define LEDMASK_USB_NOTREADY LEDS_LED1
/** LED mask for the library LED driver, to indicate that the USB interface is enumerating. */
#define LEDMASK_USB_ENUMERATING (LEDS_LED2 | LEDS_LED3)
/** LED mask for the library LED driver, to indicate that the USB interface is ready. */
#define LEDMASK_USB_READY (LEDS_LED2 | LEDS_LED4)
/** LED mask for the library LED driver, to indicate that an error has occurred in the USB interface. */
#define LEDMASK_USB_ERROR (LEDS_LED1 | LEDS_LED3)
/** LED mask for the library LED driver, to indicate that the USB interface is busy. */
#define LEDMASK_USB_BUSY LEDS_LED2
/** Magic bootloader key to unlock forced application start mode. */
#define MAGIC_BOOT_KEY 0xDC42
/* Global Variables: */
extern bool RunBootloader;
/* Function Prototypes: */
int main(void) AUX_BOOT_SECTION;
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;
#if defined(INCLUDE_FROM_BOOTLOADER_MASSSTORAGE_C)
static void SetupHardware(void) AUX_BOOT_SECTION;
#endif
#endif

View file

@ -0,0 +1,225 @@
/** \file
*
* This file contains special DoxyGen information for the generation of the main page and other special
* documentation pages. It is not a project source file.
*/
/** \mainpage Mass Storage Class USB AVR Bootloader
*
* \section Sec_Compat Demo Compatibility:
*
* The following list indicates what microcontrollers are compatible with this demo.
*
* \li Series 7 USB AVRs (AT90USBxxx7)
* \li Series 6 USB AVRs (AT90USBxxx6)
* \li Series 4 USB AVRs (ATMEGAxxU4) - <i>See \ref SSec_Aux_Space</i>
* \li ATMEGA32U2 - <i>See \ref SSec_Aux_Space</i>
*
* \section Sec_Info USB Information:
*
* The following table gives a rundown of the USB utilization of this demo.
*
* <table>
* <tr>
* <td><b>USB Mode:</b></td>
* <td>Device</td>
* </tr>
* <tr>
* <td><b>USB Class:</b></td>
* <td>Mass Storage Device</td>
* </tr>
* <tr>
* <td><b>USB Subclass:</b></td>
* <td>Bulk-Only Transport</td>
* </tr>
* <tr>
* <td><b>Relevant Standards:</b></td>
* <td>USBIF Mass Storage Standard \n
* USB Bulk-Only Transport Standard \n
* SCSI Primary Commands Specification \n
* SCSI Block Commands Specification</td>
* </tr>
* <tr>
* <td><b>Supported USB Speeds:</b></td>
* <td>Full Speed Mode</td>
* </tr>
* </table>
*
* \section Sec_Description Project Description:
*
* This bootloader enumerates to the host as a Mass Storage device, capable of reading and writing a new binary
* 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
* 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.
*
* When the bootloader is running, the board's LED(s) will flash at regular intervals to distinguish the
* bootloader from the normal user application.
*
* \warning <b>THIS BOOTLOADER IS NOT SECURE.</b> Malicious entities can recover written data, even if the device
* lockbits are set.
*
* \section Sec_Running Running the Bootloader
*
* This bootloader is designed to be started via the HWB mechanism of the USB AVRs; ground the HWB pin (see device
* datasheet) then momentarily ground /RESET to start the bootloader. This assumes the HWBE fuse is set and the BOOTRST
* fuse is cleared.
*
* For board specific exceptions to the above, see below.
*
* \subsection SSec_XPLAIN Atmel Xplain Board
* Ground the USB AVR JTAG's \c TCK pin to ground when powering on the board to start the bootloader. This assumes the
* \c HWBE fuse is cleared and the \c BOOTRST fuse is set as the HWBE pin is not user accessible on this board.
*
* \subsection SSec_Leonardo Arduino Leonardo Board
* Ground \c IO13 when powering the board to start the bootloader. This assumes the \c HWBE fuse is cleared and the
* \c BOOTRST fuse is set as the HWBE pin is not user accessible on this board.
*
* \section Sec_Installation Driver Installation
*
* This bootloader uses the Mass Storage drivers inbuilt into all modern operating systems, thus no additional
* drivers need to be supplied for correct operation.
*
* \section Sec_HostApp Host Controller Application
*
* This bootloader is compatible with all operating systems that support the FAT12 file system format. To reprogram the
* device, overwrite a file stored on the virtual FAT filesystem with a new binary (BIN format) image. Remember to safely
* remove your device from the host using the host OS's ejection APIs, to ensure all data is correctly flushed to the
* bootloader's virtual filesystem and not cached in the OS's file system driver.
*
* The current device firmware can be read from the device by reading a file from the virtual FAT filesystem.
*
* \warning This bootloader is currently <b>incompatible with the Apple MacOS X OS Finder GUI</b>, due to the
* large amount of meta files this OS attempts to write to the disk along with the new binaries. On
* this platform, firmwares must be copied to the disk via the Terminal application only to prevent
* firmware corruption.
*
* \section Sec_API User Application API
*
* Several user application functions for FLASH and other special memory area manipulations are exposed by the bootloader,
* allowing the user application to call into the bootloader at runtime to read and write FLASH data.
*
* By default, the bootloader API jump table is located 32 bytes from the end of the device's FLASH memory, and follows the
* following layout:
*
* \code
* #define BOOTLOADER_API_TABLE_SIZE 32
* #define BOOTLOADER_API_TABLE_START ((FLASHEND + 1UL) - BOOTLOADER_API_TABLE_SIZE)
* #define BOOTLOADER_API_CALL(Index) (void*)((BOOTLOADER_API_TABLE_START + (Index * 2)) / 2)
*
* void (*BootloaderAPI_ErasePage)(uint32_t Address) = BOOTLOADER_API_CALL(0);
* void (*BootloaderAPI_WritePage)(uint32_t Address) = BOOTLOADER_API_CALL(1);
* void (*BootloaderAPI_FillWord)(uint32_t Address, uint16_t Word) = BOOTLOADER_API_CALL(2);
* uint8_t (*BootloaderAPI_ReadSignature)(uint16_t Address) = BOOTLOADER_API_CALL(3);
* uint8_t (*BootloaderAPI_ReadFuse)(uint16_t Address) = BOOTLOADER_API_CALL(4);
* uint8_t (*BootloaderAPI_ReadLock)(void) = BOOTLOADER_API_CALL(5);
* void (*BootloaderAPI_WriteLock)(uint8_t LockBits) = BOOTLOADER_API_CALL(6);
*
* #define BOOTLOADER_MAGIC_SIGNATURE_START (BOOTLOADER_API_TABLE_START + (BOOTLOADER_API_TABLE_SIZE - 2))
* #define BOOTLOADER_MAGIC_SIGNATURE 0xDCFB
*
* #define BOOTLOADER_CLASS_SIGNATURE_START (BOOTLOADER_API_TABLE_START + (BOOTLOADER_API_TABLE_SIZE - 4))
* #define BOOTLOADER_MASS_STORAGE_SIGNATURE 0xDF30
*
* #define BOOTLOADER_ADDRESS_START (BOOTLOADER_API_TABLE_START + (BOOTLOADER_API_TABLE_SIZE - 8))
* #define BOOTLOADER_ADDRESS_LENGTH 4
* \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
* The following illustration indicates the final memory map of the device when loaded with the bootloader.
*
* \verbatim
* +----------------------------+ 0x0000
* | |
* | |
* | |
* | |
* | |
* | |
* | |
* | |
* | User Application |
* | |
* | |
* | |
* | |
* | |
* | |
* | |
* | |
* +----------------------------+ 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
* | |
* | Bootloader Application |
* | (Not User App. Accessible) |
* | |
* +----------------------------+ FLASHEND - 96
* | API Table Trampolines |
* | (Not User App. Accessible) |
* +----------------------------+ FLASHEND - 32
* | Bootloader API Table |
* | (User App. Accessible) |
* +----------------------------+ FLASHEND - 8
* | Bootloader ID Constants |
* | (User App. Accessible) |
* +----------------------------+ FLASHEND
* \endverbatim
*
* \section Sec_KnownIssues Known Issues:
*
* \par In some cases, the application is not fully loaded into the device.
* Write-caching on some operating systems may interfere with the normal
* operation of the bootloader. Write caching should be disabled when using the
* Mass Storage bootloader, or the file system synced via an appropriate command
* (such as the OS's normal disk ejection command) before disconnecting the device.
*
* \par After loading an application, it is not run automatically on startup.
* Some USB AVR boards ship with the BOOTRST fuse set, causing the bootloader
* to run automatically when the device is reset. In most cases, the BOOTRST
* fuse should be disabled and the HWBE fuse used instead to run the bootloader
* when needed.
*
* \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.
*
* <table>
* <tr>
* <th><b>Define Name:</b></th>
* <th><b>Location:</b></th>
* <th><b>Description:</b></th>
* </tr>
* <tr>
* <td>NO_APP_START_ON_EJECT</td>
* <td>AppConfig.h</td>
* <td>Define to disable automatic start of the loaded application when the virtual
* Mass Storage disk is ejected on the host.</td>
* </tr>
* </table>
*/

View file

@ -0,0 +1,47 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaims all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
* \brief Application Configuration Header File
*
* This is a header file which is be used to configure LUFA's
* compile time options, as an alternative to the compile time
* constants supplied through a makefile.
*
* For information on what each token does, refer to the
* \ref Sec_Options section of the application documentation.
*/
#ifndef _APP_CONFIG_H_
#define _APP_CONFIG_H_
// #define NO_APP_START_ON_EJECT
#endif

View file

@ -0,0 +1,93 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaims all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
* \brief LUFA Library Configuration Header File
*
* This header file is used to configure LUFA's compile time options,
* as an alternative to the compile time constants supplied through
* a makefile.
*
* For information on what each token does, refer to the LUFA
* manual section "Summary of Compile Tokens".
*/
#ifndef _LUFA_CONFIG_H_
#define _LUFA_CONFIG_H_
#if (ARCH == ARCH_AVR8)
/* Non-USB Related Configuration Tokens: */
// #define DISABLE_TERMINAL_CODES
/* USB Class Driver Related Tokens: */
// #define HID_HOST_BOOT_PROTOCOL_ONLY
// #define HID_STATETABLE_STACK_DEPTH {Insert Value Here}
// #define HID_USAGE_STACK_DEPTH {Insert Value Here}
// #define HID_MAX_COLLECTIONS {Insert Value Here}
// #define HID_MAX_REPORTITEMS {Insert Value Here}
// #define HID_MAX_REPORT_IDS {Insert Value Here}
// #define NO_CLASS_DRIVER_AUTOFLUSH
/* General USB Driver Related Tokens: */
#define ORDERED_EP_CONFIG
#define USE_STATIC_OPTIONS (USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)
#define USB_DEVICE_ONLY
// #define USB_HOST_ONLY
// #define USB_STREAM_TIMEOUT_MS {Insert Value Here}
// #define NO_LIMITED_CONTROLLER_CONNECT
#define NO_SOF_EVENTS
/* USB Device Mode Driver Related Tokens: */
#define USE_RAM_DESCRIPTORS
// #define USE_FLASH_DESCRIPTORS
// #define USE_EEPROM_DESCRIPTORS
#define NO_INTERNAL_SERIAL
#define FIXED_CONTROL_ENDPOINT_SIZE 8
#define DEVICE_STATE_AS_GPIOR 0
#define FIXED_NUM_CONFIGURATIONS 1
// #define CONTROL_ONLY_DEVICE
#define INTERRUPT_CONTROL_ENDPOINT
#define NO_DEVICE_REMOTE_WAKEUP
#define NO_DEVICE_SELF_POWER
/* USB Host Mode Driver Related Tokens: */
// #define HOST_STATE_AS_GPIOR {Insert Value Here}
// #define USB_HOST_TIMEOUT_MS {Insert Value Here}
// #define HOST_DEVICE_SETTLE_DELAY_MS {Insert Value Here}
// #define NO_AUTO_VBUS_MANAGEMENT
// #define INVERTED_VBUS_ENABLE_LINE
#else
#error Unsupported architecture for this LUFA configuration file.
#endif
#endif

View file

@ -0,0 +1,157 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaims all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* USB Device Descriptors, for library use when in USB device mode. Descriptors are special
* computer-readable structures which the host requests upon device enumeration, to determine
* the device's capabilities and functions.
*/
#include "Descriptors.h"
/** Device descriptor structure. This descriptor, located in SRAM memory, describes the overall
* device characteristics, including the supported USB version, control endpoint size and the
* number of device configurations. The descriptor is read out by the USB host when the enumeration
* process begins.
*/
const USB_Descriptor_Device_t DeviceDescriptor =
{
.Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},
.USBSpecification = VERSION_BCD(1,1,0),
.Class = USB_CSCP_NoDeviceClass,
.SubClass = USB_CSCP_NoDeviceSubclass,
.Protocol = USB_CSCP_NoDeviceProtocol,
.Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE,
.VendorID = 0x03EB,
.ProductID = 0x2045,
.ReleaseNumber = VERSION_BCD(0,0,1),
.ManufacturerStrIndex = NO_DESCRIPTOR,
.ProductStrIndex = NO_DESCRIPTOR,
.SerialNumStrIndex = NO_DESCRIPTOR,
.NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS
};
/** Configuration descriptor structure. This descriptor, located in FLASH memory, describes the usage
* of the device in one of its supported configurations, including information about any device interfaces
* and endpoints. The descriptor is read out by the USB host during the enumeration process when selecting
* a configuration so that the host may correctly communicate with the USB device.
*/
const USB_Descriptor_Configuration_t ConfigurationDescriptor =
{
.Config =
{
.Header = {.Size = sizeof(USB_Descriptor_Configuration_Header_t), .Type = DTYPE_Configuration},
.TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t),
.TotalInterfaces = 1,
.ConfigurationNumber = 1,
.ConfigurationStrIndex = NO_DESCRIPTOR,
.ConfigAttributes = USB_CONFIG_ATTR_RESERVED,
.MaxPowerConsumption = USB_CONFIG_POWER_MA(100)
},
.MS_Interface =
{
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
.InterfaceNumber = INTERFACE_ID_MassStorage,
.AlternateSetting = 0,
.TotalEndpoints = 2,
.Class = MS_CSCP_MassStorageClass,
.SubClass = MS_CSCP_SCSITransparentSubclass,
.Protocol = MS_CSCP_BulkOnlyTransportProtocol,
.InterfaceStrIndex = NO_DESCRIPTOR
},
.MS_DataInEndpoint =
{
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
.EndpointAddress = MASS_STORAGE_IN_EPADDR,
.Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
.EndpointSize = MASS_STORAGE_IO_EPSIZE,
.PollingIntervalMS = 0x05
},
.MS_DataOutEndpoint =
{
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
.EndpointAddress = MASS_STORAGE_OUT_EPADDR,
.Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
.EndpointSize = MASS_STORAGE_IO_EPSIZE,
.PollingIntervalMS = 0x05
}
};
/** 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
* to the USB library. When the device receives a Get Descriptor request on the control endpoint, this function
* is called so that the descriptor details can be passed back and the appropriate descriptor sent back to the
* USB host.
*/
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
const uint8_t wIndex,
const void** const DescriptorAddress)
{
const uint8_t DescriptorType = (wValue >> 8);
const void* Address = NULL;
uint16_t Size = NO_DESCRIPTOR;
/* If/Else If chain compiles slightly smaller than a switch case */
if (DescriptorType == DTYPE_Device)
{
Address = &DeviceDescriptor;
Size = sizeof(USB_Descriptor_Device_t);
}
else if (DescriptorType == DTYPE_Configuration)
{
Address = &ConfigurationDescriptor;
Size = sizeof(USB_Descriptor_Configuration_t);
}
*DescriptorAddress = Address;
return Size;
}

View file

@ -0,0 +1,88 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaims all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* Header file for Descriptors.c.
*/
#ifndef _DESCRIPTORS_H_
#define _DESCRIPTORS_H_
/* Includes: */
#include <avr/pgmspace.h>
#include <LUFA/Drivers/USB/USB.h>
#include "BootloaderAPI.h"
/* Macros: */
/** Endpoint address of the Mass Storage device-to-host data IN endpoint. */
#define MASS_STORAGE_IN_EPADDR (ENDPOINT_DIR_IN | 3)
/** Endpoint address of the Mass Storage host-to-device data OUT endpoint. */
#define MASS_STORAGE_OUT_EPADDR (ENDPOINT_DIR_OUT | 4)
/** Size in bytes of the Mass Storage data endpoints. */
#define MASS_STORAGE_IO_EPSIZE 64
/* Type Defines: */
/** Type define for the device configuration descriptor structure. This must be defined in the
* application code, as the configuration descriptor contains several sub-descriptors which
* vary between devices, and which describe the device's usage to the host.
*/
typedef struct
{
USB_Descriptor_Configuration_Header_t Config;
// Mass Storage Interface
USB_Descriptor_Interface_t MS_Interface;
USB_Descriptor_Endpoint_t MS_DataInEndpoint;
USB_Descriptor_Endpoint_t MS_DataOutEndpoint;
} USB_Descriptor_Configuration_t;
/** Enum for the device interface descriptor IDs within the device. Each interface descriptor
* should have a unique ID index associated with it, which can be used to refer to the
* interface from other descriptors.
*/
enum InterfaceDescriptors_t
{
INTERFACE_ID_MassStorage = 0, /**< Mass storage interface descriptor ID */
};
/* Function Prototypes: */
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
const uint8_t wIndex,
const void** const DescriptorAddress)
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3) AUX_BOOT_SECTION;
#endif

View file

@ -0,0 +1,294 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaims all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* SCSI command processing routines, for SCSI commands issued by the host. Mass Storage
* devices use a thin "Bulk-Only Transport" protocol for issuing commands and status information,
* which wrap around standard SCSI device commands for controlling the actual storage medium.
*/
#define INCLUDE_FROM_SCSI_C
#include "SCSI.h"
/** Structure to hold the SCSI response data to a SCSI INQUIRY command. This gives information about the device's
* features and capabilities.
*/
static const SCSI_Inquiry_Response_t InquiryData =
{
.DeviceType = DEVICE_TYPE_BLOCK,
.PeripheralQualifier = 0,
.Removable = true,
.Version = 0,
.ResponseDataFormat = 2,
.NormACA = false,
.TrmTsk = false,
.AERC = false,
.AdditionalLength = 0x1F,
.SoftReset = false,
.CmdQue = false,
.Linked = false,
.Sync = false,
.WideBus16Bit = false,
.WideBus32Bit = false,
.RelAddr = false,
.VendorID = "LUFA",
.ProductID = "Bootloader",
.RevisionID = {'0','.','0','0'},
};
/** Structure to hold the sense data for the last issued SCSI command, which is returned to the host after a SCSI REQUEST SENSE
* command is issued. This gives information on exactly why the last command failed to complete.
*/
static SCSI_Request_Sense_Response_t SenseData =
{
.ResponseCode = 0x70,
.AdditionalLength = 0x0A,
};
/** Main routine to process the SCSI command located in the Command Block Wrapper read from the host. This dispatches
* to the appropriate SCSI command handling routine if the issued command is supported by the device, else it returns
* a command failure due to a ILLEGAL REQUEST.
*
* \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
*
* \return Boolean \c true if the command completed successfully, \c false otherwise
*/
bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
{
bool CommandSuccess = false;
/* Run the appropriate SCSI command hander function based on the passed command */
switch (MSInterfaceInfo->State.CommandBlock.SCSICommandData[0])
{
case SCSI_CMD_INQUIRY:
CommandSuccess = SCSI_Command_Inquiry(MSInterfaceInfo);
break;
case SCSI_CMD_REQUEST_SENSE:
CommandSuccess = SCSI_Command_Request_Sense(MSInterfaceInfo);
break;
case SCSI_CMD_READ_CAPACITY_10:
CommandSuccess = SCSI_Command_Read_Capacity_10(MSInterfaceInfo);
break;
case SCSI_CMD_WRITE_10:
CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_WRITE);
break;
case SCSI_CMD_READ_10:
CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_READ);
break;
case SCSI_CMD_MODE_SENSE_6:
CommandSuccess = SCSI_Command_ModeSense_6(MSInterfaceInfo);
break;
case SCSI_CMD_START_STOP_UNIT:
#if !defined(NO_APP_START_ON_EJECT)
/* If the user ejected the volume, signal bootloader exit at next opportunity. */
RunBootloader = ((MSInterfaceInfo->State.CommandBlock.SCSICommandData[4] & 0x03) != 0x02);
#endif
case SCSI_CMD_SEND_DIAGNOSTIC:
case SCSI_CMD_TEST_UNIT_READY:
case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
case SCSI_CMD_VERIFY_10:
/* These commands should just succeed, no handling required */
CommandSuccess = true;
MSInterfaceInfo->State.CommandBlock.DataTransferLength = 0;
break;
default:
/* Update the SENSE key to reflect the invalid command */
SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,
SCSI_ASENSE_INVALID_COMMAND,
SCSI_ASENSEQ_NO_QUALIFIER);
break;
}
/* Check if command was successfully processed */
if (CommandSuccess)
{
SCSI_SET_SENSE(SCSI_SENSE_KEY_GOOD,
SCSI_ASENSE_NO_ADDITIONAL_INFORMATION,
SCSI_ASENSEQ_NO_QUALIFIER);
return true;
}
return false;
}
/** Command processing for an issued SCSI INQUIRY command. This command returns information about the device's features
* and capabilities to the host.
*
* \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
*
* \return Boolean \c true if the command completed successfully, \c false otherwise.
*/
static bool SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
{
uint16_t AllocationLength = SwapEndian_16(*(uint16_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[3]);
uint16_t BytesTransferred = MIN(AllocationLength, sizeof(InquiryData));
/* Only the standard INQUIRY data is supported, check if any optional INQUIRY bits set */
if ((MSInterfaceInfo->State.CommandBlock.SCSICommandData[1] & ((1 << 0) | (1 << 1))) ||
MSInterfaceInfo->State.CommandBlock.SCSICommandData[2])
{
/* Optional but unsupported bits set - update the SENSE key and fail the request */
SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,
SCSI_ASENSE_INVALID_FIELD_IN_CDB,
SCSI_ASENSEQ_NO_QUALIFIER);
return false;
}
Endpoint_Write_Stream_LE(&InquiryData, BytesTransferred, NULL);
/* Pad out remaining bytes with 0x00 */
Endpoint_Null_Stream((AllocationLength - BytesTransferred), NULL);
/* Finalize the stream transfer to send the last packet */
Endpoint_ClearIN();
/* Succeed the command and update the bytes transferred counter */
MSInterfaceInfo->State.CommandBlock.DataTransferLength -= BytesTransferred;
return true;
}
/** Command processing for an issued SCSI REQUEST SENSE command. This command returns information about the last issued command,
* including the error code and additional error information so that the host can determine why a command failed to complete.
*
* \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
*
* \return Boolean \c true if the command completed successfully, \c false otherwise.
*/
static bool SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
{
uint8_t AllocationLength = MSInterfaceInfo->State.CommandBlock.SCSICommandData[4];
uint8_t BytesTransferred = MIN(AllocationLength, sizeof(SenseData));
Endpoint_Write_Stream_LE(&SenseData, BytesTransferred, NULL);
Endpoint_Null_Stream((AllocationLength - BytesTransferred), NULL);
Endpoint_ClearIN();
/* Succeed the command and update the bytes transferred counter */
MSInterfaceInfo->State.CommandBlock.DataTransferLength -= BytesTransferred;
return true;
}
/** Command processing for an issued SCSI READ CAPACITY (10) command. This command returns information about the device's capacity
* on the selected Logical Unit (drive), as a number of OS-sized blocks.
*
* \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
*
* \return Boolean \c true if the command completed successfully, \c false otherwise.
*/
static bool SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
{
Endpoint_Write_32_BE(LUN_MEDIA_BLOCKS - 1);
Endpoint_Write_32_BE(SECTOR_SIZE_BYTES);
Endpoint_ClearIN();
/* Succeed the command and update the bytes transferred counter */
MSInterfaceInfo->State.CommandBlock.DataTransferLength -= 8;
return true;
}
/** 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
* reading and writing of the data.
*
* \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
* \param[in] IsDataRead Indicates if the command is a READ (10) command or WRITE (10) command (DATA_READ or DATA_WRITE)
*
* \return Boolean \c true if the command completed successfully, \c false otherwise.
*/
static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
const bool IsDataRead)
{
uint16_t BlockAddress;
uint16_t TotalBlocks;
/* Load in the 32-bit block address (SCSI uses big-endian, so have to reverse the byte order) */
BlockAddress = SwapEndian_32(*(uint32_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[2]);
/* Load in the 16-bit total blocks (SCSI uses big-endian, so have to reverse the byte order) */
TotalBlocks = SwapEndian_16(*(uint16_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[7]);
/* Check if the block address is outside the maximum allowable value for the LUN */
if (BlockAddress >= LUN_MEDIA_BLOCKS)
{
/* Block address is invalid, update SENSE key and return command fail */
SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,
SCSI_ASENSE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE,
SCSI_ASENSEQ_NO_QUALIFIER);
return false;
}
/* Determine if the packet is a READ (10) or WRITE (10) command, call appropriate function */
for (uint16_t i = 0; i < TotalBlocks; i++)
{
if (IsDataRead == DATA_READ)
VirtualFAT_ReadBlock(BlockAddress + i);
else
VirtualFAT_WriteBlock(BlockAddress + i);
}
/* Update the bytes transferred counter and succeed the command */
MSInterfaceInfo->State.CommandBlock.DataTransferLength -= ((uint32_t)TotalBlocks * SECTOR_SIZE_BYTES);
return true;
}
/** Command processing for an issued SCSI MODE SENSE (6) command. This command returns various informational pages about
* the SCSI device, as well as the device's Write Protect status.
*
* \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
*
* \return Boolean \c true if the command completed successfully, \c false otherwise.
*/
static bool SCSI_Command_ModeSense_6(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
{
/* Send an empty header response indicating Write Protect flag is off */
Endpoint_Write_32_LE(0);
Endpoint_ClearIN();
/* Update the bytes transferred counter and succeed the command */
MSInterfaceInfo->State.CommandBlock.DataTransferLength -= 4;
return true;
}

View file

@ -0,0 +1,84 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaims all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* Header file for SCSI.c.
*/
#ifndef _SCSI_H_
#define _SCSI_H_
/* Includes: */
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <LUFA/Drivers/USB/USB.h>
#include "../BootloaderMassStorage.h"
#include "../Descriptors.h"
#include "VirtualFAT.h"
/* Macros: */
/** Macro to set the current SCSI sense data to the given key, additional sense code and additional sense qualifier. This
* is for convenience, as it allows for all three sense values (returned upon request to the host to give information about
* the last command failure) in a quick and easy manner.
*
* \param[in] Key New SCSI sense key to set the sense code to
* \param[in] Acode New SCSI additional sense key to set the additional sense code to
* \param[in] Aqual New SCSI additional sense key qualifier to set the additional sense qualifier code to
*/
#define SCSI_SET_SENSE(Key, Acode, Aqual) do { SenseData.SenseKey = (Key); \
SenseData.AdditionalSenseCode = (Acode); \
SenseData.AdditionalSenseQualifier = (Aqual); } while (0)
/** Macro for the \ref SCSI_Command_ReadWrite_10() function, to indicate that data is to be read from the storage medium. */
#define DATA_READ true
/** Macro for the \ref SCSI_Command_ReadWrite_10() function, to indicate that data is to be written to the storage medium. */
#define DATA_WRITE false
/** Value for the DeviceType entry in the SCSI_Inquiry_Response_t enum, indicating a Block Media device. */
#define DEVICE_TYPE_BLOCK 0x00
/* Function Prototypes: */
bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) AUX_BOOT_SECTION;
#if defined(INCLUDE_FROM_SCSI_C)
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) AUX_BOOT_SECTION;
static bool SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) AUX_BOOT_SECTION;
static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
const bool IsDataRead) AUX_BOOT_SECTION;
static bool SCSI_Command_ModeSense_6(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) AUX_BOOT_SECTION;
#endif
#endif

View file

@ -0,0 +1,482 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaims all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* Virtualized FAT12 filesystem implementation, to perform self-programming
* in response to read and write requests to the virtual filesystem by the
* host PC.
*/
#define INCLUDE_FROM_VIRTUAL_FAT_C
#include "VirtualFAT.h"
/** FAT filesystem boot sector block, must be the first sector on the physical
* disk so that the host can identify the presence of a FAT filesystem. This
* block is truncated; normally a large bootstrap section is located near the
* end of the block for booting purposes however as this is not meant to be a
* bootable disk it is omitted for space reasons.
*
* \note When returning the boot block to the host, the magic signature 0xAA55
* must be added to the very end of the block to identify it as a boot
* block.
*/
static const FATBootBlock_t BootBlock =
{
.Bootstrap = {0xEB, 0x3C, 0x90},
.Description = "mkdosfs",
.SectorSize = SECTOR_SIZE_BYTES,
.SectorsPerCluster = SECTOR_PER_CLUSTER,
.ReservedSectors = 1,
.FATCopies = 2,
.RootDirectoryEntries = (SECTOR_SIZE_BYTES / sizeof(FATDirectoryEntry_t)),
.TotalSectors16 = LUN_MEDIA_BLOCKS,
.MediaDescriptor = 0xF8,
.SectorsPerFAT = 1,
.SectorsPerTrack = (LUN_MEDIA_BLOCKS % 64),
.Heads = (LUN_MEDIA_BLOCKS / 64),
.HiddenSectors = 0,
.TotalSectors32 = 0,
.PhysicalDriveNum = 0,
.ExtendedBootRecordSig = 0x29,
.VolumeSerialNumber = 0x12345678,
.VolumeLabel = "LUFA BOOT ",
.FilesystemIdentifier = "FAT12 ",
};
/** FAT 8.3 style directory entry, for the virtual FLASH contents file. */
static FATDirectoryEntry_t FirmwareFileEntries[] =
{
/* Root volume label entry; disk label is contained in the Filename and
* Extension fields (concatenated) with a special attribute flag - other
* fields are ignored. Should be the same as the label in the boot block.
*/
[DISK_FILE_ENTRY_VolumeID] =
{
.MSDOS_Directory =
{
.Name = "LUFA BOOT ",
.Attributes = FAT_FLAG_VOLUME_NAME,
.Reserved = {0},
.CreationTime = 0,
.CreationDate = 0,
.StartingCluster = 0,
.Reserved2 = 0,
}
},
/* VFAT Long File Name entry for the virtual firmware file; required to
* prevent corruption from systems that are unable to detect the device
* as being a legacy MSDOS style FAT12 volume. */
[DISK_FILE_ENTRY_FLASH_LFN] =
{
.VFAT_LongFileName =
{
.Ordinal = 1 | FAT_ORDINAL_LAST_ENTRY,
.Attribute = FAT_FLAG_LONG_FILE_NAME,
.Reserved1 = 0,
.Reserved2 = 0,
.Checksum = FAT_CHECKSUM('F','L','A','S','H',' ',' ',' ','B','I','N'),
.Unicode1 = 'F',
.Unicode2 = 'L',
.Unicode3 = 'A',
.Unicode4 = 'S',
.Unicode5 = 'H',
.Unicode6 = '.',
.Unicode7 = 'B',
.Unicode8 = 'I',
.Unicode9 = 'N',
.Unicode10 = 0,
.Unicode11 = 0,
.Unicode12 = 0,
.Unicode13 = 0,
}
},
/* MSDOS file entry for the virtual Firmware image. */
[DISK_FILE_ENTRY_FLASH_MSDOS] =
{
.MSDOS_File =
{
.Filename = "FLASH ",
.Extension = "BIN",
.Attributes = 0,
.Reserved = {0},
.CreationTime = FAT_TIME(1, 1, 0),
.CreationDate = FAT_DATE(14, 2, 1989),
.StartingCluster = 2,
.FileSizeBytes = FLASH_FILE_SIZE_BYTES,
}
},
[DISK_FILE_ENTRY_EEPROM_LFN] =
{
.VFAT_LongFileName =
{
.Ordinal = 1 | FAT_ORDINAL_LAST_ENTRY,
.Attribute = FAT_FLAG_LONG_FILE_NAME,
.Reserved1 = 0,
.Reserved2 = 0,
.Checksum = FAT_CHECKSUM('E','E','P','R','O','M',' ',' ','B','I','N'),
.Unicode1 = 'E',
.Unicode2 = 'E',
.Unicode3 = 'P',
.Unicode4 = 'R',
.Unicode5 = 'O',
.Unicode6 = 'M',
.Unicode7 = '.',
.Unicode8 = 'B',
.Unicode9 = 'I',
.Unicode10 = 'N',
.Unicode11 = 0,
.Unicode12 = 0,
.Unicode13 = 0,
}
},
[DISK_FILE_ENTRY_EEPROM_MSDOS] =
{
.MSDOS_File =
{
.Filename = "EEPROM ",
.Extension = "BIN",
.Attributes = 0,
.Reserved = {0},
.CreationTime = FAT_TIME(1, 1, 0),
.CreationDate = FAT_DATE(14, 2, 1989),
.StartingCluster = 2 + FILE_CLUSTERS(FLASH_FILE_SIZE_BYTES),
.FileSizeBytes = EEPROM_FILE_SIZE_BYTES,
}
},
};
/** Starting cluster of the virtual FLASH.BIN file on disk, tracked so that the
* offset from the start of the data sector can be determined. On Windows
* systems files are usually replaced using the original file's disk clusters,
* while Linux appears to overwrite with an offset which must be compensated for.
*/
static const uint16_t* FLASHFileStartCluster = &FirmwareFileEntries[DISK_FILE_ENTRY_FLASH_MSDOS].MSDOS_File.StartingCluster;
/** Starting cluster of the virtual EEPROM.BIN file on disk, tracked so that the
* offset from the start of the data sector can be determined. On Windows
* systems files are usually replaced using the original file's disk clusters,
* while Linux appears to overwrite with an offset which must be compensated for.
*/
static const uint16_t* EEPROMFileStartCluster = &FirmwareFileEntries[DISK_FILE_ENTRY_EEPROM_MSDOS].MSDOS_File.StartingCluster;
/** Reads a byte of EEPROM out from the EEPROM memory space.
*
* \note This function is required as the avr-libc EEPROM functions do not cope
* with linker relaxations, and a jump longer than 4K of FLASH on the
* larger USB AVRs will break the linker. This function is marked as
* never inlinable and placed into the normal text segment so that the
* call to the EEPROM function will be short even if the AUX boot section
* is used.
*
* \param[in] Address Address of the EEPROM location to read from
*
* \return Read byte of EEPROM data.
*/
static uint8_t ReadEEPROMByte(const uint8_t* const Address)
{
return eeprom_read_byte(Address);
}
/** Writes a byte of EEPROM out to the EEPROM memory space.
*
* \note This function is required as the avr-libc EEPROM functions do not cope
* with linker relaxations, and a jump longer than 4K of FLASH on the
* larger USB AVRs will break the linker. This function is marked as
* never inlinable and placed into the normal text segment so that the
* call to the EEPROM function will be short even if the AUX boot section
* is used.
*
* \param[in] Address Address of the EEPROM location to write to
* \param[in] Data New data to write to the EEPROM location
*/
static void WriteEEPROMByte(uint8_t* const Address,
const uint8_t Data)
{
eeprom_update_byte(Address, Data);
}
/** Updates a FAT12 cluster entry in the FAT file table with the specified next
* chain index. If the cluster is the last in the file chain, the magic value
* \c 0xFFF should be used.
*
* \note FAT data cluster indexes are offset by 2, so that cluster 2 is the
* first file data cluster on the disk. See the FAT specification.
*
* \param[out] FATTable Pointer to the FAT12 allocation table
* \param[in] Index Index of the cluster entry to update
* \param[in] ChainEntry Next cluster index in the file chain
*/
static void UpdateFAT12ClusterEntry(uint8_t* const FATTable,
const uint16_t Index,
const uint16_t ChainEntry)
{
/* Calculate the starting offset of the cluster entry in the FAT12 table */
uint8_t FATOffset = (Index + (Index >> 1));
bool UpperNibble = ((Index & 1) != 0);
/* Check if the start of the entry is at an upper nibble of the byte, fill
* out FAT12 entry as required */
if (UpperNibble)
{
FATTable[FATOffset] = (FATTable[FATOffset] & 0x0F) | ((ChainEntry & 0x0F) << 4);
FATTable[FATOffset + 1] = (ChainEntry >> 4);
}
else
{
FATTable[FATOffset] = ChainEntry;
FATTable[FATOffset + 1] = (FATTable[FATOffset] & 0xF0) | (ChainEntry >> 8);
}
}
/** Updates a FAT12 cluster chain in the FAT file table with a linear chain of
* the specified length.
*
* \note FAT data cluster indexes are offset by 2, so that cluster 2 is the
* first file data cluster on the disk. See the FAT specification.
*
* \param[out] FATTable Pointer to the FAT12 allocation table
* \param[in] Index Index of the start of the cluster chain to update
* \param[in] ChainLength Length of the chain to write, in clusters
*/
static void UpdateFAT12ClusterChain(uint8_t* const FATTable,
const uint16_t Index,
const uint8_t ChainLength)
{
for (uint8_t i = 0; i < ChainLength; i++)
{
uint16_t CurrentCluster = Index + i;
uint16_t NextCluster = CurrentCluster + 1;
/* Mark last cluster as end of file */
if (i == (ChainLength - 1))
NextCluster = 0xFFF;
UpdateFAT12ClusterEntry(FATTable, CurrentCluster, NextCluster);
}
}
/** Reads or writes a block of data from/to the physical device FLASH using a
* block buffer stored in RAM, if the requested block is within the virtual
* firmware file's sector ranges in the emulated FAT file system.
*
* \param[in] BlockNumber Physical disk block to read from/write to
* \param[in,out] BlockBuffer Pointer to the start of the block buffer in RAM
* \param[in] Read If \c true, the requested block is read, if
* \c false, the requested block is written
*/
static void ReadWriteFLASHFileBlock(const uint16_t BlockNumber,
uint8_t* BlockBuffer,
const bool Read)
{
uint16_t FileStartBlock = DISK_BLOCK_DataStartBlock + (*FLASHFileStartCluster - 2) * SECTOR_PER_CLUSTER;
uint16_t FileEndBlock = FileStartBlock + (FILE_SECTORS(FLASH_FILE_SIZE_BYTES) - 1);
/* Range check the write request - abort if requested block is not within the
* virtual firmware file sector range */
if (!((BlockNumber >= FileStartBlock) && (BlockNumber <= FileEndBlock)))
return;
#if (FLASHEND > 0xFFFF)
uint32_t FlashAddress = (uint32_t)(BlockNumber - FileStartBlock) * SECTOR_SIZE_BYTES;
#else
uint16_t FlashAddress = (uint16_t)(BlockNumber - FileStartBlock) * SECTOR_SIZE_BYTES;
#endif
if (Read)
{
/* Read out the mapped block of data from the device's FLASH */
for (uint16_t i = 0; i < SECTOR_SIZE_BYTES; i++)
{
#if (FLASHEND > 0xFFFF)
BlockBuffer[i] = pgm_read_byte_far(FlashAddress++);
#else
BlockBuffer[i] = pgm_read_byte(FlashAddress++);
#endif
}
}
else
{
/* Write out the mapped block of data to the device's FLASH */
for (uint16_t i = 0; i < SECTOR_SIZE_BYTES; i += 2)
{
if ((FlashAddress % SPM_PAGESIZE) == 0)
{
/* Erase the given FLASH page, ready to be programmed */
BootloaderAPI_ErasePage(FlashAddress);
}
/* Write the next data word to the FLASH page */
BootloaderAPI_FillWord(FlashAddress, (BlockBuffer[i + 1] << 8) | BlockBuffer[i]);
FlashAddress += 2;
if ((FlashAddress % SPM_PAGESIZE) == 0)
{
/* Write the filled FLASH page to memory */
BootloaderAPI_WritePage(FlashAddress - SPM_PAGESIZE);
}
}
}
}
/** Reads or writes a block of data from/to the physical device EEPROM using a
* block buffer stored in RAM, if the requested block is within the virtual
* firmware file's sector ranges in the emulated FAT file system.
*
* \param[in] BlockNumber Physical disk block to read from/write to
* \param[in,out] BlockBuffer Pointer to the start of the block buffer in RAM
* \param[in] Read If \c true, the requested block is read, if
* \c false, the requested block is written
*/
static void ReadWriteEEPROMFileBlock(const uint16_t BlockNumber,
uint8_t* BlockBuffer,
const bool Read)
{
uint16_t FileStartBlock = DISK_BLOCK_DataStartBlock + (*EEPROMFileStartCluster - 2) * SECTOR_PER_CLUSTER;
uint16_t FileEndBlock = FileStartBlock + (FILE_SECTORS(EEPROM_FILE_SIZE_BYTES) - 1);
/* Range check the write request - abort if requested block is not within the
* virtual firmware file sector range */
if (!((BlockNumber >= FileStartBlock) && (BlockNumber <= FileEndBlock)))
return;
uint16_t EEPROMAddress = (uint16_t)(BlockNumber - FileStartBlock) * SECTOR_SIZE_BYTES;
if (Read)
{
/* Read out the mapped block of data from the device's EEPROM */
for (uint16_t i = 0; i < SECTOR_SIZE_BYTES; i++)
BlockBuffer[i] = ReadEEPROMByte((uint8_t*)EEPROMAddress++);
}
else
{
/* Write out the mapped block of data to the device's EEPROM */
for (uint16_t i = 0; i < SECTOR_SIZE_BYTES; i++)
WriteEEPROMByte((uint8_t*)EEPROMAddress++, BlockBuffer[i]);
}
}
/** Writes a block of data to the virtual FAT filesystem, from the USB Mass
* Storage interface.
*
* \param[in] BlockNumber Index of the block to write.
*/
void VirtualFAT_WriteBlock(const uint16_t BlockNumber)
{
uint8_t BlockBuffer[SECTOR_SIZE_BYTES];
/* Buffer the entire block to be written from the host */
Endpoint_Read_Stream_LE(BlockBuffer, sizeof(BlockBuffer), NULL);
Endpoint_ClearOUT();
switch (BlockNumber)
{
case DISK_BLOCK_BootBlock:
case DISK_BLOCK_FATBlock1:
case DISK_BLOCK_FATBlock2:
/* Ignore writes to the boot and FAT blocks */
break;
case DISK_BLOCK_RootFilesBlock:
/* Copy over the updated directory entries */
memcpy(FirmwareFileEntries, BlockBuffer, sizeof(FirmwareFileEntries));
break;
default:
ReadWriteFLASHFileBlock(BlockNumber, BlockBuffer, false);
ReadWriteEEPROMFileBlock(BlockNumber, BlockBuffer, false);
break;
}
}
/** Reads a block of data from the virtual FAT filesystem, and sends it to the
* host via the USB Mass Storage interface.
*
* \param[in] BlockNumber Index of the block to read.
*/
void VirtualFAT_ReadBlock(const uint16_t BlockNumber)
{
uint8_t BlockBuffer[SECTOR_SIZE_BYTES];
memset(BlockBuffer, 0x00, sizeof(BlockBuffer));
switch (BlockNumber)
{
case DISK_BLOCK_BootBlock:
memcpy(BlockBuffer, &BootBlock, sizeof(FATBootBlock_t));
/* Add the magic signature to the end of the block */
BlockBuffer[SECTOR_SIZE_BYTES - 2] = 0x55;
BlockBuffer[SECTOR_SIZE_BYTES - 1] = 0xAA;
break;
case DISK_BLOCK_FATBlock1:
case DISK_BLOCK_FATBlock2:
/* Cluster 0: Media type/Reserved */
UpdateFAT12ClusterEntry(BlockBuffer, 0, 0xF00 | BootBlock.MediaDescriptor);
/* Cluster 1: Reserved */
UpdateFAT12ClusterEntry(BlockBuffer, 1, 0xFFF);
/* Cluster 2 onwards: Cluster chain of FLASH.BIN */
UpdateFAT12ClusterChain(BlockBuffer, *FLASHFileStartCluster, FILE_CLUSTERS(FLASH_FILE_SIZE_BYTES));
/* Cluster 2+n onwards: Cluster chain of EEPROM.BIN */
UpdateFAT12ClusterChain(BlockBuffer, *EEPROMFileStartCluster, FILE_CLUSTERS(EEPROM_FILE_SIZE_BYTES));
break;
case DISK_BLOCK_RootFilesBlock:
memcpy(BlockBuffer, FirmwareFileEntries, sizeof(FirmwareFileEntries));
break;
default:
ReadWriteFLASHFileBlock(BlockNumber, BlockBuffer, true);
ReadWriteEEPROMFileBlock(BlockNumber, BlockBuffer, true);
break;
}
/* Write the entire read block Buffer to the host */
Endpoint_Write_Stream_LE(BlockBuffer, sizeof(BlockBuffer), NULL);
Endpoint_ClearIN();
}

View file

@ -0,0 +1,302 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaims all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
#ifndef _VIRTUALFAT_H_
#define _VIRTUALFAT_H_
/* Includes: */
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <LUFA/Drivers/USB/USB.h>
#include "../BootloaderAPI.h"
/* Macros: */
/** Size of the virtual FLASH.BIN file in bytes. */
#define FLASH_FILE_SIZE_BYTES (FLASHEND - (FLASHEND - BOOT_START_ADDR) - AUX_BOOT_SECTION_SIZE)
/** Size of the virtual EEPROM.BIN file in bytes. */
#define EEPROM_FILE_SIZE_BYTES E2END
/** Number of sectors that comprise a single logical disk cluster. */
#define SECTOR_PER_CLUSTER 4
/** Size of a single logical sector on the disk. */
#define SECTOR_SIZE_BYTES 512
/** Size of a logical cluster on the disk, in bytes */
#define CLUSTER_SIZE_BYTES (SECTOR_PER_CLUSTER * SECTOR_SIZE_BYTES)
/** Number of sectors required to store a given size in bytes.
*
* \param[in] size Size of the data that needs to be stored
*
* \return Number of sectors required to store the given data on the disk.
*/
#define FILE_SECTORS(size) ((size / SECTOR_SIZE_BYTES) + ((size % SECTOR_SIZE_BYTES) ? 1 : 0))
/** Number of clusters required to store a given size in bytes.
*
* \param[in] size Size of the data that needs to be stored
*
* \return Number of clusters required to store the given data on the disk.
*/
#define FILE_CLUSTERS(size) ((size / CLUSTER_SIZE_BYTES) + ((size % CLUSTER_SIZE_BYTES) ? 1 : 0))
/** Total number of logical sectors/blocks on the disk. */
#define LUN_MEDIA_BLOCKS (FILE_SECTORS(FLASH_FILE_SIZE_BYTES) + FILE_SECTORS(EEPROM_FILE_SIZE_BYTES) + 32)
/** Converts a given time in HH:MM:SS format to a FAT filesystem time.
*
* \note The minimum seconds resolution of FAT is 2, thus odd seconds
* will be truncated to the previous integer multiple of 2 seconds.
*
* \param[in] hh Hours (0-23)
* \param[in] mm Minutes (0-59)
* \param[in] ss Seconds (0-59)
*
* \return Given time encoded as a FAT filesystem timestamp
*/
#define FAT_TIME(hh, mm, ss) ((hh << 11) | (mm << 5) | (ss >> 1))
/** Converts a given date in DD/MM/YYYY format to a FAT filesystem date.
*
* \param[in] dd Days in the month (1-31)
* \param[in] mm Months in the year (1-12)
* \param[in] yyyy Year (1980 - 2107)
*
* \return Given date encoded as a FAT filesystem datestamp
*/
#define FAT_DATE(dd, mm, yyyy) (((yyyy - 1980) << 9) | (mm << 5) | (dd << 0))
/** Bit-rotates a given 8-bit value once to the right.
*
* \param x Value to rotate right once
*
* \return Bit-rotated input value, rotated once to the right.
*/
#define _ROT8(x) ((((x) & 0xFE) >> 1) | (((x) & 1) ? 0x80 : 0x00))
/** Computes the LFN entry checksum of a MSDOS 8.3 format file entry,
* to associate a LFN entry with its short file entry.
*
* \param n0 MSDOS Filename character 1
* \param n1 MSDOS Filename character 2
* \param n2 MSDOS Filename character 3
* \param n3 MSDOS Filename character 4
* \param n4 MSDOS Filename character 5
* \param n5 MSDOS Filename character 6
* \param n6 MSDOS Filename character 7
* \param n7 MSDOS Filename character 8
* \param e0 MSDOS Extension character 1
* \param e1 MSDOS Extension character 2
* \param e2 MSDOS Extension character 3
*
* \return LFN checksum of the given MSDOS 8.3 filename.
*/
#define FAT_CHECKSUM(n0, n1, n2, n3, n4, n5, n6, n7, e0, e1, e2) \
(uint8_t)(_ROT8(_ROT8(_ROT8(_ROT8(_ROT8(_ROT8(_ROT8(_ROT8(_ROT8(_ROT8(n0)+n1)+n2)+n3)+n4)+n5)+n6)+n7)+e0)+e1)+e2)
/** \name FAT Filesystem Flags */
//@{
/** FAT attribute flag to indicate a read-only file. */
#define FAT_FLAG_READONLY (1 << 0)
/** FAT attribute flag to indicate a hidden file. */
#define FAT_FLAG_HIDDEN (1 << 1)
/** FAT attribute flag to indicate a system file. */
#define FAT_FLAG_SYSTEM (1 << 2)
/** FAT attribute flag to indicate a Volume name entry. */
#define FAT_FLAG_VOLUME_NAME (1 << 3)
/** FAT attribute flag to indicate a directory entry. */
#define FAT_FLAG_DIRECTORY (1 << 4)
/** FAT attribute flag to indicate a file ready for archiving. */
#define FAT_FLAG_ARCHIVE (1 << 5)
/** FAT pseudo-attribute flag to indicate a Long File Name entry. */
#define FAT_FLAG_LONG_FILE_NAME 0x0F
/** Ordinal flag marker for FAT Long File Name entries to mark the last entry. */
#define FAT_ORDINAL_LAST_ENTRY (1 << 6)
//@}
/* Enums: */
/** Enum for the Root FAT file entry indexes on the disk. This can be used
* to retrieve the current contents of a known directory entry.
*/
enum
{
/** Volume ID directory entry, giving the name of the virtual disk. */
DISK_FILE_ENTRY_VolumeID = 0,
/** Long File Name FAT file entry of the virtual FLASH.BIN image file. */
DISK_FILE_ENTRY_FLASH_LFN = 1,
/** Legacy MSDOS FAT file entry of the virtual FLASH.BIN image file. */
DISK_FILE_ENTRY_FLASH_MSDOS = 2,
/** Long File Name FAT file entry of the virtual EEPROM.BIN image file. */
DISK_FILE_ENTRY_EEPROM_LFN = 3,
/** Legacy MSDOS FAT file entry of the virtual EEPROM.BIN image file. */
DISK_FILE_ENTRY_EEPROM_MSDOS = 4,
};
/** Enum for the physical disk blocks of the virtual disk. */
enum
{
/** Boot sector disk block. */
DISK_BLOCK_BootBlock = 0,
/** First copy of the FAT table block. */
DISK_BLOCK_FATBlock1 = 1,
/** Second copy of the FAT table block. */
DISK_BLOCK_FATBlock2 = 2,
/** Root file and directory entries block. */
DISK_BLOCK_RootFilesBlock = 3,
/** Start block of the disk data section. */
DISK_BLOCK_DataStartBlock = 4,
};
/* Type Definitions: */
/** FAT boot block structure definition, used to identify the core
* parameters of a FAT file system stored on a disk.
*
* \note This definition is truncated to save space; the magic signature
* \c 0xAA55 must be appended to the very end of the block for it
* to be detected by the host as a valid boot block.
*/
typedef struct
{
uint8_t Bootstrap[3];
uint8_t Description[8];
uint16_t SectorSize;
uint8_t SectorsPerCluster;
uint16_t ReservedSectors;
uint8_t FATCopies;
uint16_t RootDirectoryEntries;
uint16_t TotalSectors16;
uint8_t MediaDescriptor;
uint16_t SectorsPerFAT;
uint16_t SectorsPerTrack;
uint16_t Heads;
uint32_t HiddenSectors;
uint32_t TotalSectors32;
uint16_t PhysicalDriveNum;
uint8_t ExtendedBootRecordSig;
uint32_t VolumeSerialNumber;
uint8_t VolumeLabel[11];
uint8_t FilesystemIdentifier[8];
/* uint8_t BootstrapProgram[448]; */
/* uint16_t MagicSignature; */
} FATBootBlock_t;
/** FAT directory entry structure, for the various kinds of File and
* directory descriptors on a FAT disk.
*/
typedef union
{
/** VFAT Long File Name file entry. */
struct
{
uint8_t Ordinal;
uint16_t Unicode1;
uint16_t Unicode2;
uint16_t Unicode3;
uint16_t Unicode4;
uint16_t Unicode5;
uint8_t Attribute;
uint8_t Reserved1;
uint8_t Checksum;
uint16_t Unicode6;
uint16_t Unicode7;
uint16_t Unicode8;
uint16_t Unicode9;
uint16_t Unicode10;
uint16_t Unicode11;
uint16_t Reserved2;
uint16_t Unicode12;
uint16_t Unicode13;
} VFAT_LongFileName;
/** Legacy FAT MSDOS 8.3 file entry. */
struct
{
uint8_t Filename[8];
uint8_t Extension[3];
uint8_t Attributes;
uint8_t Reserved[10];
uint16_t CreationTime;
uint16_t CreationDate;
uint16_t StartingCluster;
uint32_t FileSizeBytes;
} MSDOS_File;
/** Legacy FAT MSDOS (sub-)directory entry. */
struct
{
uint8_t Name[11];
uint8_t Attributes;
uint8_t Reserved[10];
uint16_t CreationTime;
uint16_t CreationDate;
uint16_t StartingCluster;
uint32_t Reserved2;
} MSDOS_Directory;
} FATDirectoryEntry_t;
/* Function Prototypes: */
#if defined(INCLUDE_FROM_VIRTUAL_FAT_C)
static uint8_t ReadEEPROMByte(const uint8_t* const Address) ATTR_NO_INLINE;
static void WriteEEPROMByte(uint8_t* const Address,
const uint8_t Data) ATTR_NO_INLINE;
static void UpdateFAT12ClusterEntry(uint8_t* const FATTable,
const uint16_t Index,
const uint16_t ChainEntry) AUX_BOOT_SECTION;
static void UpdateFAT12ClusterChain(uint8_t* const FATTable,
const uint16_t StartIndex,
const uint8_t ChainLength) AUX_BOOT_SECTION;
static void ReadWriteFLASHFileBlock(const uint16_t BlockNumber,
uint8_t* BlockBuffer,
const bool Read) AUX_BOOT_SECTION;
static void ReadWriteEEPROMFileBlock(const uint16_t BlockNumber,
uint8_t* BlockBuffer,
const bool Read) AUX_BOOT_SECTION;
#endif
void VirtualFAT_WriteBlock(const uint16_t BlockNumber) AUX_BOOT_SECTION;
void VirtualFAT_ReadBlock(const uint16_t BlockNumber) AUX_BOOT_SECTION;
#endif

View file

@ -0,0 +1,156 @@
<asf xmlversion="1.0">
<project caption="Mass Storage Bootloader - 128KB FLASH / 8KB Boot - AVR8 Architecture" id="lufa.bootloaders.mass_storage.avr8.128_8" force-caption="true" workspace-name="lufa_ms_128kb_8kb_">
<require idref="lufa.bootloaders.mass_storage"/>
<require idref="lufa.boards.dummy.avr8"/>
<generator value="as5_8"/>
<device-support value="at90usb1287"/>
<config name="lufa.drivers.board.name" value="none"/>
<config name="config.compiler.optimization.level" value="size"/>
<build type="define" name="F_CPU" value="16000000UL"/>
<build type="define" name="F_USB" value="16000000UL"/>
<build type="define" name="BOOT_START_ADDR" value="0x1E000"/>
<build type="linker-config" subtype="flags" value="--section-start=.text=0x1E000"/>
<build type="define" name="AUX_BOOT_SECTION_SIZE" value="0"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_trampolines=0x1FFA0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Trampolines"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_jumptable=0x1FFE0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_JumpTable"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_signatures=0x1FFF8"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Signatures"/>
</project>
<project caption="Mass Storage Bootloader - 64KB FLASH / 8KB Boot - AVR8 Architecture" id="lufa.bootloaders.mass_storage.avr8.64_8" force-caption="true" workspace-name="lufa_ms_64kb_8kb_">
<require idref="lufa.bootloaders.mass_storage"/>
<require idref="lufa.boards.dummy.avr8"/>
<generator value="as5_8"/>
<device-support value="at90usb647"/>
<config name="lufa.drivers.board.name" value="none"/>
<config name="config.compiler.optimization.level" value="size"/>
<build type="define" name="F_CPU" value="16000000UL"/>
<build type="define" name="F_USB" value="16000000UL"/>
<build type="define" name="BOOT_START_ADDR" value="0xE000"/>
<build type="linker-config" subtype="flags" value="--section-start=.text=0xE000"/>
<build type="define" name="AUX_BOOT_SECTION_SIZE" value="0"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_trampolines=0xFFA0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Trampolines"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_jumptable=0xFFE0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_JumpTable"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_signatures=0xFFF8"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Signatures"/>
</project>
<project caption="Mass Storage Bootloader - 32KB FLASH / 4KB Boot (2KB AUX) - AVR8 Architecture" id="lufa.bootloaders.mass_storage.avr8.32_4" force-caption="true" workspace-name="lufa_ms_32kb_4kb_">
<require idref="lufa.bootloaders.mass_storage"/>
<require idref="lufa.boards.dummy.avr8"/>
<generator value="as5_8"/>
<device-support value="atmega32u4"/>
<config name="lufa.drivers.board.name" value="none"/>
<config name="config.compiler.optimization.level" value="size"/>
<build type="define" name="F_CPU" value="16000000UL"/>
<build type="define" name="F_USB" value="16000000UL"/>
<build type="define" name="BOOT_START_ADDR" value="0x7000"/>
<build type="linker-config" subtype="flags" value="--section-start=.text=0x7000"/>
<build type="define" name="AUX_BOOT_SECTION_SIZE" value="2048"/>
<build type="linker-config" subtype="flags" value="--section-start=.boot_aux=0x6810"/>
<build type="linker-config" subtype="flags" value="--section-start=.boot_aux_trampoline=0x6800"/>
<build type="linker-config" subtype="flags" value="--undefined=Boot_AUX_Trampoline"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_trampolines=0x7FA0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Trampolines"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_jumptable=0x7FE0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_JumpTable"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_signatures=0x7FF8"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Signatures"/>
</project>
<project caption="Mass Storage Bootloader - 16KB FLASH / 4KB Boot (2KB AUX) - AVR8 Architecture" id="lufa.bootloaders.mass_storage.avr8.16_4" force-caption="true" workspace-name="lufa_ms_16kb_4kb_">
<require idref="lufa.bootloaders.mass_storage"/>
<require idref="lufa.boards.dummy.avr8"/>
<generator value="as5_8"/>
<device-support value="atmega16u2"/>
<config name="lufa.drivers.board.name" value="none"/>
<config name="config.compiler.optimization.level" value="size"/>
<build type="define" name="F_CPU" value="16000000UL"/>
<build type="define" name="F_USB" value="16000000UL"/>
<build type="define" name="BOOT_START_ADDR" value="0x3000"/>
<build type="linker-config" subtype="flags" value="--section-start=.text=0x3000"/>
<build type="define" name="AUX_BOOT_SECTION_SIZE" value="2048"/>
<build type="linker-config" subtype="flags" value="--section-start=.boot_aux=0x2810"/>
<build type="linker-config" subtype="flags" value="--section-start=.boot_aux_trampoline=0x2800"/>
<build type="linker-config" subtype="flags" value="--undefined=Boot_AUX_Trampoline"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_trampolines=0x3FA0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Trampolines"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_jumptable=0x3FE0"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_JumpTable"/>
<build type="linker-config" subtype="flags" value="--section-start=.apitable_signatures=0x3FF8"/>
<build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Signatures"/>
</project>
<module type="application" id="lufa.bootloaders.mass_storage" caption="Mass Storage Bootloader">
<info type="description" value="summary">
Mass Storage Class Bootloader, capable of reprogramming a device via binary BIN files copied to the virtual FAT12 file-system it creates when plugged into a host.
</info>
<info type="gui-flag" value="move-to-root"/>
<info type="keyword" value="Technology">
<keyword value="Bootloaders"/>
<keyword value="USB Device"/>
</info>
<device-support-alias value="lufa_avr8"/>
<device-support-alias value="lufa_xmega"/>
<device-support-alias value="lufa_uc3"/>
<build type="include-path" value="."/>
<build type="c-source" value="BootloaderMassStorage.c"/>
<build type="header-file" value="BootloaderMassStorage.h"/>
<build type="c-source" value="Descriptors.c"/>
<build type="header-file" value="Descriptors.h"/>
<build type="c-source" value="BootloaderAPI.c"/>
<build type="header-file" value="BootloaderAPI.h"/>
<build type="asm-source" value="BootloaderAPITable.S"/>
<build type="module-config" subtype="path" value="Config"/>
<build type="header-file" value="Config/LUFAConfig.h"/>
<build type="header-file" value="Config/AppConfig.h"/>
<build type="include-path" value="Lib"/>
<build type="header-file" value="Lib/VirtualFAT.h"/>
<build type="c-source" value="Lib/VirtualFAT.c"/>
<build type="header-file" value="Lib/SCSI.h"/>
<build type="c-source" value="Lib/SCSI.c"/>
<build type="distribute" subtype="user-file" value="doxyfile"/>
<build type="distribute" subtype="user-file" value="BootloaderMassStorage.txt"/>
<require idref="lufa.common"/>
<require idref="lufa.platform"/>
<require idref="lufa.drivers.usb"/>
<require idref="lufa.drivers.board"/>
<require idref="lufa.drivers.board.leds"/>
</module>
</asf>

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,68 @@
#
# LUFA Library
# Copyright (C) Dean Camera, 2014.
#
# dean [at] fourwalledcubicle [dot] com
# www.lufa-lib.org
#
# --------------------------------------
# LUFA Project Makefile.
# --------------------------------------
# Run "make help" for target help.
MCU = at90usb1287
ARCH = AVR8
BOARD = USBKEY
F_CPU = 8000000
F_USB = $(F_CPU)
OPTIMIZATION = s
TARGET = BootloaderMassStorage
SRC = $(TARGET).c Descriptors.c BootloaderAPI.c BootloaderAPITable.S Lib/SCSI.c Lib/VirtualFAT.c $(LUFA_SRC_USB) $(LUFA_SRC_USBCLASS)
LUFA_PATH = ../../LUFA
CC_FLAGS = -DUSE_LUFA_CONFIG_HEADER -IConfig/ -DBOOT_START_ADDR=$(BOOT_START_OFFSET)
LD_FLAGS = -Wl,--section-start=.text=$(BOOT_START_OFFSET) $(BOOT_API_LD_FLAGS)
# Flash size and bootloader section sizes of the target, in KB. These must
# match the target's total FLASH size and the bootloader size set in the
# device's fuses.
FLASH_SIZE_KB = 128
BOOT_SECTION_SIZE_KB = 8
# Bootloader address calculation formulas
# Do not modify these macros, but rather modify the dependent values above.
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_SEC_OFFSET = $(call CALC_ADDRESS_IN_HEX, ($(FLASH_SIZE_KB) * 1024) - ($(strip $(1))) )
# Bootloader linker section flags for relocating the API table sections to
# known FLASH addresses - these should not normally be user-edited.
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, .apitable_trampolines, BootloaderAPI_Trampolines, 96)
BOOT_API_LD_FLAGS += $(call BOOT_SECTION_LD_FLAG, .apitable_jumptable, BootloaderAPI_JumpTable, 32)
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_SIZE=0
else
AUX_BOOT_SECTION_SIZE_KB = (6 - $(BOOT_SECTION_SIZE_KB))
CC_FLAGS += -DAUX_BOOT_SECTION_SIZE='($(AUX_BOOT_SECTION_SIZE_KB) * 1024)'
LD_FLAGS += -Wl,--section-start=.boot_aux=$(call BOOT_SEC_OFFSET, (($(BOOT_SECTION_SIZE_KB) + $(AUX_BOOT_SECTION_SIZE_KB)) * 1024 - 16))
LD_FLAGS += $(call BOOT_SECTION_LD_FLAG, .boot_aux_trampoline, Boot_AUX_Trampoline, ($(BOOT_SECTION_SIZE_KB) + $(AUX_BOOT_SECTION_SIZE_KB)) * 1024)
endif
# Default target
all:
# Include LUFA build script makefiles
include $(LUFA_PATH)/Build/lufa_core.mk
include $(LUFA_PATH)/Build/lufa_sources.mk
include $(LUFA_PATH)/Build/lufa_build.mk
include $(LUFA_PATH)/Build/lufa_cppcheck.mk
include $(LUFA_PATH)/Build/lufa_doxygen.mk
include $(LUFA_PATH)/Build/lufa_avrdude.mk
include $(LUFA_PATH)/Build/lufa_atprogram.mk