Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/LICENSE.txt
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/LICENSE.txt	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/LICENSE.txt	(revision 30)
@@ -0,0 +1,249 @@
+MICROSOFT SOFTWARE LICENSE TERMS 
+
+MICROSOFT AZURE RTOS 
+
+
+These license terms are an agreement between you and Microsoft Corporation (or
+one of its affiliates). They apply to the software named above and any Microsoft
+services or software updates (except to the extent such services or updates are
+accompanied by new or additional terms, in which case those different terms
+apply prospectively and do not alter your or Microsoft’s rights relating to
+pre-updated software or services). IF YOU COMPLY WITH THESE LICENSE TERMS, YOU
+HAVE THE RIGHTS BELOW.  BY USING THE SOFTWARE, YOU ACCEPT THESE TERMS. 
+
+1. INSTALLATION AND USE RIGHTS.  
+
+a) General. You may (I) install, use and modify the software and (ii) install and use the included Microsoft
+Applications (if any), each solely for internal development, testing and evaluation purposes.
+Distribution or production use is governed by the license terms set forth in
+Section 2.  You may also obtain distribution or production use rights through a separate agreement with 
+Microsoft. 
+
+b) Contributions. Microsoft welcomes contributions to this software. In the event
+that you make a contribution to this software you will be required to agree to a
+Contributor License Agreement (CLA) declaring that you have the right to, and
+actually do, grant Microsoft the rights to use your contribution. For details,
+visit https://cla.microsoft.com.  
+
+c) Included Microsoft Applications. The software may include other Microsoft
+applications which are governed by the licenses embedded in or made available
+with those applications.  
+
+d) Third Party Components. The software may include third party components with
+separate legal notices or governed by other agreements, as may be described
+within the software or in the ThirdPartyNotices file(s) accompanying the
+software. 
+
+e) Competitive Benchmarking. If you are a direct competitor, and you access or use
+the software for purposes of competitive benchmarking, analysis, or intelligence
+gathering, you waive as against Microsoft, its subsidiaries, and its affiliated
+companies (including prospectively) any competitive use, access, and
+benchmarking test restrictions in the terms governing your software to the
+extent your terms of use are, or purport to be, more restrictive than
+Microsoft’s terms. If you do not waive any such purported restrictions in the
+terms governing your software, you are not allowed to access or use this
+software, and will not do so. 
+
+2. DISTRIBUTION AND PRODUCTION USE. If you have obtained and/or are developing on
+microprocessor(s) and/or microcontroller(s) (“hardware”) listed in the file
+named “LICENSED-HARDWARE.txt” included in the repository and/or distributed with
+the software you have the following rights in and to the software solely when
+used in combination with the hardware. In the event hardware is not listed in
+the LICENSED-HARDWARE.txt file, you do not have the rights in this Section 2. 
+
+a) Distribution and Production Use Rights.  
+
+i. You may use the software in production (e.g. program the modified or unmodified
+software to devices you own or control) and distribute (i.e. make available to
+third parties) the modified or unmodified binary image produced from this code.
+
+ii. You may permit your device distributors or developers to copy and distribute the
+binary image as programmed or to be programmed to your devices. 
+
+iii. You may redistribute the unmodified or modified source to your device
+distributors or developers. Modifications must be clearly marked. Any
+redistribution in source code form must contain this license and any other
+licenses that accompany the software. 
+
+b) Requirements. For any code you distribute, you must: 
+
+i. when distributed in binary form, except as embedded in a device, include with
+such distribution the terms of this agreement;  
+ii. when distributed in source code form to distributors or developers of your
+devices, include with such distribution the terms of this agreement; and 
+iii. indemnify, defend and hold harmless Microsoft from any claims, including claims arising from any High Risk Uses, and inclusive of attorneys’ fees, related to the distribution or use of your devices that include the software, except to the extent that any intellectual property claim is based solely on the unmodified software.
+
+c) Restrictions. You may not: 
+i. use or modify the software to create competing real time operating system
+software;  
+
+ii. remove any copyright notices or licenses contained in the software; 
+
+iii. use Microsoft’s trademarks or trade dress in your application in any way that
+suggests your device or application comes from or is endorsed by Microsoft;  
+
+iv. transfer individual components, specific libraries, classes, functions or code
+fragments of the software separately for purposes unrelated to the software; or 
+
+v. use or distribute the software in any way that would subject the software or
+Microsoft’s intellectual property or technology to any other license terms. 
+
+3. SCOPE OF LICENSE. The software is licensed, not sold. Microsoft reserves all
+other rights. Unless applicable law gives you more rights despite this
+limitation, you will not (and have no right to): 
+
+a) remove, minimize, block, or modify any notices of Microsoft or its suppliers in
+the software; 
+
+b) use the software in any way that is against the law or to create or propagate
+malware; or 
+
+c) share, publish, distribute, or lease the software (except as permitted in
+Section 2 above), or provide the software as a stand-alone offering for others
+to use. 
+
+4. DATA. This software may interact with other Microsoft products that collect data
+that is transmitted to Microsoft. To learn more about how Microsoft processes
+personal data we collect, please see the Microsoft Privacy Statement at
+https://go.microsoft.com/fwlink/?LinkId=248681. 
+
+5. EXPORT RESTRICTIONS. You must comply with all domestic and international export
+laws and regulations that apply to the software, which include restrictions on
+destinations, end users, and end use. For further information on export
+restrictions, visit https://aka.ms/exporting. 
+
+6. SUPPORT SERVICES. Microsoft is not obligated under this agreement to provide any
+support services for the software. Any support provided is “as is”, “with all
+faults”, and without warranty of any kind. 
+
+7. UPDATES. Microsoft may periodically update the software. You may obtain updates
+only from Microsoft or Microsoft-authorized sources. Updates may not include or
+support all existing software features, services, or peripheral devices. 
+
+8. TERMINATION. Without prejudice to any other rights, Microsoft may terminate this
+agreement if you fail to comply with any of its terms or conditions. In such
+event, you must destroy all copies of the software and all of its component
+parts. 
+
+9. ENTIRE AGREEMENT. This agreement, and any other terms Microsoft may provide for
+supplements, updates, or third-party applications, is the entire agreement for
+the software. To the extent you have entered into a separate agreement with
+Microsoft relating specifically to the software, the terms in such agreement
+shall control. 
+
+10. APPLICABLE LAW AND PLACE TO RESOLVE DISPUTES. If you acquired the software in
+the United States or Canada, the laws of the state or province where you live
+(or, if a business, where your principal place of business is located) govern
+the interpretation of this agreement, claims for its breach, and all other
+claims (including consumer protection, unfair competition, and tort claims),
+regardless of conflict of laws principles. If you acquired the software in any
+other country, its laws apply. If U.S. federal jurisdiction exists, you and
+Microsoft consent to exclusive jurisdiction and venue in the federal court in
+King County, Washington for all disputes heard in court. If not, you and
+Microsoft consent to exclusive jurisdiction and venue in the Superior Court of
+King County, Washington for all disputes heard in court. 
+
+11. CONSUMER RIGHTS; REGIONAL VARIATIONS. This agreement describes certain legal
+rights. You may have other rights, including consumer rights, under the laws of
+your state or country. Separate and apart from your relationship with Microsoft,
+you may also have rights with respect to the party from which you acquired the
+software. This agreement does not change those other rights if the laws of your
+state or country do not permit it to do so. For example, if you acquired the
+software in one of the below regions, or mandatory country law applies, then the
+following provisions apply to you: 
+
+a) Australia. You have statutory guarantees under the Australian Consumer Law and
+nothing in this agreement is intended to affect those rights. 
+
+b) Germany and Austria. 
+
+i. Warranty. The properly licensed software will perform substantially as
+described in any Microsoft materials that accompany the software. However,
+Microsoft gives no contractual guarantee in relation to the licensed software. 
+
+ii. Limitation of Liability. In case of intentional conduct, gross negligence,
+claims based on the Product Liability Act, as well as, in case of death or
+personal or physical injury, Microsoft is liable according to the statutory law.
+
+
+Subject to the foregoing clause ii., Microsoft will only be liable for slight
+negligence if Microsoft is in breach of such material contractual obligations,
+the fulfillment of which facilitate the due performance of this agreement, the
+breach of which would endanger the purpose of this agreement and the compliance
+with which a party may constantly trust in (so-called "cardinal obligations").
+In other cases of slight negligence, Microsoft will not be liable for slight
+negligence. 
+12. DISCLAIMER OF WARRANTY. 
+a) THE SOFTWARE IS LICENSED “AS IS.” YOU BEAR THE RISK OF
+USING IT. MICROSOFT GIVES NO EXPRESS WARRANTIES, GUARANTEES, OR CONDITIONS. TO
+THE EXTENT PERMITTED UNDER APPLICABLE LAWS, MICROSOFT EXCLUDES ALL IMPLIED
+WARRANTIES, INCLUDING MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
+NON-INFRINGEMENT. 
+b) HIGH RISK USE DISCLAIMER. WARNING: THE SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE  WHERE FAILURE OR FAULT OF ANY KIND OF THE SOFTWARE COULD  RESULT IN DEATH OR SERIOUS BODILY INJURY, OR IN  PHYSICAL OR ENVIRONMENTAL DAMAGE (“collectively High Risk Use”). Accordingly, You must design and implement your hardware and software such that, in the event of any interruption, defect, error, or other failure of the software, the safety of people, property, and the environment are not reduced below a level that is reasonable, appropriate, and legal, whether in general or for a specific industry. Your High Risk Use of the software is at Your own risk. 
+
+13. LIMITATION ON AND EXCLUSION OF DAMAGES. IF YOU HAVE ANY BASIS FOR RECOVERING
+DAMAGES DESPITE THE PRECEDING DISCLAIMER OF WARRANTY, YOU CAN RECOVER FROM
+MICROSOFT AND ITS SUPPLIERS ONLY DIRECT DAMAGES UP TO U.S. $5.00. YOU CANNOT
+RECOVER ANY OTHER DAMAGES, INCLUDING CONSEQUENTIAL, LOST PROFITS, SPECIAL,
+INDIRECT, OR INCIDENTAL DAMAGES. 
+
+This limitation applies to (a) anything related to the software, services,
+content (including code) on third party Internet sites, or third party
+applications; and (b) claims for breach of contract, warranty, guarantee, or
+condition; strict liability, negligence, or other tort; or any other claim; in
+each case to the extent permitted by applicable law. 
+
+It also applies even if Microsoft knew or should have known about the
+possibility of the damages. The above limitation or exclusion may not apply to
+you because your state, province, or country may not allow the exclusion or
+limitation of incidental, consequential, or other damages. 
+
+ Please note: As this software is distributed in Canada, some of the clauses in
+this agreement are provided below in French. 
+
+Remarque: Ce logiciel étant distribué au Canada, certaines des clauses dans ce
+contrat sont fournies ci-dessous en français. 
+
+EXONÉRATION DE GARANTIE. 
+a)	Le logiciel visé par une licence est offert « tel quel
+». Toute utilisation de ce logiciel est à votre seule risque et péril. Microsoft
+n’accorde aucune autre garantie expresse. Vous pouvez bénéficier de droits
+additionnels en vertu du droit local sur la protection des consommateurs, que ce
+contrat ne peut modifier. La ou elles sont permises par le droit locale, les
+garanties implicites de qualité marchande, d’adéquation à un usage particulier
+et d’absence de contrefaçon sont exclues. 
+b)	CLAUSE D’EXCLUSION DE RESPONSABILITÉ RELATIVE À L’UTILISATION À HAUT RISQUE. 
+AVERTISSEMENT: LE LOGICIEL N’EST PAS CONÇU OU DESTINÉ À ÊTRE UTILISÉ LORSQU’UNE 
+DÉFAILLANCE OU UN DÉFAUT DE QUELQUE NATURE QUE CE SOIT POURRAIT ENTRAÎNER LA 
+MORT OU DES BLESSURES CORPORELLES GRAVES, OU DES DOMMAGES PHYSIQUES OU 
+ENVIRONNEMENTAUX (« Utilisation à haut risque »). Par conséquent, vous devez concevoir et mettre en 
+œuvre votre équipement et votre logiciel de manière à ce que, en cas d’interruption, de défaut, d’erreur 
+ou de toute autre défaillance du logiciel, la sécurité des personnes, des biens et de l’environnement ne 
+soit pas réduite en dessous d’un niveau raisonnable, approprié et légal, que ce soit en général ou pour 
+un secteur spécifique. Votre utilisation à haut risque du logiciel est à vos propres risques.
+
+LIMITATION DES DOMMAGES-INTÉRÊTS ET EXCLUSION DE RESPONSABILITÉ POUR LES
+DOMMAGES. Vous pouvez obtenir de Microsoft et de ses fournisseurs une
+indemnisation en cas de dommages directs uniquement à hauteur de 5,00 $ US. Vous
+ne pouvez prétendre à aucune indemnisation pour les autres dommages, y compris
+les dommages spéciaux, indirects ou accessoires et pertes de bénéfices. 
+
+Cette limitation concerne: 
+
+•tout ce qui est relié au logiciel, aux services ou au contenu (y compris le
+code) figurant sur des sites Internet tiers ou dans des programmes tiers; et 
+
+•les réclamations au titre de violation de contrat ou de garantie, ou au titre
+de responsabilité stricte, de négligence ou d’une autre faute dans la limite
+autorisée par la loi en vigueur. 
+
+Elle s’applique également, même si Microsoft connaissait ou devrait connaître
+l’éventualité d’un tel dommage. Si votre pays n’autorise pas l’exclusion ou la
+limitation de responsabilité pour les dommages indirects, accessoires ou de
+quelque nature que ce soit, il se peut que la limitation ou l’exclusion
+ci-dessus ne s’appliquera pas à votre égard. 
+
+EFFET JURIDIQUE. Le présent contrat décrit certains droits juridiques. Vous
+pourriez avoir d’autres droits prévus par les lois de votre pays. Le présent
+contrat ne modifie pas les droits que vous confèrent les lois de votre pays si
+celles-ci ne le permettent pas.
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/LICENSED-HARDWARE.txt
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/LICENSED-HARDWARE.txt	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/LICENSED-HARDWARE.txt	(revision 30)
@@ -0,0 +1,49 @@
+LICENSED HARDWARE LIST
+
+Last Updated September 06, 2024
+
+Microsoft has entered into OEM Agreements with manufacturers of the following microprocessors and
+microcontrollers (the “hardware”) to enable those manufacturers to include and distribute Azure RTOS
+in certain hardware. By purchasing and using hardware on this list you inherit the “Distribution and
+Production Use” rights in Section 2 of the Microsoft Software License Terms for Microsoft Azure RTOS. If
+hardware is not listed below, you do not have those rights.
+
+Manufacturer:
+
+	STMicroelectronics
+
+Licensed Microcontrollers and Microprocessors:
+
+	STM32H7 Series
+
+	STM32U5 Series
+
+	STM32F4 Series
+
+	STM32L4/STM32L4+ series
+
+	STM32G4 Series
+
+	STM32F7 Series
+
+	STM32L5 Series
+
+	STM32G0 Series
+
+	STM32WL Series
+
+	STM32WB Series
+
+	STM32C0 Series
+
+	STM32H5 Series
+
+	STM32WBA Series
+
+	STM32MP1 Series
+
+	STM32U0 Series
+
+	STM32U3 Series
+
+	STM32N6 Series
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/drivers/fx_stm32_sd_driver.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/drivers/fx_stm32_sd_driver.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/drivers/fx_stm32_sd_driver.c	(revision 30)
@@ -0,0 +1,411 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Partial Copyright (c) Microsoft Corporation. All rights reserved.*/
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*      Partial Copyright (c) STMicroelctronics 2020. All rights reserved */
+/**************************************************************************/
+
+
+/* Include necessary system files.  */
+#include "fx_stm32_sd_driver.h"
+
+/*
+ * the scratch buffer is required when performing DMA transfers using unaligned addresses
+ * When CPU cache is enabled, the scratch buffer should be 32-byte aligned to match a whole cache line
+ * otherwise it is 4-byte aligned to match the DMA alignment constraints
+ */
+
+#if (FX_STM32_SD_CACHE_MAINTENANCE == 1)
+static UCHAR scratch[FX_STM32_SD_DEFAULT_SECTOR_SIZE] __attribute__ ((aligned (32)));
+#else
+static UCHAR scratch[FX_STM32_SD_DEFAULT_SECTOR_SIZE] __attribute__ ((aligned (4)));
+#endif
+
+UINT  _fx_partition_offset_calculate(void  *partition_sector, UINT partition, ULONG *partition_start, ULONG *partition_size);
+
+static UINT sd_read_data(FX_MEDIA *media_ptr, ULONG sector, UINT num_sectors, UINT use_scratch_buffer);
+static UINT sd_write_data(FX_MEDIA *media_ptr, ULONG sector, UINT num_sectors, UINT use_scratch_buffer);
+
+static UINT is_initialized = 0;
+
+
+static INT check_sd_status(uint32_t instance)
+{
+  uint32_t start = FX_STM32_SD_CURRENT_TIME();
+
+  while (FX_STM32_SD_CURRENT_TIME() - start < FX_STM32_SD_DEFAULT_TIMEOUT)
+  {
+    if (fx_stm32_sd_get_status(instance) == 0)
+    {
+      return 0;
+    }
+  }
+
+  return 1;
+}
+
+/**
+* @brief This function is the entry point to the STM32 SD disk driver.
+* It relies on the STM32 peripheral library from ST.
+* @param media_ptr: FileX's Media Config Block
+* @retval None
+*/
+VOID  fx_stm32_sd_driver(FX_MEDIA *media_ptr)
+{
+  UINT status;
+  UINT unaligned_buffer;
+  ULONG partition_start;
+  ULONG partition_size;
+
+#if (FX_STM32_SD_INIT == 0)
+ /* the SD was initialized by the application */
+  is_initialized = 1;
+#endif
+  /* before performing any operation, check the status of the SD IP */
+  if (is_initialized == 1)
+  {
+    if (check_sd_status(FX_STM32_SD_INSTANCE) != 0)
+    {
+      media_ptr->fx_media_driver_status =  FX_IO_ERROR;
+      return;
+    }
+  }
+
+#if (FX_STM32_SD_DMA_API == 1)
+  /* the SD DMA requires a 4-byte aligned buffers */
+  unaligned_buffer = (UINT)(media_ptr->fx_media_driver_buffer) & 0x3;
+#else
+  /* if the DMA is not used there isn't any constraint on buffer alignment */
+  unaligned_buffer = 0;
+#endif
+  /* Process the driver request specified in the media control block.  */
+  switch(media_ptr->fx_media_driver_request)
+  {
+  case FX_DRIVER_INIT:
+    {
+      media_ptr->fx_media_driver_status = FX_SUCCESS;
+
+      FX_STM32_SD_PRE_INIT(media_ptr);
+
+#if (FX_STM32_SD_INIT == 1)
+      /* Initialize the SD instance */
+      if (is_initialized == 0)
+      {
+        status = fx_stm32_sd_init(FX_STM32_SD_INSTANCE);
+
+        if (status == 0)
+        {
+          is_initialized = 1;
+        }
+        else
+        {
+          media_ptr->fx_media_driver_status =  FX_IO_ERROR;
+        }
+      }
+#endif
+      /* call post init user macro */
+      FX_STM32_SD_POST_INIT(media_ptr);
+      break;
+    }
+
+  case FX_DRIVER_UNINIT:
+    {
+      media_ptr->fx_media_driver_status = FX_SUCCESS;
+
+#if (FX_STM32_SD_INIT == 1)
+      status = fx_stm32_sd_deinit(FX_STM32_SD_INSTANCE);
+
+      if (status != 0)
+      {
+        media_ptr->fx_media_driver_status = FX_IO_ERROR;
+      }
+      else
+      {
+        is_initialized = 0;
+      }
+#endif
+      /* call post deinit processing  */
+      FX_STM32_SD_POST_DEINIT(media_ptr);
+
+      break;
+    }
+
+  case FX_DRIVER_READ:
+    {
+      media_ptr->fx_media_driver_status = FX_IO_ERROR;
+
+      if (sd_read_data(media_ptr, media_ptr->fx_media_driver_logical_sector + media_ptr->fx_media_hidden_sectors,
+                       media_ptr->fx_media_driver_sectors, unaligned_buffer) == FX_SUCCESS)
+      {
+        media_ptr->fx_media_driver_status = FX_SUCCESS;
+      }
+
+      break;
+    }
+
+  case FX_DRIVER_WRITE:
+    {
+      media_ptr->fx_media_driver_status = FX_IO_ERROR;
+
+      if (sd_write_data(media_ptr, media_ptr->fx_media_driver_logical_sector + media_ptr->fx_media_hidden_sectors,
+                        media_ptr->fx_media_driver_sectors, unaligned_buffer) == FX_SUCCESS)
+      {
+        media_ptr->fx_media_driver_status = FX_SUCCESS;
+      }
+
+      break;
+    }
+
+  case FX_DRIVER_FLUSH:
+    {
+      /* Return driver success.  */
+      media_ptr->fx_media_driver_status =  FX_SUCCESS;
+      break;
+    }
+
+  case FX_DRIVER_ABORT:
+    {
+      /* Return driver success.  */
+      media_ptr->fx_media_driver_status =  FX_SUCCESS;
+
+      FX_STM32_SD_POST_ABORT(media_ptr);
+      break;
+    }
+
+  case FX_DRIVER_BOOT_READ:
+    {
+      /* the boot sector is the sector zero */
+      status = sd_read_data(media_ptr, 0, media_ptr->fx_media_driver_sectors, unaligned_buffer);
+
+      if (status != FX_SUCCESS)
+      {
+        media_ptr->fx_media_driver_status = status;
+        break;
+      }
+
+      /* Check if the sector 0 is the actual boot sector, otherwise calculate the offset into it.
+      Please note that this should belong to higher level of MW to do this check and it is here
+      as a temporary work solution */
+
+      partition_start =  0;
+
+      status =  _fx_partition_offset_calculate(media_ptr -> fx_media_driver_buffer, 0,
+                                               &partition_start, &partition_size);
+
+      /* Check partition read error.  */
+      if (status)
+      {
+        /* Unsuccessful driver request.  */
+        media_ptr -> fx_media_driver_status =  FX_IO_ERROR;
+        break;
+      }
+
+      /* Now determine if there is a partition...   */
+      if (partition_start)
+      {
+
+        if (check_sd_status(FX_STM32_SD_INSTANCE) != 0)
+        {
+          media_ptr->fx_media_driver_status =  FX_IO_ERROR;
+          break;
+        }
+
+        /* Yes, now lets read the actual boot record.  */
+        status = sd_read_data(media_ptr, partition_start, media_ptr->fx_media_driver_sectors, unaligned_buffer);
+
+        if (status != FX_SUCCESS)
+        {
+          media_ptr->fx_media_driver_status = status;
+          break;
+        }
+      }
+
+      /* Successful driver request.  */
+      media_ptr -> fx_media_driver_status =  FX_SUCCESS;
+      break;
+    }
+
+  case FX_DRIVER_BOOT_WRITE:
+    {
+      status = sd_write_data(media_ptr, 0, media_ptr->fx_media_driver_sectors, unaligned_buffer);
+
+      media_ptr->fx_media_driver_status = status;
+
+      break;
+    }
+
+  default:
+    {
+      media_ptr->fx_media_driver_status =  FX_IO_ERROR;
+      break;
+    }
+  }
+}
+
+/**
+* @brief Read data from uSD into destination buffer
+* @param FX_MEDIA *media_ptr a pointer the main FileX structure
+* @param ULONG start_sector first sector to start reading from
+* @param UINT num_sectors number of sectors to be read
+* @param UINT use_scratch_buffer to enable scratch buffer usage or not.
+* @retval FX_SUCCESS on success FX_BUFFER_ERROR / FX_ACCESS_ERROR / FX_IO_ERROR otherwise
+*/
+
+static UINT sd_read_data(FX_MEDIA *media_ptr, ULONG start_sector, UINT num_sectors, UINT use_scratch_buffer)
+{
+  INT i = 0;
+  UINT status;
+  UCHAR *read_addr;
+
+ /* perform the Pre read operations */
+  FX_STM32_SD_PRE_READ_TRANSFER(media_ptr);
+
+  if (use_scratch_buffer)
+  {
+    read_addr = media_ptr->fx_media_driver_buffer;
+
+    for (i = 0; i < num_sectors; i++)
+    {
+      /* Start reading into the scratch buffer */
+      status = fx_stm32_sd_read_blocks(FX_STM32_SD_INSTANCE, (UINT *)scratch, (UINT)start_sector++, 1);
+
+      if (status != 0)
+      {
+        /* read error occurred, call the error handler code then return immediately */
+        FX_STM32_SD_READ_TRANSFER_ERROR(status);
+        return FX_IO_ERROR;
+      }
+
+    /* wait for read transfer notification */
+       FX_STM32_SD_READ_CPLT_NOTIFY();
+
+#if (FX_STM32_SD_CACHE_MAINTENANCE == 1)
+      invalidate_cache_by_addr((uint32_t*)scratch, FX_STM32_SD_DEFAULT_SECTOR_SIZE);
+#endif
+
+      _fx_utility_memory_copy(scratch, read_addr, FX_STM32_SD_DEFAULT_SECTOR_SIZE);
+      read_addr += FX_STM32_SD_DEFAULT_SECTOR_SIZE;
+    }
+
+    /* Check if all sectors were read */
+    if (i == num_sectors)
+    {
+      status = FX_SUCCESS;
+    }
+    else
+    {
+      status = FX_BUFFER_ERROR;
+    }
+  }
+  else
+  {
+
+    status = fx_stm32_sd_read_blocks(FX_STM32_SD_INSTANCE, (UINT *)media_ptr->fx_media_driver_buffer, (UINT)start_sector, num_sectors);
+
+    if (status != 0)
+    {
+      /* read error occurred, call the error handler code then return immediately */
+      FX_STM32_SD_READ_TRANSFER_ERROR(status);
+
+      return FX_IO_ERROR;
+    }
+
+    /* wait for read transfer notification */
+       FX_STM32_SD_READ_CPLT_NOTIFY();
+
+#if (FX_STM32_SD_CACHE_MAINTENANCE == 1)
+    invalidate_cache_by_addr((uint32_t*)media_ptr->fx_media_driver_buffer, num_sectors * FX_STM32_SD_DEFAULT_SECTOR_SIZE);
+#endif
+
+    status = FX_SUCCESS;
+  }
+
+  /* Operation finished, call the post read macro if defined */
+
+  FX_STM32_SD_POST_READ_TRANSFER(media_ptr);
+  return status;
+}
+
+/**
+* @brief write data buffer into the uSD
+* @param FX_MEDIA *media_ptr a pointer the main FileX structure
+* @param ULONG start_sector first sector to start writing from
+* @param UINT num_sectors number of sectors to be written
+* @param UINT use_scratch_buffer to enable scratch buffer usage or not.
+* @retval FX_SUCCESS on success FX_BUFFER_ERROR / FX_ACCESS_ERROR / FX_IO_ERROR otherwise
+*/
+
+static UINT sd_write_data(FX_MEDIA *media_ptr, ULONG start_sector, UINT num_sectors, UINT use_scratch_buffer)
+{
+  INT i = 0;
+  UINT status;
+  UCHAR *write_addr;
+
+  /* call Pre write operation macro */
+  FX_STM32_SD_PRE_WRITE_TRANSFER(media_ptr);
+
+  if (use_scratch_buffer)
+  {
+    write_addr = media_ptr->fx_media_driver_buffer;
+
+    for (i = 0; i < num_sectors; i++)
+    {
+      _fx_utility_memory_copy(write_addr, scratch, FX_STM32_SD_DEFAULT_SECTOR_SIZE);
+      write_addr += FX_STM32_SD_DEFAULT_SECTOR_SIZE;
+
+#if (FX_STM32_SD_CACHE_MAINTENANCE == 1)
+      /* Clean the DCache to make the SD DMA see the actual content of the scratch buffer */
+      clean_cache_by_addr((uint32_t*)scratch, FX_STM32_SD_DEFAULT_SECTOR_SIZE);
+#endif
+
+      status = fx_stm32_sd_write_blocks(FX_STM32_SD_INSTANCE, (UINT *)scratch, (UINT)start_sector++, 1);
+
+      if (status != 0)
+      {
+        /* in case of error call the error handling macro */
+        FX_STM32_SD_WRITE_TRANSFER_ERROR(status);
+        return FX_IO_ERROR;
+      }
+
+      /*  */
+       FX_STM32_SD_WRITE_CPLT_NOTIFY();
+    }
+
+    if (i == num_sectors)
+    {
+      status = FX_SUCCESS;
+    }
+    else
+    {
+      status = FX_BUFFER_ERROR;
+    }
+  }
+  else
+  {
+#if (FX_STM32_SD_CACHE_MAINTENANCE == 1)
+    clean_cache_by_addr((uint32_t*)media_ptr->fx_media_driver_buffer, num_sectors * FX_STM32_SD_DEFAULT_SECTOR_SIZE);
+#endif
+    status = fx_stm32_sd_write_blocks(FX_STM32_SD_INSTANCE, (UINT *)media_ptr->fx_media_driver_buffer, (UINT)start_sector, num_sectors);
+
+    if (status != 0)
+    {
+      FX_STM32_SD_WRITE_TRANSFER_ERROR(status);
+      return FX_IO_ERROR;
+    }
+
+    /* when defined, wait for the write notification */
+     FX_STM32_SD_WRITE_CPLT_NOTIFY();
+
+    status = FX_SUCCESS;
+  }
+
+  /* perform post write operations */
+  FX_STM32_SD_POST_WRITE_TRANSFER(media_ptr);
+
+
+  return status;
+}
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/inc/fx_api.h
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/inc/fx_api.h	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/inc/fx_api.h	(revision 30)
@@ -0,0 +1,1689 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Application Interface                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  APPLICATION INTERFACE DEFINITION                       RELEASE        */
+/*                                                                        */
+/*    fx_api.h                                            PORTABLE C      */
+/*                                                           6.4.0        */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This file defines the basic Application Interface (API) to the      */
+/*    high-performance FileX FAT compatible embedded file system.         */
+/*    All service prototypes and data structure definitions are defined   */
+/*    in this file.                                                       */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s), and      */
+/*                                            updated product constants,  */
+/*                                            and added conditionals to   */
+/*                                            disable few declarations    */
+/*                                            for code size reduction,    */
+/*                                            resulting in version 6.1    */
+/*  11-09-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1.2  */
+/*  12-31-2020     William E. Lamie         Modified comment(s), and      */
+/*                                            updated product constants,  */
+/*                                            resulting in version 6.1.3  */
+/*  03-02-2021     William E. Lamie         Modified comment(s), and      */
+/*                                            added standalone support,   */
+/*                                            resulting in version 6.1.5  */
+/*  04-02-2021     William E. Lamie         Modified comment(s), and      */
+/*                                            updated product constants,  */
+/*                                            resulting in version 6.1.6  */
+/*  06-02-2021     William E. Lamie         Modified comment(s), and      */
+/*                                            updated product constants,  */
+/*                                            resulting in version 6.1.7  */
+/*  08-02-2021     William E. Lamie         Modified comment(s), and      */
+/*                                            updated product constants,  */
+/*                                            resulting in version 6.1.8  */
+/*  01-31-2022     Bhupendra Naphade        Modified comment(s), and      */
+/*                                            removed fixed sector        */
+/*                                            size in exFAT, fixed        */
+/*                                            errors without cache,       */
+/*                                            resulting in version 6.1.10 */
+/*  04-25-2022     William E. Lamie         Modified comment(s), and      */
+/*                                            updated product constants,  */
+/*                                            resulting in version 6.1.11 */
+/*  07-29-2022     William E. Lamie         Modified comment(s), and      */
+/*                                            updated product constants,  */
+/*                                            resulting in version 6.1.12 */
+/*  10-31-2022     Xiuwen Cai               Modified comment(s), and      */
+/*                                            updated product constants,  */
+/*                                            resulting in version 6.2.0  */
+/*  03-08-2023     Xiuwen Cai               Modified comment(s), and      */
+/*                                            updated product constants,  */
+/*                                            resulting in version 6.2.1  */
+/*  10-31-2023     Xiuwen Cai               Modified comment(s), and      */
+/*                                            updated product constants,  */
+/*                                            resulting in version 6.3.0  */
+/*  12-31-2023     Xiuwen Cai               Modified comment(s), and      */
+/*                                            updated product constants,  */
+/*                                            resulting in version 6.4.0  */
+/*                                                                        */
+/**************************************************************************/
+
+#ifndef FX_API_H
+#define FX_API_H
+
+
+/* Determine if a C++ compiler is being used.  If so, ensure that standard
+   C is used to process the API information.  */
+
+#ifdef __cplusplus
+
+/* Yes, C++ compiler is present.  Use standard C.  */
+extern   "C" {
+
+#endif
+
+
+/* Disable warning of parameter not used. */
+#ifndef FX_PARAMETER_NOT_USED
+#define FX_PARAMETER_NOT_USED(p) ((void)(p))
+#endif /* FX_PARAMETER_NOT_USED */
+
+
+/* Disable ThreadX error checking for internal FileX source code.  */
+
+#ifdef FX_SOURCE_CODE
+#ifndef TX_DISABLE_ERROR_CHECKING
+#define TX_DISABLE_ERROR_CHECKING
+#endif
+#endif
+
+
+/* Include the FileX port-specific file.  */
+
+#include "fx_port.h"
+
+/* Define compiler library include files */
+ 
+#ifdef FX_STANDALONE_ENABLE
+#include   "string.h"
+#endif
+
+/* Define the major/minor version information that can be used by the application
+   and the FileX source as well.  */
+
+#define AZURE_RTOS_FILEX
+#define FILEX_MAJOR_VERSION     6
+#define FILEX_MINOR_VERSION     4
+#define FILEX_PATCH_VERSION     0
+
+/* Define the following symbols for backward compatibility */
+#define EL_PRODUCT_FILEX
+
+#ifdef FX_STANDALONE_ENABLE
+
+/* FileX will be used without Azure RTOS ThreadX */
+
+#ifndef FX_SINGLE_THREAD
+#define FX_SINGLE_THREAD
+#endif /* !FX_SINGLE_THREAD */
+
+
+/* FileX will be used with local path logic disabled */
+
+#ifndef FX_NO_LOCAL_PATH
+#define FX_NO_LOCAL_PATH
+#endif /* !FX_NO_LOCAL_PATH */
+
+
+/* FileX is built without update to the time parameters. */
+
+#ifndef FX_NO_TIMER
+#define FX_NO_TIMER
+#endif /* !FX_NO_TIMER */
+
+#endif
+
+
+/* Override the interrupt protection provided in FileX port files to simply use ThreadX protection,
+   which is often in-line assembly.  */
+
+#ifndef FX_LEGACY_INTERRUPT_PROTECTION
+#undef  FX_INT_SAVE_AREA
+#undef  FX_DISABLE_INTS
+#undef  FX_RESTORE_INTS
+#define FX_INT_SAVE_AREA    TX_INTERRUPT_SAVE_AREA
+#define FX_DISABLE_INTS     TX_DISABLE
+#define FX_RESTORE_INTS     TX_RESTORE
+#endif
+
+
+/* Define the update rate of the system timer.  These values may also be defined at the command
+   line when compiling the fx_system_initialize.c module in the FileX library build.  Alternatively, they can
+   be modified in this file.  Note: the update rate must be an even number of seconds greater
+   than or equal to 2, which is the minimal update rate for FAT time. */
+
+#ifndef FX_UPDATE_RATE_IN_SECONDS
+#define FX_UPDATE_RATE_IN_SECONDS       10     /* Update time at 10 second intervals */
+#endif
+
+#ifndef FX_UPDATE_RATE_IN_TICKS
+#define FX_UPDATE_RATE_IN_TICKS         1000   /* Same update rate, but in ticks  */
+#endif
+
+
+/* Determine if fault tolerance is selected. If so, turn on the old fault tolerant options -
+   if they are not defined already.  */
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+#ifndef FX_FAULT_TOLERANT_DATA
+#define FX_FAULT_TOLERANT_DATA
+#endif
+#ifndef FX_FAULT_TOLERANT
+#define FX_FAULT_TOLERANT
+#endif
+#endif
+
+
+/* Determine if cache is disabled. If so, disable direct read sector cache.  */
+#ifdef FX_DISABLE_CACHE
+#ifndef FX_DISABLE_DIRECT_DATA_READ_CACHE_FILL
+#define FX_DISABLE_DIRECT_DATA_READ_CACHE_FILL
+#endif
+#endif
+
+
+/* Determine if local paths are enabled and if the local path setup code has not been defined.
+   If so, define the default local path setup code for files that reference the local path.  */
+
+#ifndef FX_NO_LOCAL_PATH
+#ifndef FX_LOCAL_PATH_SETUP
+#ifndef FX_SINGLE_THREAD
+#define FX_LOCAL_PATH_SETUP     extern TX_THREAD *_tx_thread_current_ptr;
+#else
+#define FX_NO_LOCAL_PATH
+#endif
+#endif
+#endif
+
+/* Determine if tracing is enabled.  */
+
+#if defined(TX_ENABLE_EVENT_TRACE) && !defined(FX_STANDALONE_ENABLE)
+
+
+/* Trace is enabled. Remap calls so that interrupts can be disabled around the actual event logging.  */
+
+#include "tx_trace.h"
+
+
+/* Define the object types in FileX, if not defined.  */
+
+#ifndef FX_TRACE_OBJECT_TYPE_MEDIA
+#define FX_TRACE_OBJECT_TYPE_MEDIA                      9               /* P1 = FAT cache size, P2 = sector cache size       */
+#define FX_TRACE_OBJECT_TYPE_FILE                       10              /* none                                              */
+#endif
+
+
+/* Define event filters that can be used to selectively disable certain events or groups of events.  */
+
+#define FX_TRACE_ALL_EVENTS                             0x00007800      /* All FileX events                          */
+#define FX_TRACE_INTERNAL_EVENTS                        0x00000800      /* FileX internal events                     */
+#define FX_TRACE_MEDIA_EVENTS                           0x00001000      /* FileX media events                        */
+#define FX_TRACE_DIRECTORY_EVENTS                       0x00002000      /* FileX directory events                    */
+#define FX_TRACE_FILE_EVENTS                            0x00004000      /* FileX file events                         */
+
+
+/* Define the trace events in FileX, if not defined.  */
+
+/* Define FileX Trace Events, along with a brief description of the additional information fields,
+   where I1 -> Information Field 1, I2 -> Information Field 2, etc.  */
+
+/* Define the FileX internal events first.  */
+
+#ifndef FX_TRACE_INTERNAL_LOG_SECTOR_CACHE_MISS
+#define FX_TRACE_INTERNAL_LOG_SECTOR_CACHE_MISS         201             /* I1 = media ptr, I2 = sector, I3 = total misses, I4 = cache size          */
+#define FX_TRACE_INTERNAL_DIR_CACHE_MISS                202             /* I1 = media ptr, I2 = total misses                                        */
+#define FX_TRACE_INTERNAL_MEDIA_FLUSH                   203             /* I1 = media ptr, I2 = dirty sectors                                       */
+#define FX_TRACE_INTERNAL_DIR_ENTRY_READ                204             /* I1 = media ptr                                                           */
+#define FX_TRACE_INTERNAL_DIR_ENTRY_WRITE               205             /* I1 = media ptr                                                           */
+#define FX_TRACE_INTERNAL_IO_DRIVER_READ                206             /* I1 = media ptr, I2 = sector, I3 = number of sectors, I4 = buffer         */
+#define FX_TRACE_INTERNAL_IO_DRIVER_WRITE               207             /* I1 = media ptr, I2 = sector, I3 = number of sectors, I4 = buffer         */
+#define FX_TRACE_INTERNAL_IO_DRIVER_FLUSH               208             /* I1 = media ptr                                                           */
+#define FX_TRACE_INTERNAL_IO_DRIVER_ABORT               209             /* I1 = media ptr                                                           */
+#define FX_TRACE_INTERNAL_IO_DRIVER_INIT                210             /* I1 = media ptr                                                           */
+#define FX_TRACE_INTERNAL_IO_DRIVER_BOOT_READ           211             /* I1 = media ptr, I2 = buffer                                              */
+#define FX_TRACE_INTERNAL_IO_DRIVER_RELEASE_SECTORS     212             /* I1 = media ptr, I2 = sector, I3 = number of sectors                      */
+#define FX_TRACE_INTERNAL_IO_DRIVER_BOOT_WRITE          213             /* I1 = media ptr, I2 = buffer                                              */
+#define FX_TRACE_INTERNAL_IO_DRIVER_UNINIT              214             /* I1 = media ptr                                                           */
+
+
+/* Define the FileX API events.  */
+
+#define FX_TRACE_DIRECTORY_ATTRIBUTES_READ              220             /* I1 = media ptr, I2 = directory name, I3 = attributes                     */
+#define FX_TRACE_DIRECTORY_ATTRIBUTES_SET               221             /* I1 = media ptr, I2 = directory name, I3 = attributes                     */
+#define FX_TRACE_DIRECTORY_CREATE                       222             /* I1 = media ptr, I2 = directory name                                      */
+#define FX_TRACE_DIRECTORY_DEFAULT_GET                  223             /* I1 = media ptr, I2 = return path name                                    */
+#define FX_TRACE_DIRECTORY_DEFAULT_SET                  224             /* I1 = media ptr, I2 = new path name                                       */
+#define FX_TRACE_DIRECTORY_DELETE                       225             /* I1 = media ptr, I2 = directory name                                      */
+#define FX_TRACE_DIRECTORY_FIRST_ENTRY_FIND             226             /* I1 = media ptr, I2 = directory name                                      */
+#define FX_TRACE_DIRECTORY_FIRST_FULL_ENTRY_FIND        227             /* I1 = media ptr, I2 = directory name                                      */
+#define FX_TRACE_DIRECTORY_INFORMATION_GET              228             /* I1 = media ptr, I2 = directory name                                      */
+#define FX_TRACE_DIRECTORY_LOCAL_PATH_CLEAR             229             /* I1 = media ptr                                                           */
+#define FX_TRACE_DIRECTORY_LOCAL_PATH_GET               230             /* I1 = media ptr, I2 = return path name                                    */
+#define FX_TRACE_DIRECTORY_LOCAL_PATH_RESTORE           231             /* I1 = media ptr, I2 = local path ptr                                      */
+#define FX_TRACE_DIRECTORY_LOCAL_PATH_SET               232             /* I1 = media ptr, I2 = local path ptr, I3 = new path name                  */
+#define FX_TRACE_DIRECTORY_LONG_NAME_GET                233             /* I1 = media ptr, I2 = short file name, I3 = long file name                */
+#define FX_TRACE_DIRECTORY_NAME_TEST                    234             /* I1 = media ptr, I2 = directory name                                      */
+#define FX_TRACE_DIRECTORY_NEXT_ENTRY_FIND              235             /* I1 = media ptr, I2 = directory name                                      */
+#define FX_TRACE_DIRECTORY_NEXT_FULL_ENTRY_FIND         236             /* I1 = media ptr, I2 = directory name                                      */
+#define FX_TRACE_DIRECTORY_RENAME                       237             /* I1 = media ptr, I2 = old directory name, I3 = new directory name         */
+#define FX_TRACE_DIRECTORY_SHORT_NAME_GET               238             /* I1 = media ptr, I2 = long file name, I3 = short file name                */
+#define FX_TRACE_FILE_ALLOCATE                          239             /* I1 = file ptr, I2 = size I3 = previous size, I4 = new size               */
+#define FX_TRACE_FILE_ATTRIBUTES_READ                   240             /* I1 = media ptr, I2 = file name, I3 = attributes                          */
+#define FX_TRACE_FILE_ATTRIBUTES_SET                    241             /* I1 = media ptr, I2 = file name, I3 = attributes                          */
+#define FX_TRACE_FILE_BEST_EFFORT_ALLOCATE              242             /* I1 = file ptr, I2 = size, I3 = actual_size_allocated                     */
+#define FX_TRACE_FILE_CLOSE                             243             /* I1 = file ptr, I3 = file size                                            */
+#define FX_TRACE_FILE_CREATE                            244             /* I1 = media ptr, I2 = file name                                           */
+#define FX_TRACE_FILE_DATE_TIME_SET                     245             /* I1 = media ptr, I2 = file name, I3 = year, I4 = month                    */
+#define FX_TRACE_FILE_DELETE                            246             /* I1 = media ptr, I2 = file name                                           */
+#define FX_TRACE_FILE_OPEN                              247             /* I1 = media ptr, I2 = file ptr, I3 = file name, I4 = open type            */
+#define FX_TRACE_FILE_READ                              248             /* I1 = file ptr, I2 = buffer ptr, I3 = request size I4 = actual size       */
+#define FX_TRACE_FILE_RELATIVE_SEEK                     249             /* I1 = file ptr, I2 = byte offset, I3 = seek from, I4 = previous offset    */
+#define FX_TRACE_FILE_RENAME                            250             /* I1 = media ptr, I2 = old file name, I3 = new file name                   */
+#define FX_TRACE_FILE_SEEK                              251             /* I1 = file ptr, I2 = byte offset, I3 = previous offset                    */
+#define FX_TRACE_FILE_TRUNCATE                          252             /* I1 = file ptr, I2 = size, I3 = previous size, I4 = new size              */
+#define FX_TRACE_FILE_TRUNCATE_RELEASE                  253             /* I1 = file ptr, I2 = size, I3 = previous size, I4 = new size              */
+#define FX_TRACE_FILE_WRITE                             254             /* I1 = file ptr, I2 = buffer ptr, I3 = size, I4 = bytes written            */
+#define FX_TRACE_MEDIA_ABORT                            255             /* I1 = media ptr                                                           */
+#define FX_TRACE_MEDIA_CACHE_INVALIDATE                 256             /* I1 = media ptr                                                           */
+#define FX_TRACE_MEDIA_CHECK                            257             /* I1 = media ptr, I2 = scratch memory, I3 = scratch memory size, I4 =errors*/
+#define FX_TRACE_MEDIA_CLOSE                            258             /* I1 = media ptr                                                           */
+#define FX_TRACE_MEDIA_FLUSH                            259             /* I1 = media ptr                                                           */
+#define FX_TRACE_MEDIA_FORMAT                           260             /* I1 = media ptr, I2 = root entries, I3 = sectors, I4 = sectors per cluster*/
+#define FX_TRACE_MEDIA_OPEN                             261             /* I1 = media ptr, I2 = media driver, I3 = memory ptr, I4 = memory size     */
+#define FX_TRACE_MEDIA_READ                             262             /* I1 = media ptr, I2 = logical sector, I3 = buffer ptr, I4 = bytes read    */
+#define FX_TRACE_MEDIA_SPACE_AVAILABLE                  263             /* I1 = media ptr, I2 = available bytes ptr, I3 = available clusters        */
+#define FX_TRACE_MEDIA_VOLUME_GET                       264             /* I1 = media ptr, I2 = volume name, I3 = volume source                     */
+#define FX_TRACE_MEDIA_VOLUME_SET                       265             /* I1 = media ptr, I2 = volume name                                         */
+#define FX_TRACE_MEDIA_WRITE                            266             /* I1 = media ptr, I2 = logical_sector, I3 = buffer_ptr, I4 = byte written  */
+#define FX_TRACE_SYSTEM_DATE_GET                        267             /* I1 = year, I2 = month, I3 = day                                          */
+#define FX_TRACE_SYSTEM_DATE_SET                        268             /* I1 = year, I2 = month, I3 = day                                          */
+#define FX_TRACE_SYSTEM_INITIALIZE                      269             /* None                                                                     */
+#define FX_TRACE_SYSTEM_TIME_GET                        270             /* I1 = hour, I2 = minute, I3 = second                                      */
+#define FX_TRACE_SYSTEM_TIME_SET                        271             /* I1 = hour, I2 = minute, I3 = second                                      */
+#define FX_TRACE_UNICODE_DIRECTORY_CREATE               272             /* I1 = media ptr, I2 = source unicode, I3 = source length, I4 = short_name */
+#define FX_TRACE_UNICODE_DIRECTORY_RENAME               273             /* I1 = media ptr, I2 = source unicode, I3 = source length, I4 = new_name   */
+#define FX_TRACE_UNICODE_FILE_CREATE                    274             /* I1 = media ptr, I2 = source unicode, I3 = source length, I4 = short name */
+#define FX_TRACE_UNICODE_FILE_RENAME                    275             /* I1 = media ptr, I2 = source unicode, I3 = source length, I4 = new name   */
+#define FX_TRACE_UNICODE_LENGTH_GET                     276             /* I1 = unicode name, I2 = length                                           */
+#define FX_TRACE_UNICODE_NAME_GET                       277             /* I1 = media ptr, I2 = source short name, I3 = unicode name, I4 = length   */
+#define FX_TRACE_UNICODE_SHORT_NAME_GET                 278             /* I1 = media ptr, I2 = source unicode name, I3 = length, I4 =  short name  */
+#endif
+
+
+/* Map the trace macros to internal FileX versions so we can get interrupt protection.  */
+
+#ifdef FX_SOURCE_CODE
+
+#define FX_TRACE_OBJECT_REGISTER(t, p, n, a, b)         _fx_trace_object_register(t, (VOID *)p, (CHAR *)n, (ULONG)a, (ULONG)b);
+#define FX_TRACE_OBJECT_UNREGISTER(o)                   _fx_trace_object_unregister((VOID *)o);
+#define FX_TRACE_IN_LINE_INSERT(i, a, b, c, d, f, g, h) _fx_trace_event_insert((ULONG)i, (ULONG)a, (ULONG)b, (ULONG)c, (ULONG)d, (ULONG)f, g, h);
+#define FX_TRACE_EVENT_UPDATE(e, t, i, a, b, c, d)      _fx_trace_event_update((TX_TRACE_BUFFER_ENTRY *)e, (ULONG)t, (ULONG)i, (ULONG)a, (ULONG)b, (ULONG)c, (ULONG)d);
+
+
+/* Define FileX trace prototypes.  */
+
+VOID _fx_trace_object_register(UCHAR object_type, VOID *object_ptr, CHAR *object_name, ULONG parameter_1, ULONG parameter_2);
+VOID _fx_trace_object_unregister(VOID *object_ptr);
+VOID _fx_trace_event_insert(ULONG event_id, ULONG info_field_1, ULONG info_field_2, ULONG info_field_3, ULONG info_field_4, ULONG filter, TX_TRACE_BUFFER_ENTRY **current_event, ULONG *current_timestamp);
+VOID _fx_trace_event_update(TX_TRACE_BUFFER_ENTRY *event, ULONG timestamp, ULONG event_id, ULONG info_field_1, ULONG info_field_2, ULONG info_field_3, ULONG info_field_4);
+
+#endif
+
+#else
+#define FX_TRACE_OBJECT_REGISTER(t, p, n, a, b)
+#define FX_TRACE_OBJECT_UNREGISTER(o)
+#define FX_TRACE_IN_LINE_INSERT(i, a, b, c, d, f, g, h)
+#define FX_TRACE_EVENT_UPDATE(e, t, i, a, b, c, d)
+#endif
+
+
+/* Define basic constants for FileX.  */
+
+#define FX_MEDIA_ID                            ((ULONG)0x4D454449)
+#define FX_MEDIA_CLOSED_ID                     ((ULONG)0x4D454443)
+#define FX_MEDIA_ABORTED_ID                    ((ULONG)0x4D454441)
+
+#define FX_FILE_ID                             ((ULONG)0x46494C45)
+#define FX_FILE_CLOSED_ID                      ((ULONG)0x46494C43)
+#define FX_FILE_ABORTED_ID                     ((ULONG)0x46494C41)
+
+
+/* The maximum path includes the entire path and the file name.  */
+
+#ifndef FX_MAXIMUM_PATH
+#define FX_MAXIMUM_PATH                        256
+#endif
+
+
+/* Define directory entry name sizes. Directory entries are found in the
+   root directory and in directory files (sub-directories). Each directory
+   entry has a short file name which is a fixed maximum of 13 characters and
+   and optional 255 character long file name.  */
+
+#ifndef FX_MAX_LONG_NAME_LEN
+#define FX_MAX_LONG_NAME_LEN                   256      /* Minimum value is 13, Maximum value is 256.  */
+#endif
+
+#define FX_MAX_SHORT_NAME_LEN                  13       /* Only allowed value is 13.  */
+
+#ifndef FX_MAX_LAST_NAME_LEN
+#define FX_MAX_LAST_NAME_LEN                   256      /* Should be as large or larger than FX_MAX_LONG_NAME_LEN.  */
+#endif
+
+
+/* Define constants related to the logical sector cache. These constants represent the maximum
+   number of logical sectors that can be cached. The actual number of logical sectors in the
+   cache is determined by the amount of memory supplied to fx_media_open for the FX_MEDIA
+   instance.  */
+
+#ifndef FX_MAX_SECTOR_CACHE
+#define FX_MAX_SECTOR_CACHE                    256      /* Maximum size of logical sector cache,
+                                                           minimum value of 2 all other values must
+                                                           be a power of 2.  */
+#endif
+
+/* Define the mask for the hash index into the logical sector cache.  If the logical sector cache
+   determined by the amount of memory supplied by the application to fx_media_open is larger than
+   FX_SECTOR_CACHE_HASH_ENABLE (usually 16) and can satisfy FX_MAX_SECTOR_CACHE sectors, the cache
+   is divided into 4 entry pieces (FX_SECTOR_CACHE_DEPTH) that are indexed by the formula:
+
+        index =  (cluster & media_ptr -> fx_media_sector_cache_hash_mask) * FX_SECTOR_CACHE_LEVELS
+
+   The FX_SECTOR_CACHE_DEPTH define must not be changed unless the logical sector read/write
+   code is also changed.  */
+
+#define FX_SECTOR_CACHE_HASH_ENABLE            16
+#define FX_SECTOR_CACHE_DEPTH                  4
+
+#ifndef FX_FAT_MAP_SIZE
+#define FX_FAT_MAP_SIZE                        128  /* Minimum 1, maximum any. This represents how many 32-bit words used for the written FAT sector bit map. */
+#endif
+
+#ifndef FX_MAX_FAT_CACHE
+#define FX_MAX_FAT_CACHE                       16   /* Minimum value is 8, all values must be a power of 2.  */
+#endif
+
+
+/* Define the size of fault tolerant cache, which is used when freeing FAT chain. */
+
+#ifndef FX_FAULT_TOLERANT_CACHE_SIZE
+#define FX_FAULT_TOLERANT_CACHE_SIZE           1024
+#endif /* FX_FAULT_TOLERANT_CACHE_SIZE */
+
+
+/* Define the mask for the hash index into the FAT table.  The FAT cache is divided into 4 entry pieces
+   that are indexed by the formula:
+
+            index =  (cluster & FX_FAT_CACHE_HASH_MASK) * FX_FAT_CACHE_LEVELS
+
+   The FX_FAT_CACHE_DEPTH define must not be changed unless the FAT entry read/write code is also changed.  */
+
+#define FX_FAT_CACHE_DEPTH                     4
+#define FX_FAT_CACHE_HASH_MASK                 ((FX_MAX_FAT_CACHE / FX_FAT_CACHE_DEPTH) - 1)
+
+
+/* FileX API input parameters and general constants.  */
+
+#define FX_TRUE                                1
+#define FX_FALSE                               0
+#define FX_NULL                                0
+#define FX_OPEN_FOR_READ                       0
+#define FX_OPEN_FOR_WRITE                      1
+#define FX_OPEN_FOR_READ_FAST                  2
+
+#define FX_12_BIT_FAT_SIZE                     4086
+#define FX_16_BIT_FAT_SIZE                     65525
+#define FX_MAX_12BIT_CLUST                     0x0FF0
+#define FX_SIGN_EXTEND                         0xF000
+#define FX_12BIT_SIZE                          3    /* 2 FAT entries per 3 bytes  */
+
+#define FX_FAT_ENTRY_START                     2
+#define FX_DIR_ENTRY_SIZE                      32
+#define FX_DIR_NAME_SIZE                       8
+#define FX_DIR_EXT_SIZE                        3
+#define FX_DIR_RESERVED                        8
+#define FX_DIR_ENTRY_FREE                      0xE5
+#define FX_DIR_ENTRY_DONE                      0x00
+#define FX_READ_ONLY                           0x01
+#define FX_HIDDEN                              0x02
+#define FX_SYSTEM                              0x04
+#define FX_VOLUME                              0x08
+#define FX_DIRECTORY                           0x10
+#define FX_ARCHIVE                             0x20
+#define FX_LONG_NAME                           (FX_READ_ONLY | FX_HIDDEN | FX_SYSTEM | FX_VOLUME)
+#define FX_LONG_NAME_ENTRY_LEN                 13
+
+
+/* Define FAT FAT entry values.  */
+
+#define FX_FREE_CLUSTER                        0x0000
+#define FX_NOT_USED                            0x0001
+#define FX_RESERVED_1                          0xFFF0
+#define FX_RESERVED_2                          0xFFF6
+#define FX_BAD_CLUSTER                         0xFFF7
+#define FX_LAST_CLUSTER_1                      0xFFF8
+#define FX_LAST_CLUSTER_2                      0xFFFF
+
+#define FX_RESERVED_1_32                       0x0FFFFFF0
+#define FX_RESERVED_2_32                       0x0FFFFFF6
+#define FX_BAD_CLUSTER_32                      0x0FFFFFF7
+#define FX_LAST_CLUSTER_1_32                   0x0FFFFFF8
+#define FX_LAST_CLUSTER_2_32                   0x0FFFFFFF
+
+
+/* Define time/date FAT constants.  */
+
+#define FX_YEAR_SHIFT                          9
+#define FX_MONTH_SHIFT                         5
+#define FX_HOUR_SHIFT                          11
+#define FX_MINUTE_SHIFT                        5
+#define FX_YEAR_MASK                           0x7F
+#define FX_MONTH_MASK                          0x0F
+#define FX_DAY_MASK                            0x1F
+#define FX_HOUR_MASK                           0x1F
+#define FX_MINUTE_MASK                         0x3F
+#define FX_SECOND_MASK                         0x1F
+#define FX_BASE_YEAR                           1980
+#define FX_MAXIMUM_YEAR                        2107
+#define FX_MAXIMUM_MONTH                       12
+#define FX_MAXIMUM_HOUR                        23
+#define FX_MAXIMUM_MINUTE                      59
+#define FX_MAXIMUM_SECOND                      59
+#define FX_INITIAL_DATE                        0x4A21   /* 01-01-2017 */
+#define FX_INITIAL_TIME                        0x0000   /* 12:00 am   */
+
+/* FileX API return values.  */
+
+#define FX_SUCCESS                             0x00
+#define FX_BOOT_ERROR                          0x01
+#define FX_MEDIA_INVALID                       0x02
+#define FX_FAT_READ_ERROR                      0x03
+#define FX_NOT_FOUND                           0x04
+#define FX_NOT_A_FILE                          0x05
+#define FX_ACCESS_ERROR                        0x06
+#define FX_NOT_OPEN                            0x07
+#define FX_FILE_CORRUPT                        0x08
+#define FX_END_OF_FILE                         0x09
+#define FX_NO_MORE_SPACE                       0x0A
+#define FX_ALREADY_CREATED                     0x0B
+#define FX_INVALID_NAME                        0x0C
+#define FX_INVALID_PATH                        0x0D
+#define FX_NOT_DIRECTORY                       0x0E
+#define FX_NO_MORE_ENTRIES                     0x0F
+#define FX_DIR_NOT_EMPTY                       0x10
+#define FX_MEDIA_NOT_OPEN                      0x11
+#define FX_INVALID_YEAR                        0x12
+#define FX_INVALID_MONTH                       0x13
+#define FX_INVALID_DAY                         0x14
+#define FX_INVALID_HOUR                        0x15
+#define FX_INVALID_MINUTE                      0x16
+#define FX_INVALID_SECOND                      0x17
+#define FX_PTR_ERROR                           0x18
+#define FX_INVALID_ATTR                        0x19
+#define FX_CALLER_ERROR                        0x20
+#define FX_BUFFER_ERROR                        0x21
+#define FX_NOT_IMPLEMENTED                     0x22
+#define FX_WRITE_PROTECT                       0x23
+#define FX_INVALID_OPTION                      0x24
+#define FX_SECTOR_INVALID                      0x89
+#define FX_IO_ERROR                            0x90
+#define FX_NOT_ENOUGH_MEMORY                   0x91
+#define FX_ERROR_FIXED                         0x92
+#define FX_ERROR_NOT_FIXED                     0x93
+#define FX_NOT_AVAILABLE                       0x94
+#define FX_INVALID_CHECKSUM                    0x95
+#define FX_READ_CONTINUE                       0x96
+#define FX_INVALID_STATE                       0x97
+
+
+/* FileX driver interface constants.  */
+
+#define FX_DRIVER_READ                         0
+#define FX_DRIVER_WRITE                        1
+#define FX_DRIVER_FLUSH                        2
+#define FX_DRIVER_ABORT                        3
+#define FX_DRIVER_INIT                         4
+#define FX_DRIVER_BOOT_READ                    5
+#define FX_DRIVER_RELEASE_SECTORS              6
+#define FX_DRIVER_BOOT_WRITE                   7
+#define FX_DRIVER_UNINIT                       8
+
+
+/* Define relative seek constants.  */
+
+#define FX_SEEK_BEGIN                          0
+#define FX_SEEK_END                            1
+#define FX_SEEK_FORWARD                        2
+#define FX_SEEK_BACK                           3
+
+
+/* Define types for logical sectors. This information is passed to the driver
+   as additional information.  */
+
+#define FX_UNKNOWN_SECTOR                      0
+#define FX_BOOT_SECTOR                         1
+#define FX_FAT_SECTOR                          2
+#define FX_DIRECTORY_SECTOR                    3
+#define FX_DATA_SECTOR                         4
+
+
+/* Define media diagnostic constants.  */
+
+#define FX_FAT_CHAIN_ERROR                     0x01
+#define FX_DIRECTORY_ERROR                     0x02
+#define FX_LOST_CLUSTER_ERROR                  0x04
+#define FX_FILE_SIZE_ERROR                     0x08
+
+
+/* Define boot record offset constants.  */
+
+#define FX_JUMP_INSTR                          0x000
+#define FX_OEM_NAME                            0x003
+#define FX_BYTES_SECTOR                        0x00B
+#define FX_SECTORS_CLUSTER                     0x00D
+#define FX_RESERVED_SECTORS                    0x00E
+#define FX_NUMBER_OF_FATS                      0x010
+#define FX_ROOT_DIR_ENTRIES                    0x011
+#define FX_SECTORS                             0x013
+#define FX_MEDIA_TYPE                          0x015
+#define FX_SECTORS_PER_FAT                     0x016
+#define FX_SECTORS_PER_TRK                     0x018
+#define FX_HEADS                               0x01A
+#define FX_HIDDEN_SECTORS                      0x01C
+#define FX_HUGE_SECTORS                        0x020
+#define FX_DRIVE_NUMBER                        0x024
+#define FX_RESERVED                            0x025
+#define FX_BOOT_SIG                            0x026
+#define FX_BOOT_SIG_32                         0x042
+#define FX_VOLUME_ID                           0x027
+#define FX_VOLUME_ID_32                        0x043
+#define FX_VOLUME_LABEL                        0x02B
+#define FX_VOLUME_LABEL_32                     0x047
+#define FX_FILE_SYSTEM_TYPE                    0x036
+#define FX_SIG_OFFSET                          0x1FE
+#define FX_ROOT_CLUSTER_32                     0x02C
+#define FX_SECTORS_PER_FAT_32                  0x024
+#define FX_SIG_BYTE_1                          0x55
+#define FX_SIG_BYTE_2                          0xAA
+
+
+/* If not-defined, default port-specific processing extensions to white space.  */
+
+#ifndef FX_FILE_OPEN_EXTENSION
+#define FX_FILE_OPEN_EXTENSION
+#endif
+
+#ifndef FX_DIRECTORY_ENTRY_READ_EXTENSION
+#define FX_DIRECTORY_ENTRY_READ_EXTENSION
+#endif
+
+#ifndef FX_DIRECTORY_ENTRY_WRITE_EXTENSION
+#define FX_DIRECTORY_ENTRY_WRITE_EXTENSION
+#endif
+
+#ifndef FX_UTILITY_FAT_ENTRY_READ_EXTENSION
+#define FX_UTILITY_FAT_ENTRY_READ_EXTENSION
+#endif
+
+#ifndef FX_UTILITY_FAT_ENTRY_WRITE_EXTENSION
+#define FX_UTILITY_FAT_ENTRY_WRITE_EXTENSION
+#endif
+
+#ifndef FX_UTILITY_LOGICAL_SECTOR_FLUSH_EXTENSION
+#define FX_UTILITY_LOGICAL_SECTOR_FLUSH_EXTENSION
+#endif
+
+#ifndef FX_UTILITY_LOGICAL_SECTOR_READ_EXTENSION
+#define FX_UTILITY_LOGICAL_SECTOR_READ_EXTENSION
+#endif
+
+#ifndef FX_UTILITY_LOGICAL_SECTOR_READ_EXTENSION_1
+#define FX_UTILITY_LOGICAL_SECTOR_READ_EXTENSION_1
+#endif
+
+#ifndef FX_UTILITY_LOGICAL_SECTOR_WRITE_EXTENSION
+#define FX_UTILITY_LOGICAL_SECTOR_WRITE_EXTENSION
+#endif
+
+
+#ifdef FX_ENABLE_EXFAT
+
+
+/* Define exFAT specific constants.  */
+
+#define FX_EF_MUST_BE_ZERO                     11       /* Must be Zero Area                  053 bytes */
+#define FX_EF_PARTITION_OFFSET                 64       /* Partition Offset                   008 bytes */
+#define FX_EF_VOLUME_LENGTH                    72       /* Number of sectors on the Partition 008 bytes */
+#define FX_EF_FAT_OFFSET                       80       /* Number of sectors before exFAT     004 bytes */
+#define FX_EF_FAT_LENGTH                       84       /* Each FAT length in Sectors         004 bytes */
+#define FX_EF_CLUSTER_HEAP_OFFSET              88       /* Number of Sectors Before Cluster   004 bytes
+                                                           Heap */
+#define FX_EF_CLUSTER_COUNT                    92       /* Number of Clusters in the Cluster  004 bytes
+                                                           Heap */
+#define FX_EF_FIRST_CLUSTER_OF_ROOT_DIR        96       /* Cluster index of the First         004 bytes
+                                                           Cluster of the ROOT Directory                */
+#define FX_EF_VOLUME_SERIAL_NUMBER             100      /* Volume Serial Number               004 bytes */
+#define FX_EF_FILE_SYSTEM_REVISION             104      /* File System  Revision              002 bytes */
+#define FX_EF_VOLUME_FLAGS                     106      /* Status of exFAT structures         002 bytes */
+#define FX_EF_BYTE_PER_SECTOR_SHIFT            108      /* log2(N),where N is the Number of   001 byte
+                                                           Bytes per Sector */
+#define FX_EF_SECTOR_PER_CLUSTER_SHIFT         109      /* log2(N),where N is the Number of   001 byte
+                                                           Sectors per Cluster */
+#define FX_EF_NUMBER_OF_FATS                   110      /* Number of FATs                     001 byte */
+#define FX_EF_DRIVE_SELECT                     111      /* Extended INT13h driver number      001 byte */
+#define FX_EF_PERCENT_IN_USE                   112      /* Percentage of Allocated Clusters   001 byte */
+#define FX_EF_RESERVED                         113      /* Reserved                           007 bytes */
+#define FX_EF_BOOT_CODE                        120      /* Boot code area                     390 bytes */
+
+#define FX_RESERVED_1_exFAT                    0xFFFFFFF8
+#define FX_RESERVED_2_exFAT                    0xFFFFFFFE
+#define FX_BAD_CLUSTER_exFAT                   0xFFFFFFF7
+#define FX_LAST_CLUSTER_exFAT                  0xFFFFFFFF
+
+#ifndef FX_MAX_EX_FAT_NAME_LEN
+#define FX_MAX_EX_FAT_NAME_LEN                 255      /* Only allowed value is 255 */
+#endif
+
+#ifndef BITS_PER_BYTE
+#define BITS_PER_BYTE                          8
+#endif
+#define BITS_PER_BYTE_SHIFT                    3
+
+
+#define FX_EXFAT_MAX_DIRECTORY_SIZE            (256 * 1024 * 1024)  /* 256 MB */
+#define FX_EXFAT_SIZE_OF_FAT_ELEMENT_SHIFT     2
+
+#define FX_EXFAT_BIT_MAP_NUM_OF_CACHED_SECTORS 1
+
+#define FX_EXFAT_BITMAP_CLUSTER_FREE           0
+#define FX_EXFAT_BITMAP_CLUSTER_OCCUPIED       1
+
+#ifndef FX_EXFAT_MAX_CACHE_SIZE
+#define FX_EXFAT_MAX_CACHE_SIZE                512
+#endif
+#define FX_EXFAT_BITMAP_CACHE_SIZE             FX_EXFAT_MAX_CACHE_SIZE
+
+/* exFAT System Area Layout */
+
+#define FX_EXFAT_FAT_MAIN_SYSTEM_AREA_SIZE     12
+
+#define FX_EXFAT_FAT_MAIN_BOOT_SECTOR_OFFSET   0
+#define FX_EXFAT_FAT_BACKUP_BOOT_SECTOR_OFFSET FX_EXFAT_FAT_MAIN_SYSTEM_AREA_SIZE
+
+#define FX_EXFAT_FAT_EXT_BOOT_SECTOR_OFFSET    1
+#define FX_EXFAT_FAT_OEM_PARAM_OFFSET          9
+#define FX_EXFAT_FAT_CHECK_SUM_OFFSET          11
+
+#define FX_EXFAT_FAT_NUM_OF_SYSTEM_AREAS       2
+
+
+/* Define exFAT format parameters.  */
+
+#define  EXFAT_MIN_NUM_OF_RESERVED_SECTORS     1
+#define  EXFAT_BOOT_REGION_SIZE                24
+#define  EXFAT_FAT_BITS                        32
+#define  EXFAT_FAT_FILE_SYS_REVISION           0x100
+#define  EXFAT_FAT_VOLUME_FLAG                 0x000
+#define  EXFAT_FAT_NUM_OF_FATS                 0x001
+#define  EXFAT_FAT_DRIVE_SELECT                0x080
+#define  EXFAT_FAT_VOLUME_NAME_FIELD_SIZE      11
+#define  EXFAT_BIT_MAP_FIRST_TABLE             0
+#define  EXFAT_LAST_CLUSTER_MASK               0xFFFFFFFF
+#define  EXFAT_DEFAULT_BOUNDARY_UNIT           128
+#define  EXFAT_NUM_OF_DIR_ENTRIES              2
+
+
+#define DIVIDE_TO_CEILING(a, b)                (((a) + (b) - 1) / (b))
+#define ALIGN_UP(a, b)                         (DIVIDE_TO_CEILING(a, b) * (b))
+
+#define FX_FAT12                               0x01
+#define FX_FAT16                               0x04
+#define FX_BIGDOS                              0x06
+#define FX_exFAT                               0x07
+#define FX_FAT32                               0x0B
+#define FX_NO_FAT                              0xFF
+
+#endif /* FX_ENABLE_EXFAT */
+
+
+/* Define the control block definitions for all system objects.  */
+
+
+/* Define a single entry in the FAT cache.  The FAT cache is used to reduce the
+   number of times the actual FAT sectors need to be accessed, thereby improving
+   performance.  */
+
+typedef struct FX_FAT_CACHE_ENTRY_STRUCT
+{
+    ULONG fx_fat_cache_entry_cluster;
+    ULONG fx_fat_cache_entry_value;
+    ULONG fx_fat_cache_entry_dirty;
+} FX_FAT_CACHE_ENTRY;
+
+
+/* Define the directory entry structure that contains information about a specific
+   directory entry.  */
+
+typedef struct FX_DIR_ENTRY_STRUCT
+{
+
+    CHAR   *fx_dir_entry_name;
+    CHAR    fx_dir_entry_short_name[FX_MAX_SHORT_NAME_LEN];                 /* Short file name, if LFN is present                */
+    UINT    fx_dir_entry_long_name_present;                                 /* 0 (default) => LFN not present; 1 => LFN present  */
+    UINT    fx_dir_entry_long_name_shorted;                                 /* LFN too large, file name was made shorter         */
+    UCHAR   fx_dir_entry_attributes;                                        /* Directory entry attributes                        */
+    UCHAR   fx_dir_entry_reserved;                                          /* NT reserved, write 0 at create, otherwise ignore  */
+    UCHAR   fx_dir_entry_created_time_ms;                                   /* Create time in milliseconds, always write 0       */
+    UINT    fx_dir_entry_created_time;                                      /* Created time                                      */
+    UINT    fx_dir_entry_created_date;                                      /* Created date                                      */
+    UINT    fx_dir_entry_last_accessed_date;                                /* Last accessed date                                */
+    UINT    fx_dir_entry_time;                                              /* Modified time                                     */
+    UINT    fx_dir_entry_date;                                              /* Modified cluster                                  */
+    ULONG   fx_dir_entry_cluster;                                           /* File/directory's starting cluster                 */
+    ULONG64 fx_dir_entry_file_size;                                         /* Size of the file in bytes                         */
+    ULONG64 fx_dir_entry_log_sector;                                        /* Logical sector of this directory entry            */
+    ULONG   fx_dir_entry_byte_offset;                                       /* Offset in logical sector of this directory entry  */
+    ULONG   fx_dir_entry_number;                                            /* Index into the directory                          */
+    ULONG   fx_dir_entry_last_search_cluster;                               /* Last cluster searched                             */
+    ULONG   fx_dir_entry_last_search_relative_cluster;                      /* Last relative cluster searched                    */
+    ULONG64 fx_dir_entry_last_search_log_sector;                            /* Last logical sector searched                      */
+    ULONG   fx_dir_entry_last_search_byte_offset;                           /* Last offset in logical sector searched            */
+    ULONG64 fx_dir_entry_next_log_sector;
+
+#ifdef FX_ENABLE_EXFAT
+    /* for exFAT */
+    CHAR    fx_dir_entry_dont_use_fat;                                      /* 0 bit - for current, 1st bit - for parent         */
+    UCHAR   fx_dir_entry_type;
+    ULONG64 fx_dir_entry_available_file_size;
+    ULONG   fx_dir_entry_secondary_count;
+#endif /* FX_ENABLE_EXFAT */
+} FX_DIR_ENTRY;
+
+typedef FX_DIR_ENTRY  *FX_DIR_ENTRY_PTR;
+
+
+/* Define the path data structure.  This structure will contain
+   the current path and the information for performing directory
+   entry operations.  */
+
+typedef struct FX_PATH_STRUCT
+{
+    /* Define the path information.  */
+    FX_DIR_ENTRY fx_path_directory;
+    CHAR         fx_path_string[FX_MAXIMUM_PATH];
+    CHAR         fx_path_name_buffer[FX_MAX_LONG_NAME_LEN];
+    ULONG        fx_path_current_entry;
+} FX_PATH;
+
+typedef FX_PATH FX_LOCAL_PATH;
+
+
+/* Define the cache control data structure.  There are FX_MAX_SECTOR_CACHE
+   of these structures defined inside the FX_MEDIA structure.  Each entry
+   maintains a cache representation of a media sector.  */
+
+typedef struct FX_CACHED_SECTOR_STRUCT
+{
+
+    /* Define the buffer pointer associated with this cache entry.  */
+    UCHAR               *fx_cached_sector_memory_buffer;
+
+    /* Define the sector number that is cached.  */
+    ULONG64             fx_cached_sector;
+
+    /* Define the flag that indicates whether or not the cached sector
+       has been modified and needs to be written to the media.  */
+    UCHAR               fx_cached_sector_buffer_dirty;
+
+    /* Define the valid flag that indicates whether or not this entry is
+       still valid.  */
+    UCHAR               fx_cached_sector_valid;
+
+    /* Define the sector type, which indicates what type of sector is present.  */
+    UCHAR               fx_cached_sector_type;
+
+    /* Define a reserved byte, reserved for future use.  */
+    UCHAR               fx_cached_sector_reserved;
+
+    /* Define the next cached sector pointer.  This is used to implement
+       the "last used" algorithm when looking for cache entry to swap out to
+       the physical media.  */
+    struct FX_CACHED_SECTOR_STRUCT
+                        *fx_cached_sector_next_used;
+
+} FX_CACHED_SECTOR;
+
+
+/* Determine if the media control block has an extension defined. If not, 
+   define the extension to whitespace.  */
+
+#ifndef FX_MEDIA_MODULE_EXTENSION
+#define FX_MEDIA_MODULE_EXTENSION
+#endif
+
+
+/* Define the media control block.  All information about each open
+   media device are maintained in by the FX_MEDIA data type.  */
+
+typedef struct FX_MEDIA_STRUCT
+{
+
+    /* Define the media ID used for error checking.  */
+    ULONG               fx_media_id;
+
+    /* Define the media's name.  */
+    CHAR                *fx_media_name;
+
+    /* Remember the memory buffer area.  */
+    UCHAR               *fx_media_memory_buffer;
+    ULONG               fx_media_memory_size;
+
+#ifdef FX_DISABLE_CACHE
+    ULONG64             fx_media_memory_buffer_sector;
+#else
+
+    /* Define the flag that indicates whether the logical cache utilizes
+       a hash function or is a linear search. If set, the logical cache
+       is accessed via a hash function on the requested sector.  */
+    UINT                fx_media_sector_cache_hashed;
+
+    /* Define the number of sectors that can actually be cached based on the
+       user supplied buffer at media open time.  */
+    ULONG               fx_media_sector_cache_size;
+
+    /* Define the end of the cache area.  This is used to determine
+       if the I/O is for the internal memory of the media.  */
+    UCHAR               *fx_media_sector_cache_end;
+
+    /* Define the list head of the cached sector entries.  This
+       pointer points to the most recently used cache sector.  */
+    struct FX_CACHED_SECTOR_STRUCT
+                        *fx_media_sector_cache_list_ptr;
+
+    /* Define the bit map that represents the hashed cache sectors that are
+       valid. This bit map will help optimize the invalidation of the hashed
+       sector cache.  */
+    ULONG               fx_media_sector_cache_hashed_sector_valid;
+
+    /* Define the outstanding dirty sector counter. This is used to optimize
+       the searching of sectors to flush to the media.  */
+    ULONG               fx_media_sector_cache_dirty_count;
+#endif /* FX_DISABLE_CACHE */
+
+    /* Define the basic information about the associated media.  */
+    UINT                fx_media_bytes_per_sector;
+    UINT                fx_media_sectors_per_track;
+    UINT                fx_media_heads;
+
+    ULONG64             fx_media_total_sectors;
+    ULONG               fx_media_total_clusters;
+
+#ifdef FX_ENABLE_EXFAT
+    /* Define exFAT media information.  */
+    ULONG               fx_media_exfat_volume_serial_number;
+    UINT                fx_media_exfat_file_system_revision;
+    UINT                fx_media_exfat_volume_flag;
+    USHORT              fx_media_exfat_drive_select;
+    USHORT              fx_media_exfat_percent_in_use;
+    UINT                fx_media_exfat_bytes_per_sector_shift;
+    UINT                fx_media_exfat_sector_per_clusters_shift;
+
+    /* exFAT: Bitmap cache */
+    /* Pointer to Bitmap cache */
+    UCHAR               fx_media_exfat_bitmap_cache[FX_EXFAT_BITMAP_CACHE_SIZE];
+
+    /* Define beginning sector of Bitmap table.  */
+    ULONG               fx_media_exfat_bitmap_start_sector;
+
+    /* Define the cache size in sectors. Used for flash operation.  */
+    ULONG               fx_media_exfat_bitmap_cache_size_in_sectors;
+
+    /* Define the number of first cached cluster.  */
+    ULONG               fx_media_exfat_bitmap_cache_start_cluster;
+
+    /* Define the number of last cached cluster.  */
+    ULONG               fx_media_exfat_bitmap_cache_end_cluster;
+
+    /* Define how many clusters mapped in one sector.  */
+    UINT                fx_media_exfat_bitmap_clusters_per_sector_shift;
+
+    /* Define is Bitmap table was changed or not.  */
+    UINT                fx_media_exfat_bitmap_cache_dirty;
+#endif /* FX_ENABLE_EXFAT */
+
+    UINT                fx_media_reserved_sectors;
+    UINT                fx_media_root_sector_start;
+    UINT                fx_media_root_sectors;
+    UINT                fx_media_data_sector_start;
+    UINT                fx_media_sectors_per_cluster;
+    UINT                fx_media_sectors_per_FAT;
+    UINT                fx_media_number_of_FATs;
+    UINT                fx_media_12_bit_FAT;
+    UINT                fx_media_32_bit_FAT;
+    ULONG               fx_media_FAT32_additional_info_sector;
+    UINT                fx_media_FAT32_additional_info_last_available;
+#ifdef FX_DRIVER_USE_64BIT_LBA
+    ULONG64             fx_media_hidden_sectors;
+#else
+    ULONG               fx_media_hidden_sectors;
+#endif
+    ULONG               fx_media_root_cluster_32;
+    UINT                fx_media_root_directory_entries;
+    ULONG               fx_media_available_clusters;
+    ULONG               fx_media_cluster_search_start;
+
+    /* Define the information pertinent to the I/O driver interface.  */
+
+    VOID                *fx_media_driver_info;
+    UINT                fx_media_driver_request;
+    UINT                fx_media_driver_status;
+    UCHAR               *fx_media_driver_buffer;
+#ifdef FX_DRIVER_USE_64BIT_LBA
+    ULONG64             fx_media_driver_logical_sector;
+#else
+    ULONG               fx_media_driver_logical_sector;
+#endif
+    ULONG               fx_media_driver_sectors;
+    ULONG               fx_media_driver_physical_sector;
+    UINT                fx_media_driver_physical_track;
+    UINT                fx_media_driver_physical_head;
+    UINT                fx_media_driver_write_protect;      /* The driver sets this to FX_TRUE when media is write protected.  */
+    UINT                fx_media_driver_free_sector_update; /* The driver sets this to FX_TRUE when it needs to know freed clusters.  */
+    UINT                fx_media_driver_system_write;
+    UINT                fx_media_driver_data_sector_read;
+    UINT                fx_media_driver_sector_type;
+
+    /* Define the driver entry point.  */
+    VOID                (*fx_media_driver_entry)(struct FX_MEDIA_STRUCT *);
+
+    /* Define notify function called when media is open. */
+    VOID                (*fx_media_open_notify)(struct FX_MEDIA_STRUCT *);
+
+    /* Define notify function called when media is closed. */
+    VOID                (*fx_media_close_notify)(struct FX_MEDIA_STRUCT *);
+
+    /* Define the head pointer for the open files of this media.  */
+    struct FX_FILE_STRUCT
+                        *fx_media_opened_file_list;
+
+    /* Define the counter for keeping track of how many open files are
+       present.  */
+    ULONG               fx_media_opened_file_count;
+
+    /* Define the next and previous link pointers for the open media list.  */
+    struct FX_MEDIA_STRUCT
+                        *fx_media_opened_next,
+                        *fx_media_opened_previous;
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Define various statistics for this media instance. This information
+       should be useful in performance tuning and optimizing the application.  */
+
+    ULONG               fx_media_directory_attributes_reads;
+    ULONG               fx_media_directory_attributes_sets;
+    ULONG               fx_media_directory_creates;
+    ULONG               fx_media_directory_default_gets;
+    ULONG               fx_media_directory_default_sets;
+    ULONG               fx_media_directory_deletes;
+    ULONG               fx_media_directory_first_entry_finds;
+    ULONG               fx_media_directory_first_full_entry_finds;
+    ULONG               fx_media_directory_information_gets;
+    ULONG               fx_media_directory_local_path_clears;
+    ULONG               fx_media_directory_local_path_gets;
+    ULONG               fx_media_directory_local_path_restores;
+    ULONG               fx_media_directory_local_path_sets;
+    ULONG               fx_media_directory_name_tests;
+    ULONG               fx_media_directory_next_entry_finds;
+    ULONG               fx_media_directory_next_full_entry_finds;
+    ULONG               fx_media_directory_renames;
+    ULONG               fx_media_file_allocates;
+    ULONG               fx_media_file_attributes_reads;
+    ULONG               fx_media_file_attributes_sets;
+    ULONG               fx_media_file_best_effort_allocates;
+    ULONG               fx_media_file_closes;
+    ULONG               fx_media_file_creates;
+    ULONG               fx_media_file_deletes;
+    ULONG               fx_media_file_opens;
+    ULONG               fx_media_file_reads;
+    ULONG               fx_media_file_relative_seeks;
+    ULONG               fx_media_file_renames;
+    ULONG               fx_media_file_seeks;
+    ULONG               fx_media_file_truncates;
+    ULONG               fx_media_file_truncate_releases;
+    ULONG               fx_media_file_writes;
+    ULONG               fx_media_aborts;
+    ULONG               fx_media_flushes;
+    ULONG               fx_media_reads;
+    ULONG               fx_media_writes;
+    ULONG               fx_media_directory_entry_reads;
+    ULONG               fx_media_directory_entry_writes;
+    ULONG               fx_media_directory_searches;
+    ULONG               fx_media_directory_free_searches;
+    ULONG               fx_media_fat_entry_reads;
+    ULONG               fx_media_fat_entry_writes;
+    ULONG               fx_media_fat_entry_cache_read_hits;
+    ULONG               fx_media_fat_entry_cache_read_misses;
+    ULONG               fx_media_fat_entry_cache_write_hits;
+    ULONG               fx_media_fat_entry_cache_write_misses;
+    ULONG               fx_media_fat_cache_flushes;
+    ULONG               fx_media_fat_sector_reads;
+    ULONG               fx_media_fat_sector_writes;
+    ULONG               fx_media_logical_sector_reads;
+    ULONG               fx_media_logical_sector_writes;
+    ULONG               fx_media_logical_sector_cache_read_hits;
+    ULONG               fx_media_logical_sector_cache_read_misses;
+    ULONG               fx_media_driver_read_requests;
+    ULONG               fx_media_driver_write_requests;
+    ULONG               fx_media_driver_boot_read_requests;
+    ULONG               fx_media_driver_boot_write_requests;
+    ULONG               fx_media_driver_release_sectors_requests;
+    ULONG               fx_media_driver_flush_requests;
+#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
+    ULONG               fx_media_directory_search_cache_hits;
+#endif
+#endif
+
+    /* Define the media's protection object, which is a ThreadX mutex.
+       Only one thread is allowed to access any media or associated files
+       at a time.  If FX_SINGLE_THREAD is defined, the FileX services are
+       going to be called from only one thread, hence the protection is
+       not needed.  */
+#ifndef FX_SINGLE_THREAD
+    TX_MUTEX            fx_media_protect;
+#endif
+
+#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
+
+    /* Define the information used to remember the last directory entry found through
+       searching or walking the directory via directory entry next. This information
+       will be used to eliminate multiple searches for the same directory entry if
+       the accesses are done sequentially.  */
+    UINT                fx_media_last_found_directory_valid;
+    FX_DIR_ENTRY        fx_media_last_found_directory;
+    FX_DIR_ENTRY        fx_media_last_found_entry;
+    CHAR                fx_media_last_found_file_name[FX_MAX_LONG_NAME_LEN];
+    CHAR                fx_media_last_found_name[FX_MAX_LAST_NAME_LEN];
+#endif
+
+    /* Define the current directory information for the media.  */
+    FX_PATH             fx_media_default_path;
+
+    /* Define FAT entry cache and the variable used to index the cache.  */
+    FX_FAT_CACHE_ENTRY  fx_media_fat_cache[FX_MAX_FAT_CACHE];
+
+    /* Define the FAT secondary update map.  This will be used on flush and
+       close to update sectors of any secondary FATs in the media.  */
+    UCHAR               fx_media_fat_secondary_update_map[FX_FAT_MAP_SIZE];
+
+    /* Define a variable for the application's use.  */
+    ALIGN_TYPE          fx_media_reserved_for_user;
+
+    /* Define an area to allocate long file names so that local storage on
+       calling thread's stack is not used for long file names.  This helps
+       reduce the amount of thread stack space needed when using FileX.  */
+    CHAR                fx_media_name_buffer[4*FX_MAX_LONG_NAME_LEN];
+
+#ifdef FX_RENAME_PATH_INHERIT
+
+    /* Define the file and directory rename buffer that will be used to prepend
+       paths when necessary to the target file name.  */
+    CHAR                fx_media_rename_buffer[FX_MAXIMUM_PATH];
+#endif
+
+#ifndef FX_DISABLE_CACHE
+    /* Define the sector cache control structures for this media.  */
+    struct FX_CACHED_SECTOR_STRUCT
+                        fx_media_sector_cache[FX_MAX_SECTOR_CACHE];
+
+    /* Define the sector cache hash mask so that the hash algorithm can be used with
+       any power of 2 number of cache sectors.  */
+    ULONG               fx_media_sector_cache_hash_mask;
+#endif /* FX_DISABLE_CACHE */
+
+    /* Define a variable to disable burst cache. This is used by the underlying
+       driver.  */
+    ULONG               fx_media_disable_burst_cache;
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+
+    /* Fault tolerant information */
+    /* Indicate whether fault tolerant is enabled. */
+
+    UCHAR               fx_media_fault_tolerant_enabled;
+
+    /* State of fault tolerant operation. */
+    UCHAR               fx_media_fault_tolerant_state;
+
+    /* Transaction recursive count. */
+    USHORT              fx_media_fault_tolerant_transaction_count;
+
+    /* Start cluster of log. */
+    ULONG               fx_media_fault_tolerant_start_cluster;
+
+    /* Count of consecutive clusters of log. */
+    ULONG               fx_media_fault_tolerant_clusters;
+
+    /* Count of total logs. */
+    ULONG               fx_media_fault_tolerant_total_logs;
+
+    /* Pointer to the memory buffer area used for fault tolerant operations.  */
+    UCHAR              *fx_media_fault_tolerant_memory_buffer;
+
+    /* Size of memory buffer area used for fault tolerant operations. */
+    ULONG               fx_media_fault_tolerant_memory_buffer_size;
+
+    /* Size of log file. */
+    ULONG               fx_media_fault_tolerant_file_size;
+
+    /* Memory space used during the release of FAT list. */
+    ULONG               fx_media_fault_tolerant_cache[FX_FAULT_TOLERANT_CACHE_SIZE >> 2];
+
+    /* Sector number of cached FAT entries. */
+    ULONG               fx_media_fault_tolerant_cached_FAT_sector;
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Reserved value of FAT table. */
+    ULONG               fx_media_fat_reserved;
+
+    /* Last value of FAT table. */
+    ULONG               fx_media_fat_last;
+
+    /* Media geometry structure */
+    UCHAR               fx_media_FAT_type;
+
+    /* Define the module port extension in the media control block. This 
+       is typically defined to whitespace in fx_port.h.  */
+    FX_MEDIA_MODULE_EXTENSION
+
+} FX_MEDIA;
+
+typedef FX_MEDIA *      FX_MEDIA_PTR;
+
+
+/* Determine if the file control block has an extension defined. If not, 
+   define the extension to whitespace.  */
+
+#ifndef FX_FILE_MODULE_EXTENSION
+#define FX_FILE_MODULE_EXTENSION
+#endif
+
+
+/* Define the FileX file control block.  All information about open
+   files are found in this data type.  */
+
+typedef struct FX_FILE_STRUCT
+{
+
+    /* Define the file ID used for error checking.  */
+    ULONG               fx_file_id;
+
+    /* Define the file's name.  */
+    CHAR                *fx_file_name;
+
+    /* Define the open mode request.  */
+    ULONG               fx_file_open_mode;
+
+    /* Define the file modified field.  */
+    UCHAR               fx_file_modified;
+
+    /* Define the data storage parameters.  */
+    ULONG               fx_file_total_clusters;
+    ULONG               fx_file_first_physical_cluster;
+    ULONG               fx_file_consecutive_cluster;
+    ULONG               fx_file_last_physical_cluster;
+    ULONG               fx_file_current_physical_cluster;
+    ULONG64             fx_file_current_logical_sector;
+    ULONG               fx_file_current_logical_offset;
+    ULONG               fx_file_current_relative_cluster;
+    ULONG               fx_file_current_relative_sector;
+    ULONG64             fx_file_current_file_offset;
+    ULONG64             fx_file_current_file_size;
+    ULONG64             fx_file_current_available_size;
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    ULONG64             fx_file_maximum_size_used;
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Remember the media that is associated with this file. */
+    FX_MEDIA            *fx_file_media_ptr;
+
+    /* Define the pointers necessary to maintain the open file on
+       the list of open files.  */
+    struct FX_FILE_STRUCT
+                        *fx_file_opened_next,
+                        *fx_file_opened_previous;
+
+    /* Define the complete directory entry structure.  */
+    FX_DIR_ENTRY        fx_file_dir_entry;
+    CHAR                fx_file_name_buffer[FX_MAX_LONG_NAME_LEN];
+
+    /* Define a variable for the application's use */
+    ULONG               fx_file_disable_burst_cache;
+
+    /* Define a notify function called when file is written to. */
+    VOID               (*fx_file_write_notify)(struct FX_FILE_STRUCT *);
+
+    /* Define the module port extension in the file control block. This 
+       is typically defined to whitespace in fx_port.h.  */
+    FX_FILE_MODULE_EXTENSION
+
+} FX_FILE;
+
+typedef FX_FILE  *FX_FILE_PTR;
+
+
+/* Define the FileX API mappings based on the error checking
+   selected by the user.  Note: this section is only applicable to
+   application source code, hence the conditional that turns off this
+   stuff when the include file is processed by the FileX source. */
+
+#ifndef FX_SOURCE_CODE
+
+#ifdef FX_DISABLE_ONE_LINE_FUNCTION
+#define fx_file_seek(f, b)                    fx_file_extended_seek(f, (ULONG64)b)
+#define fx_file_allocate(f, s)                fx_file_extended_allocate(f, (ULONG64)s);
+#define fx_file_truncate(f, s)                fx_file_extended_truncate(f, (ULONG64)s);
+#define fx_file_relative_seek(f, b, sf)       fx_file_extended_relative_seek(f, (ULONG64)b, sf);
+#define fx_file_truncate_release(f, s)        fx_file_extended_truncate_release(f, (ULONG64)s);
+#endif /* FX_DISABLE_ONE_LINE_FUNCTION */
+
+/* Determine if error checking is desired.  If so, map API functions
+   to the appropriate error checking front-ends.  Otherwise, map API
+   functions to the core functions that actually perform the work.
+   Note: error checking is enabled by default.  */
+
+#ifdef FX_DISABLE_ERROR_CHECKING
+
+/* Services without error checking.  */
+
+#define fx_directory_attributes_read          _fx_directory_attributes_read
+#define fx_directory_attributes_set           _fx_directory_attributes_set
+#define fx_directory_create                   _fx_directory_create
+#define fx_directory_default_get              _fx_directory_default_get
+#define fx_directory_default_get_copy         _fx_directory_default_get_copy
+#define fx_directory_default_set              _fx_directory_default_set
+#define fx_directory_delete                   _fx_directory_delete
+#define fx_directory_first_entry_find         _fx_directory_first_entry_find
+#define fx_directory_first_full_entry_find    _fx_directory_first_full_entry_find
+#define fx_directory_information_get          _fx_directory_information_get
+#define fx_directory_local_path_clear         _fx_directory_local_path_clear
+#define fx_directory_local_path_get           _fx_directory_local_path_get
+#define fx_directory_local_path_get_copy      _fx_directory_local_path_get_copy
+#define fx_directory_local_path_restore       _fx_directory_local_path_restore
+#define fx_directory_local_path_set           _fx_directory_local_path_set
+#define fx_directory_long_name_get            _fx_directory_long_name_get
+#define fx_directory_long_name_get_extended   _fx_directory_long_name_get_extended
+#define fx_directory_name_test                _fx_directory_name_test
+#define fx_directory_next_entry_find          _fx_directory_next_entry_find
+#define fx_directory_next_full_entry_find     _fx_directory_next_full_entry_find
+#define fx_directory_rename                   _fx_directory_rename
+#define fx_directory_short_name_get           _fx_directory_short_name_get
+#define fx_directory_short_name_get_extended  _fx_directory_short_name_get_extended
+
+#ifndef FX_DISABLE_ONE_LINE_FUNCTION
+#define fx_file_allocate                      _fx_file_allocate
+#endif /* FX_DISABLE_ONE_LINE_FUNCTION */
+#define fx_file_attributes_read               _fx_file_attributes_read
+#define fx_file_attributes_set                _fx_file_attributes_set
+#define fx_file_best_effort_allocate          _fx_file_best_effort_allocate
+#define fx_file_close                         _fx_file_close
+#define fx_file_create                        _fx_file_create
+#define fx_file_date_time_set                 _fx_file_date_time_set
+#define fx_file_delete                        _fx_file_delete
+#define fx_file_open                          _fx_file_open
+#define fx_file_read                          _fx_file_read
+#ifndef FX_DISABLE_ONE_LINE_FUNCTION
+#define fx_file_relative_seek                 _fx_file_relative_seek
+#endif /* FX_DISABLE_ONE_LINE_FUNCTION */
+#define fx_file_rename                        _fx_file_rename
+#ifndef FX_DISABLE_ONE_LINE_FUNCTION
+#define fx_file_seek                          _fx_file_seek
+#define fx_file_truncate                      _fx_file_truncate
+#define fx_file_truncate_release              _fx_file_truncate_release
+#endif /* FX_DISABLE_ONE_LINE_FUNCTION */
+#define fx_file_write                         _fx_file_write
+#define fx_file_write_notify_set              _fx_file_write_notify_set
+#define fx_file_extended_allocate             _fx_file_extended_allocate
+#define fx_file_extended_best_effort_allocate _fx_file_extended_best_effort_allocate
+#define fx_file_extended_relative_seek        _fx_file_extended_relative_seek
+#define fx_file_extended_seek                 _fx_file_extended_seek
+#define fx_file_extended_truncate             _fx_file_extended_truncate
+#define fx_file_extended_truncate_release     _fx_file_extended_truncate_release
+
+#define fx_media_abort                        _fx_media_abort
+#define fx_media_cache_invalidate             _fx_media_cache_invalidate
+#define fx_media_check                        _fx_media_check
+#define fx_media_close                        _fx_media_close
+#define fx_media_flush                        _fx_media_flush
+#define fx_media_format                       _fx_media_format
+#ifdef FX_ENABLE_EXFAT
+#define fx_media_exFAT_format                 _fx_media_exFAT_format
+#endif /* FX_ENABLE_EXFAT */
+#define fx_media_open                         _fx_media_open
+#define fx_media_read                         _fx_media_read
+#define fx_media_space_available              _fx_media_space_available
+#define fx_media_volume_get                   _fx_media_volume_get
+#define fx_media_volume_get_extended          _fx_media_volume_get_extended
+#define fx_media_volume_set                   _fx_media_volume_set
+#define fx_media_write                        _fx_media_write
+#define fx_media_open_notify_set              _fx_media_open_notify_set
+#define fx_media_close_notify_set             _fx_media_close_notify_set
+#define fx_media_extended_space_available     _fx_media_extended_space_available
+
+#define fx_unicode_directory_create           _fx_unicode_directory_create
+#define fx_unicode_directory_rename           _fx_unicode_directory_rename
+#define fx_unicode_file_create                _fx_unicode_file_create
+#define fx_unicode_file_rename                _fx_unicode_file_rename
+#define fx_unicode_length_get                 _fx_unicode_length_get
+#define fx_unicode_length_get_extended        _fx_unicode_length_get_extended
+#define fx_unicode_name_get                   _fx_unicode_name_get
+#define fx_unicode_name_get_extended          _fx_unicode_name_get_extended
+#define fx_unicode_short_name_get             _fx_unicode_short_name_get
+#define fx_unicode_short_name_get_extended    _fx_unicode_short_name_get_extended
+
+#define fx_system_date_get                    _fx_system_date_get
+#define fx_system_date_set                    _fx_system_date_set
+#define fx_system_time_get                    _fx_system_time_get
+#define fx_system_time_set                    _fx_system_time_set
+#define fx_system_initialize                  _fx_system_initialize
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+#define fx_fault_tolerant_enable              _fx_fault_tolerant_enable
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+#else
+
+/* Services with error checking.  */
+
+#define fx_directory_attributes_read          _fxe_directory_attributes_read
+#define fx_directory_attributes_set           _fxe_directory_attributes_set
+#define fx_directory_create                   _fxe_directory_create
+#define fx_directory_default_get              _fxe_directory_default_get
+#define fx_directory_default_get_copy         _fxe_directory_default_get_copy
+#define fx_directory_default_set              _fxe_directory_default_set
+#define fx_directory_delete                   _fxe_directory_delete
+#define fx_directory_first_entry_find         _fxe_directory_first_entry_find
+#define fx_directory_first_full_entry_find    _fxe_directory_first_full_entry_find
+#define fx_directory_information_get          _fxe_directory_information_get
+#define fx_directory_local_path_clear         _fxe_directory_local_path_clear
+#define fx_directory_local_path_get           _fxe_directory_local_path_get
+#define fx_directory_local_path_get_copy      _fxe_directory_local_path_get_copy
+#define fx_directory_local_path_restore       _fxe_directory_local_path_restore
+#define fx_directory_local_path_set(m, l, n)  _fxe_directory_local_path_set(m, l, n, sizeof(FX_LOCAL_PATH))
+#define fx_directory_long_name_get            _fxe_directory_long_name_get
+#define fx_directory_long_name_get_extended   _fxe_directory_long_name_get_extended
+#define fx_directory_name_test                _fxe_directory_name_test
+#define fx_directory_next_entry_find          _fxe_directory_next_entry_find
+#define fx_directory_next_full_entry_find     _fxe_directory_next_full_entry_find
+#define fx_directory_rename                   _fxe_directory_rename
+#define fx_directory_short_name_get           _fxe_directory_short_name_get
+#define fx_directory_short_name_get_extended  _fxe_directory_short_name_get_extended
+
+#ifndef FX_DISABLE_ONE_LINE_FUNCTION
+#define fx_file_allocate                      _fxe_file_allocate
+#endif  /* FX_DISABLE_ONE_LINE_FUNCTION */
+#define fx_file_attributes_read               _fxe_file_attributes_read
+#define fx_file_attributes_set                _fxe_file_attributes_set
+#define fx_file_best_effort_allocate          _fxe_file_best_effort_allocate
+#define fx_file_close                         _fxe_file_close
+#define fx_file_create                        _fxe_file_create
+#define fx_file_date_time_set                 _fxe_file_date_time_set
+#define fx_file_delete                        _fxe_file_delete
+#define fx_file_open(m, f, n, t)              _fxe_file_open(m, f, n, t, sizeof(FX_FILE))
+#define fx_file_read                          _fxe_file_read
+#ifndef FX_DISABLE_ONE_LINE_FUNCTION
+#define fx_file_relative_seek                 _fxe_file_relative_seek
+#endif /* FX_DISABLE_ONE_LINE_FUNCTION */
+#define fx_file_rename                        _fxe_file_rename
+#ifndef FX_DISABLE_ONE_LINE_FUNCTION
+#define fx_file_seek                          _fxe_file_seek
+#define fx_file_truncate                      _fxe_file_truncate
+#define fx_file_truncate_release              _fxe_file_truncate_release
+#endif /* FX_DISABLE_ONE_LINE_FUNCTION */
+#define fx_file_write                         _fxe_file_write
+#define fx_file_write_notify_set              _fxe_file_write_notify_set
+#define fx_file_extended_allocate             _fxe_file_extended_allocate
+#define fx_file_extended_best_effort_allocate _fxe_file_extended_best_effort_allocate
+#define fx_file_extended_relative_seek        _fxe_file_extended_relative_seek
+#define fx_file_extended_seek                 _fxe_file_extended_seek
+#define fx_file_extended_truncate             _fxe_file_extended_truncate
+#define fx_file_extended_truncate_release     _fxe_file_extended_truncate_release
+
+#define fx_media_abort                        _fxe_media_abort
+#define fx_media_cache_invalidate             _fxe_media_cache_invalidate
+#define fx_media_check                        _fxe_media_check
+#define fx_media_close                        _fxe_media_close
+#define fx_media_flush                        _fxe_media_flush
+#define fx_media_format                       _fxe_media_format
+#ifdef FX_ENABLE_EXFAT
+#define fx_media_exFAT_format                 _fxe_media_exFAT_format
+#endif /* FX_ENABLE_EXFAT */
+#define fx_media_open(m, n, d, i, p, s)       _fxe_media_open(m, n, d, i, p, s, sizeof(FX_MEDIA))
+#define fx_media_read                         _fxe_media_read
+#define fx_media_space_available              _fxe_media_space_available
+#define fx_media_volume_get                   _fxe_media_volume_get
+#define fx_media_volume_get_extended          _fxe_media_volume_get_extended
+#define fx_media_volume_set                   _fxe_media_volume_set
+#define fx_media_write                        _fxe_media_write
+#define fx_media_open_notify_set              _fxe_media_open_notify_set
+#define fx_media_close_notify_set             _fxe_media_close_notify_set
+#define fx_media_extended_space_available     _fxe_media_extended_space_available
+
+#define fx_unicode_directory_create           _fxe_unicode_directory_create
+#define fx_unicode_directory_rename           _fxe_unicode_directory_rename
+#define fx_unicode_file_create                _fxe_unicode_file_create
+#define fx_unicode_file_rename                _fxe_unicode_file_rename
+#define fx_unicode_length_get                 _fx_unicode_length_get
+#define fx_unicode_length_get_extended        _fx_unicode_length_get_extended
+#define fx_unicode_name_get                   _fxe_unicode_name_get
+#define fx_unicode_name_get_extended          _fxe_unicode_name_get_extended
+#define fx_unicode_short_name_get             _fxe_unicode_short_name_get
+#define fx_unicode_short_name_get_extended    _fxe_unicode_short_name_get_extended
+
+#define fx_system_date_get                    _fxe_system_date_get
+#define fx_system_date_set                    _fxe_system_date_set
+#define fx_system_time_get                    _fxe_system_time_get
+#define fx_system_time_set                    _fxe_system_time_set
+#define fx_system_initialize                  _fx_system_initialize
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+#define fx_fault_tolerant_enable              _fxe_fault_tolerant_enable
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+#endif
+
+/* Define the function prototypes of the FileX API.  */
+
+UINT fx_directory_attributes_read(FX_MEDIA *media_ptr, CHAR *directory_name, UINT *attributes_ptr);
+UINT fx_directory_attributes_set(FX_MEDIA *media_ptr, CHAR *directory_name, UINT attributes);
+UINT fx_directory_create(FX_MEDIA *media_ptr, CHAR *directory_name);
+UINT fx_directory_default_get(FX_MEDIA *media_ptr, CHAR **return_path_name);
+UINT fx_directory_default_get_copy(FX_MEDIA *media_ptr, CHAR *return_path_name_buffer, UINT return_path_name_buffer_size);
+UINT fx_directory_default_set(FX_MEDIA *media_ptr, CHAR *new_path_name);
+UINT fx_directory_delete(FX_MEDIA *media_ptr, CHAR *directory_name);
+UINT fx_directory_first_entry_find(FX_MEDIA *media_ptr, CHAR *directory_name);
+UINT fx_directory_first_full_entry_find(FX_MEDIA *media_ptr, CHAR *directory_name, UINT *attributes,
+                                        ULONG *size, UINT *year, UINT *month, UINT *day, UINT *hour, UINT *minute, UINT *second);
+UINT fx_directory_information_get(FX_MEDIA *media_ptr, CHAR *directory_name, UINT *attributes, ULONG *size,
+                                  UINT *year, UINT *month, UINT *day, UINT *hour, UINT *minute, UINT *second);
+UINT fx_directory_local_path_clear(FX_MEDIA *media_ptr);
+UINT fx_directory_local_path_get(FX_MEDIA *media_ptr, CHAR **return_path_name);
+UINT fx_directory_local_path_get_copy(FX_MEDIA *media_ptr, CHAR *return_path_name_buffer, UINT return_path_name_buffer_size);
+UINT fx_directory_local_path_restore(FX_MEDIA *media_ptr, FX_LOCAL_PATH *local_path_ptr);
+#ifdef FX_DISABLE_ERROR_CHECKING
+UINT _fx_directory_local_path_set(FX_MEDIA *media_ptr, FX_LOCAL_PATH *local_path_ptr, CHAR *new_path_name);
+#else
+UINT _fxe_directory_local_path_set(FX_MEDIA *media_ptr, FX_LOCAL_PATH *local_path_ptr, CHAR *new_path_name, UINT local_path_control_block_size);
+#endif
+UINT fx_directory_long_name_get(FX_MEDIA *media_ptr, CHAR *short_file_name, CHAR *long_file_name);
+UINT fx_directory_long_name_get_extended(FX_MEDIA* media_ptr, CHAR* short_file_name, CHAR* long_file_name, UINT long_file_name_buffer_length);
+UINT fx_directory_name_test(FX_MEDIA *media_ptr, CHAR *directory_name);
+UINT fx_directory_next_entry_find(FX_MEDIA *media_ptr, CHAR *directory_name);
+UINT fx_directory_next_full_entry_find(FX_MEDIA *media_ptr, CHAR *directory_name, UINT *attributes,
+                                       ULONG *size, UINT *year, UINT *month, UINT *day, UINT *hour, UINT *minute, UINT *second);
+UINT fx_directory_rename(FX_MEDIA *media_ptr, CHAR *old_directory_name, CHAR *new_directory_name);
+UINT fx_directory_short_name_get(FX_MEDIA *media_ptr, CHAR *long_file_name, CHAR *short_file_name);
+UINT fx_directory_short_name_get_extended(FX_MEDIA* media_ptr, CHAR* long_file_name, CHAR* short_file_name, UINT short_file_name_length);
+
+#ifndef FX_DISABLE_ONE_LINE_FUNCTION
+UINT fx_file_allocate(FX_FILE *file_ptr, ULONG size);
+#endif /* FX_DISABLE_ONE_LINE_FUNCTION*/
+UINT fx_file_attributes_read(FX_MEDIA *media_ptr, CHAR *file_name, UINT *attributes_ptr);
+UINT fx_file_attributes_set(FX_MEDIA *media_ptr, CHAR *file_name, UINT attributes);
+UINT fx_file_best_effort_allocate(FX_FILE *file_ptr, ULONG size, ULONG *actual_size_allocated);
+UINT fx_file_close(FX_FILE *file_ptr);
+UINT fx_file_create(FX_MEDIA *media_ptr, CHAR *file_name);
+UINT fx_file_date_time_set(FX_MEDIA *media_ptr, CHAR *file_name,
+                           UINT year, UINT month, UINT day, UINT hour, UINT minute, UINT second);
+UINT fx_file_delete(FX_MEDIA *media_ptr, CHAR *file_name);
+#ifdef FX_DISABLE_ERROR_CHECKING
+UINT _fx_file_open(FX_MEDIA *media_ptr, FX_FILE *file_ptr, CHAR *file_name,
+                   UINT open_type);
+#else
+UINT _fxe_file_open(FX_MEDIA *media_ptr, FX_FILE *file_ptr, CHAR *file_name,
+                    UINT open_type, UINT file_control_block_size);
+#endif
+UINT fx_file_read(FX_FILE *file_ptr, VOID *buffer_ptr, ULONG request_size, ULONG *actual_size);
+#ifndef FX_DISABLE_ONE_LINE_FUNCTION
+UINT fx_file_relative_seek(FX_FILE *file_ptr, ULONG byte_offset, UINT seek_from);
+#endif /* FX_DISABLE_ONE_LINE_FUNCTION */
+UINT fx_file_rename(FX_MEDIA *media_ptr, CHAR *old_file_name, CHAR *new_file_name);
+#ifndef FX_DISABLE_ONE_LINE_FUNCTION
+UINT fx_file_seek(FX_FILE *file_ptr, ULONG byte_offset);
+UINT fx_file_truncate(FX_FILE *file_ptr, ULONG size);
+UINT fx_file_truncate_release(FX_FILE *file_ptr, ULONG size);
+#endif /* FX_DISABLE_ONE_LINE_FUNCTION */
+UINT fx_file_write(FX_FILE *file_ptr, VOID *buffer_ptr, ULONG size);
+UINT fx_file_write_notify_set(FX_FILE *file_ptr, VOID (*file_write_notify)(FX_FILE *));
+UINT fx_file_extended_allocate(FX_FILE *file_ptr, ULONG64 size);
+UINT fx_file_extended_best_effort_allocate(FX_FILE *file_ptr, ULONG64 size, ULONG64 *actual_size_allocated);
+UINT fx_file_extended_relative_seek(FX_FILE *file_ptr, ULONG64 byte_offset, UINT seek_from);
+UINT fx_file_extended_seek(FX_FILE *file_ptr, ULONG64 byte_offset);
+UINT fx_file_extended_truncate(FX_FILE *file_ptr, ULONG64 size);
+UINT fx_file_extended_truncate_release(FX_FILE *file_ptr, ULONG64 size);
+
+UINT fx_media_abort(FX_MEDIA *media_ptr);
+UINT fx_media_cache_invalidate(FX_MEDIA *media_ptr);
+UINT fx_media_check(FX_MEDIA *media_ptr, UCHAR *scratch_memory_ptr, ULONG scratch_memory_size, ULONG error_correction_option, ULONG *errors_detected);
+UINT fx_media_close(FX_MEDIA *media_ptr);
+UINT fx_media_flush(FX_MEDIA *media_ptr);
+UINT fx_media_format(FX_MEDIA *media_ptr, VOID (*driver)(FX_MEDIA *media), VOID *driver_info_ptr, UCHAR *memory_ptr, UINT memory_size,
+                     CHAR *volume_name, UINT number_of_fats, UINT directory_entries, UINT hidden_sectors,
+                     ULONG total_sectors, UINT bytes_per_sector, UINT sectors_per_cluster,
+                     UINT heads, UINT sectors_per_track);
+#ifdef FX_ENABLE_EXFAT
+UINT fx_media_exFAT_format(FX_MEDIA *media_ptr, VOID (*driver)(FX_MEDIA *media), VOID *driver_info_ptr, UCHAR *memory_ptr, UINT memory_size,
+                           CHAR *volume_name, UINT number_of_fats, ULONG64 hidden_sectors, ULONG64 total_sectors,
+                           UINT bytes_per_sector, UINT sectors_per_cluster, UINT volume_serial_number, UINT boundary_unit);
+#endif /* FX_ENABLE_EXFAT */
+#ifdef FX_DISABLE_ERROR_CHECKING
+UINT _fx_media_open(FX_MEDIA *media_ptr, CHAR *media_name,
+                    VOID (*media_driver)(FX_MEDIA *), VOID *driver_info_ptr,
+                    VOID *memory_ptr, ULONG memory_size);
+#else
+UINT _fxe_media_open(FX_MEDIA *media_ptr, CHAR *media_name,
+                     VOID (*media_driver)(FX_MEDIA *), VOID *driver_info_ptr,
+                     VOID *memory_ptr, ULONG memory_size, UINT media_control_block_size);
+#endif
+UINT fx_media_read(FX_MEDIA *media_ptr, ULONG logical_sector, VOID *buffer_ptr);
+UINT fx_media_space_available(FX_MEDIA *media_ptr, ULONG *available_bytes_ptr);
+UINT fx_media_volume_get(FX_MEDIA *media_ptr, CHAR *volume_name, UINT volume_source);
+UINT fx_media_volume_get_extended(FX_MEDIA *media_ptr, CHAR *volume_name, UINT volume_name_buffer_length, UINT volume_source);
+UINT fx_media_volume_set(FX_MEDIA *media_ptr, CHAR *volume_name);
+UINT fx_media_write(FX_MEDIA *media_ptr, ULONG logical_sector, VOID *buffer_ptr);
+UINT fx_media_open_notify_set(FX_MEDIA *media_ptr, VOID (*media_open_notify)(FX_MEDIA *));
+UINT fx_media_close_notify_set(FX_MEDIA *media_ptr, VOID (*media_close_notify)(FX_MEDIA *));
+UINT fx_media_extended_space_available(FX_MEDIA *media_ptr, ULONG64 *available_bytes_ptr);
+
+UINT fx_system_date_get(UINT *year, UINT *month, UINT *day);
+UINT fx_system_date_set(UINT year, UINT month, UINT day);
+VOID fx_system_initialize(VOID);
+UINT fx_system_time_get(UINT *hour, UINT *minute, UINT *second);
+UINT fx_system_time_set(UINT hour, UINT minute, UINT second);
+
+UINT fx_unicode_directory_create(FX_MEDIA *media_ptr,
+                                 UCHAR *source_unicode_name, ULONG source_unicode_length,
+                                 CHAR *short_name);
+UINT fx_unicode_directory_rename(FX_MEDIA *media_ptr,
+                                 UCHAR *old_unicode_name, ULONG old_unicode_length,
+                                 UCHAR *new_unicode_name, ULONG new_unicode_length,
+                                 CHAR *new_short_name);
+UINT fx_unicode_file_create(FX_MEDIA *media_ptr,
+                            UCHAR *source_unicode_name, ULONG source_unicode_length,
+                            CHAR *short_name);
+UINT  fx_unicode_file_rename(FX_MEDIA *media_ptr, UCHAR *old_unicode_name, ULONG old_unicode_length,
+                             UCHAR *new_unicode_name, ULONG new_unicode_length, CHAR *new_short_name);
+ULONG fx_unicode_length_get(UCHAR *unicode_name);
+ULONG fx_unicode_length_get_extended(UCHAR *unicode_name, UINT buffer_length);
+UINT  fx_unicode_name_get(FX_MEDIA *media_ptr, CHAR *source_short_name,
+                          UCHAR *destination_unicode_name, ULONG *destination_unicode_length);
+UINT  fx_unicode_name_get_extended(FX_MEDIA *media_ptr, CHAR *source_short_name,
+                          UCHAR *destination_unicode_name, ULONG *destination_unicode_length, ULONG unicode_name_buffer_length);
+UINT  fx_unicode_short_name_get(FX_MEDIA *media_ptr,
+                                UCHAR *source_unicode_name, ULONG source_unicode_length,
+                                CHAR *destination_short_name);
+UINT  fx_unicode_short_name_get_extended(FX_MEDIA *media_ptr,
+                                UCHAR *source_unicode_name, ULONG source_unicode_length,
+                                CHAR *destination_short_name, ULONG short_name_buffer_length);
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+UINT fx_fault_tolerant_enable(FX_MEDIA *media_ptr, VOID *memory_buffer, UINT memory_size);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+
+/* Define prototype for utility services commonly used by FileX I/O Drivers.  This eliminates the
+   need to include internal FileX component files in I/O drivers.  */
+
+UINT    _fx_utility_16_unsigned_read(UCHAR *source_ptr);
+VOID    _fx_utility_16_unsigned_write(UCHAR *dest_ptr, UINT value);
+ULONG   _fx_utility_32_unsigned_read(UCHAR *source_ptr);
+VOID    _fx_utility_32_unsigned_write(UCHAR *dest_ptr, ULONG value);
+ULONG64 _fx_utility_64_unsigned_read(UCHAR *source_ptr);
+VOID    _fx_utility_64_unsigned_write(UCHAR *dest_ptr, ULONG64 value);
+VOID    _fx_utility_memory_copy(UCHAR *source_ptr, UCHAR *dest_ptr, ULONG size);
+VOID    _fx_utility_memory_set(UCHAR *dest_ptr, UCHAR value, ULONG size);
+
+#endif
+
+/* Determine if a C++ compiler is being used.  If so, complete the standard
+   C conditional started above.  */
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/inc/fx_directory.h
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/inc/fx_directory.h	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/inc/fx_directory.h	(revision 30)
@@ -0,0 +1,137 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  COMPONENT DEFINITION                                   RELEASE        */
+/*                                                                        */
+/*    fx_directory.h                                      PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This file defines the FileX Directory component constants, data     */
+/*    definitions, and external references.  It is assumed that fx_api.h  */
+/*    (and fx_port.h) have already been included.                         */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+
+#ifndef FX_DIRECTORY_H
+#define FX_DIRECTORY_H
+
+
+/* Define the external Directory component function prototypes.  */
+
+UINT _fx_directory_attributes_read(FX_MEDIA *media_ptr, CHAR *directory_name, UINT *attributes_ptr);
+UINT _fx_directory_attributes_set(FX_MEDIA *media_ptr, CHAR *directory_name, UINT attributes);
+UINT _fx_directory_create(FX_MEDIA *media_ptr, CHAR *directory_name);
+UINT _fx_directory_default_get(FX_MEDIA *media_ptr, CHAR **return_path_name);
+UINT _fx_directory_default_get_copy(FX_MEDIA *media_ptr, CHAR *return_path_name_buffer, UINT return_path_name_buffer_size);
+UINT _fx_directory_default_set(FX_MEDIA *media_ptr, CHAR *new_path_name);
+UINT _fx_directory_delete(FX_MEDIA *media_ptr, CHAR *directory_name);
+UINT _fx_directory_entry_read_FAT(FX_MEDIA *media_ptr, FX_DIR_ENTRY *source_dir, ULONG *entry_ptr,
+                                  FX_DIR_ENTRY *destination_ptr);
+UINT _fx_directory_first_entry_find(FX_MEDIA *media_ptr, CHAR *directory_name);
+UINT _fx_directory_first_full_entry_find(FX_MEDIA *media_ptr, CHAR *directory_name, UINT *attributes,
+                                         ULONG *size, UINT *year, UINT *month, UINT *day, UINT *hour, UINT *minute, UINT *second);
+UINT _fx_directory_information_get(FX_MEDIA *media_ptr, CHAR *directory_name, UINT *attributes, ULONG *size,
+                                   UINT *year, UINT *month, UINT *day, UINT *hour, UINT *minute, UINT *second);
+UINT _fx_directory_local_path_clear(FX_MEDIA *media_ptr);
+UINT _fx_directory_local_path_get(FX_MEDIA *media_ptr, CHAR **return_path_name);
+UINT _fx_directory_local_path_get_copy(FX_MEDIA *media_ptr, CHAR *return_path_name_buffer, UINT return_path_name_buffer_size);
+UINT _fx_directory_local_path_restore(FX_MEDIA *media_ptr, FX_LOCAL_PATH *local_path_ptr);
+UINT _fx_directory_local_path_set(FX_MEDIA *media_ptr, FX_LOCAL_PATH *local_path_ptr, CHAR *new_path_name);
+UINT _fx_directory_long_name_get(FX_MEDIA *media_ptr, CHAR *short_file_name, CHAR *long_file_name);
+UINT _fx_directory_long_name_get_extended(FX_MEDIA *media_ptr, CHAR *short_file_name, CHAR *long_file_name, UINT long_file_name_buffer_length);
+UINT _fx_directory_name_test(FX_MEDIA *media_ptr, CHAR *directory_name);
+UINT _fx_directory_next_entry_find(FX_MEDIA *media_ptr, CHAR *directory_name);
+UINT _fx_directory_next_full_entry_find(FX_MEDIA *media_ptr, CHAR *directory_name, UINT *attributes,
+                                        ULONG *size, UINT *year, UINT *month, UINT *day, UINT *hour, UINT *minute, UINT *second);
+UINT _fx_directory_rename(FX_MEDIA *media_ptr, CHAR *old_directory_name, CHAR *new_directory_name);
+UINT _fx_directory_short_name_get(FX_MEDIA *media_ptr, CHAR *long_file_name, CHAR *short_file_name);
+UINT _fx_directory_short_name_get_extended(FX_MEDIA *media_ptr, CHAR *long_file_name, CHAR *short_file_name, UINT short_file_name_length);
+
+UINT _fxe_directory_attributes_read(FX_MEDIA *media_ptr, CHAR *directory_name, UINT *attributes_ptr);
+UINT _fxe_directory_attributes_set(FX_MEDIA *media_ptr, CHAR *directory_name, UINT attributes);
+UINT _fxe_directory_create(FX_MEDIA *media_ptr, CHAR *directory_name);
+UINT _fxe_directory_default_get(FX_MEDIA *media_ptr, CHAR **return_path_name);
+UINT _fxe_directory_default_get_copy(FX_MEDIA *media_ptr, CHAR *return_path_name_buffer, UINT return_path_name_buffer_size);
+UINT _fxe_directory_default_set(FX_MEDIA *media_ptr, CHAR *new_path_name);
+UINT _fxe_directory_delete(FX_MEDIA *media_ptr, CHAR *directory_name);
+UINT _fxe_directory_first_entry_find(FX_MEDIA *media_ptr, CHAR *directory_name);
+UINT _fxe_directory_first_full_entry_find(FX_MEDIA *media_ptr, CHAR *directory_name, UINT *attributes,
+                                          ULONG *size, UINT *year, UINT *month, UINT *day, UINT *hour, UINT *minute, UINT *second);
+UINT _fxe_directory_information_get(FX_MEDIA *media_ptr, CHAR *directory_name, UINT *attributes, ULONG *size,
+                                    UINT *year, UINT *month, UINT *day, UINT *hour, UINT *minute, UINT *second);
+UINT _fxe_directory_local_path_clear(FX_MEDIA *media_ptr);
+UINT _fxe_directory_local_path_get(FX_MEDIA *media_ptr, CHAR **return_path_name);
+UINT _fxe_directory_local_path_get_copy(FX_MEDIA *media_ptr, CHAR *return_path_name_buffer, UINT return_path_name_buffer_size);
+UINT _fxe_directory_local_path_restore(FX_MEDIA *media_ptr, FX_LOCAL_PATH *local_path_ptr);
+UINT _fxe_directory_local_path_set(FX_MEDIA *media_ptr, FX_LOCAL_PATH *local_path_ptr, CHAR *new_path_name, UINT local_path_control_block_size);
+UINT _fxe_directory_long_name_get(FX_MEDIA *media_ptr, CHAR *short_file_name, CHAR *long_file_name);
+UINT _fxe_directory_long_name_get_extended(FX_MEDIA *media_ptr, CHAR *short_file_name, CHAR *long_file_name, UINT long_file_name_buffer_length);
+UINT _fxe_directory_name_test(FX_MEDIA *media_ptr, CHAR *directory_name);
+UINT _fxe_directory_next_entry_find(FX_MEDIA *media_ptr, CHAR *directory_name);
+UINT _fxe_directory_next_full_entry_find(FX_MEDIA *media_ptr, CHAR *directory_name, UINT *attributes,
+                                         ULONG *size, UINT *year, UINT *month, UINT *day, UINT *hour, UINT *minute, UINT *second);
+UINT _fxe_directory_rename(FX_MEDIA *media_ptr, CHAR *old_directory_name, CHAR *new_directory_name);
+UINT _fxe_directory_short_name_get(FX_MEDIA *media_ptr, CHAR *long_file_name, CHAR *short_file_name);
+UINT _fxe_directory_short_name_get_extended(FX_MEDIA *media_ptr, CHAR *long_file_name, CHAR *short_file_name, UINT short_file_name_length);
+
+
+/* Define the internal Directory component function prototypes.  */
+#ifdef FX_ENABLE_EXFAT
+#define UPDATE_DELETE (0)
+#define UPDATE_FILE   (1)
+#define UPDATE_STREAM (2)
+#define UPDATE_NAME   (3)
+#define UPDATE_FULL   (4)
+
+UINT _fx_directory_entry_read_ex(FX_MEDIA *media_ptr, FX_DIR_ENTRY *source_dir, ULONG *entry, FX_DIR_ENTRY *destination_ptr, UINT hash);
+UINT _fx_directory_exFAT_entry_read(FX_MEDIA *media_ptr, FX_DIR_ENTRY *source_dir, ULONG *entry_ptr, FX_DIR_ENTRY *destination_ptr, UINT hash, UINT skip, UCHAR *unicode_name, UINT *unicode_len);
+UINT _fx_directory_exFAT_entry_write(FX_MEDIA *media_ptr, FX_DIR_ENTRY *entry_ptr, UCHAR update_level);
+UINT _fx_directory_exFAT_unicode_entry_write(FX_MEDIA *media_ptr, FX_DIR_ENTRY *entry_ptr, UCHAR update_level, USHORT *unicode_name,
+                                             UINT unicode_len);
+UINT _fx_directory_exFAT_free_search(FX_MEDIA *media_ptr, FX_DIR_ENTRY *directory_ptr, FX_DIR_ENTRY *entry_ptr);
+
+#endif /* FX_ENABLE_EXFAT */
+
+UINT  _fx_directory_entry_read(FX_MEDIA *media_ptr, FX_DIR_ENTRY *source_dir, ULONG *entry, FX_DIR_ENTRY *destination_ptr);
+UINT  _fx_directory_entry_write(FX_MEDIA *media_ptr, FX_DIR_ENTRY *entry_ptr);
+UINT  _fx_directory_free_search(FX_MEDIA *media_ptr, FX_DIR_ENTRY *directory_ptr, FX_DIR_ENTRY *entry_ptr);
+CHAR *_fx_directory_name_extract(CHAR *source_ptr, CHAR *dest_ptr);
+UINT  _fx_directory_search(FX_MEDIA *media_ptr, CHAR *name_ptr, FX_DIR_ENTRY *entry_ptr, FX_DIR_ENTRY *last_dir_ptr, CHAR **last_name_ptr);
+
+#endif
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/inc/fx_directory_exFAT.h
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/inc/fx_directory_exFAT.h	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/inc/fx_directory_exFAT.h	(revision 30)
@@ -0,0 +1,161 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  COMPONENT DEFINITION                                   RELEASE        */
+/*                                                                        */
+/*    fx_directory_exFAT.h                                PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This file defines the exFAT Directory entry component constants,    */
+/*    data definitions, and external references.                          */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+
+#ifndef FX_DIRECTORY_EXFAT_H
+#define FX_DIRECTORY_EXFAT_H
+
+#include "fx_api.h"
+
+#define FX_EXFAT_DIR_ENTRY_TYPE_ALLOCATION_BITMAP      0x81
+#define FX_EXFAT_DIR_ENTRY_TYPE_UP_CASE_TABLE          0x82
+#define FX_EXFAT_DIR_ENTRY_TYPE_VOLUME_LABEL           0x83
+#define FX_EXFAT_DIR_ENTRY_TYPE_FILE_DIRECTORY         0x85
+#define FX_EXFAT_DIR_ENTRY_TYPE_VOLUME_GUID            0xA0
+#define FX_EXFAT_DIR_ENTRY_TYPE_STREAM_EXTENSION       0xC0
+#define FX_EXFAT_DIR_ENTRY_TYPE_FILE_NAME              0xC1
+#define FX_EXFAT_DIR_ENTRY_TYPE_CONTINUOUS_INFO_MANAGE 0xE0
+#define FX_EXFAT_DIR_ENTRY_TYPE_CONTINUOUS_INFO        0xE1
+#define FX_EXFAT_DIR_ENTRY_TYPE_END_MARKER             0x00
+#define FX_EXFAT_DIR_ENTRY_TYPE_FREE                   0xFF
+
+
+/* Define the directory entry size.  */
+
+#define FX_EXFAT_DIR_ENTRY_SIZE                        32
+
+
+/* Define bit masks. */
+
+#define FX_EXFAT_ENTRY_TYPE_CODE_MASK                  0x1F
+#define FX_EXFAT_ENTRY_TYPE_IMPORTANCE_MASK            0x20
+#define FX_EXFAT_ENTRY_TYPE_CATEGORY_MASK              0x40
+#define FX_EXFAT_ENTRY_TYPE_IN_USE_MASK                0x80
+#define FX_EXFAT_SECOND_FLAG_ALLOCATION_POSSIBLE_MASK  0x01
+
+
+/* Define common primary and secondary directory entry structure.  */
+
+#define FX_EXFAT_ENTRY_TYPE                            0     /* Size 1 byte */
+
+
+/* Define primary-specific directory entry structure.  */
+
+#define FX_EXFAT_SECOND_COUNT                          1     /* Size 1 byte */
+#define FX_EXFAT_CHECK_SUM                             2     /* Size 2 bytes */
+#define FX_EXFAT_PRIM_FLAG                             4     /* Size 2 bytes */
+
+
+/* Define secondary-specific directory entry structure.  */
+
+#define FX_EXFAT_SECOND_FLAG                           1     /* Size 1 byte */
+
+
+/* Define common primary and secondary directory entry structure.  */
+
+#define FX_EXFAT_FIRST_CLUSTER                         20    /* Size 4 bytes */
+#define FX_EXFAT_DATA_LENGTH                           24    /* Size 8 bytes */
+
+
+/* Define Allocation Bitmap directory entry.  */
+
+#define FX_EXFAT_BIT_MAP_FLAGS                         1     /* Size 1 byte */
+
+
+/* Define UP-case Table Entry specific.  */
+
+#define FX_EXFAT_UP_CASE_TABLE_CHECK_SUM               4     /* Size 4 bytes */
+
+
+/* Define Volume Label Entry specific.  */
+
+#define FX_EXFAT_CHAR_COUNT                            1     /* Size 1 byte */
+#define FX_EXFAT_VOLUME_LABEL                          2     /* Size 22 bytes */
+
+
+/* Define File directory entry specific. This is a primary item.  */
+
+#define FX_EXFAT_FILE_ATTR                             4     /* Size 2 bytes */
+#define FX_EXFAT_CREATE_TIME                           8     /* Size 4 bytes */
+#define FX_EXFAT_LAST_MODIFIED_TIME                    12    /* Size 4 bytes */
+#define FX_EXFAT_LAST_ACCESSED_TIME                    16    /* Size 4 bytes */
+#define FX_EXFAT_LAST_CREATE_10MS_INC                  20    /* Size 1 byte */
+#define FX_EXFAT_LAST_MODIFIED_10MS_INC                21    /* Size 1 byte */
+#define FX_EXFAT_CREATE_UTC_OFFSET                     22    /* Size 1 byte */
+#define FX_EXFAT_LAST_MODIFIED_UTC_OFFSET              23    /* Size 1 byte */
+#define FX_EXFAT_LAST_ACCESSED_UTC_OFFSET              24    /* Size 1 byte */
+
+
+/* Define Volume GUID directory entry specific. This is a primary item.  */
+
+#define FX_EXFAT_VOLUME_GUID                           6     /* Size 16 bytes */
+
+
+/* Define Stream extension directory entry specific. This is a secondary item.  */
+
+#define FX_EXFAT_NAME_LENGTH                           3     /* Size 1 byte */
+#define FX_EXFAT_NAME_HASH                             4     /* Size 2 bytes */
+#define FX_EXFAT_VALID_DATA_LENGTH                     8     /* Size 8 bytes */
+
+
+/* Define File Name directory entry specific. This is a secondary item.  */
+
+#define FX_EXFAT_FILE_NAME                             2     /* Size 30 bytes */
+
+
+/* Define Continuous Information Manage directory entry specific. This is a secondary item.  */
+
+#define FX_EXFAT_VENDOR_GUID                           2     /* Size 16 bytes */
+#define FX_EXFAT_FAT_CHECKSUM                          20    /* Size 4  bytes */
+
+
+/* Define Continuous Information directory entry specific. This is a secondary item.  */
+
+#define FX_EXFAT_SET_CHECKSUM                          18    /* Size 2  bytes */
+
+#endif
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/inc/fx_fault_tolerant.h
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/inc/fx_fault_tolerant.h	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/inc/fx_fault_tolerant.h	(revision 30)
@@ -0,0 +1,414 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Fault Tolerant                                                      */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  COMPONENT DEFINITION                                   RELEASE        */
+/*                                                                        */
+/*    fx_fault_tolerant.h                                 PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This file defines the FileX Fault Tolerant component constants,     */
+/*    data definitions, and external references.  It is assumed that      */
+/*    fx_api.h (and fx_port.h) have already been included.                */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+
+#ifndef _FX_FAULT_TOLERANT_H_
+#define _FX_FAULT_TOLERANT_H_
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+
+#ifndef FX_FAULT_TOLERANT
+#error "FX_FAULT_TOLERANT must be defined with FX_ENABLE_FAULT_TOLERANT"
+#endif /* FX_FAULT_TOLERANT */
+
+/* Define ID of fault tolerant. */
+#define FX_FAULT_TOLERANT_ID                      0x46544C52
+
+/* Define fault tolerant version. */
+#define FX_FAULT_TOLERANT_VERSION_MAJOR           0x01
+#define FX_FAULT_TOLERANT_VERSION_MINOR           0x00
+
+/* Define byte offset in boot sector where the cluster number of the Fault Tolerant Log file is.
+   Note that this field (byte 116 to 119) is marked as reserved by FAT 12/16/32/exFAT specification. */
+#ifndef FX_FAULT_TOLERANT_BOOT_INDEX
+#define FX_FAULT_TOLERANT_BOOT_INDEX              116
+#endif /* FX_FAULT_TOLERANT_BOOT_INDEX */
+
+/* Define the extension invoked when fault tolerant log is recovered or applied during enable API. */
+#ifndef FX_FAULT_TOLERANT_ENABLE_EXTENSION
+#define FX_FAULT_TOLERANT_ENABLE_EXTENSION
+#endif /* FX_FAULT_TOLERANT_ENABLE_EXTENSION */
+
+/* Define the extension invoked when fault tolerant log is applied. */
+#ifndef FX_FAULT_TOLERANT_APPLY_LOGS_EXTENSION
+#define FX_FAULT_TOLERANT_APPLY_LOGS_EXTENSION
+#endif /* FX_FAULT_TOLERANT_APPLY_LOGS_EXTENSION */
+
+/* If not-defined, default port-specific processing extensions to white space.  */
+#ifndef FX_FAULT_TOLERANT_WRITE_LOG_FILE_EXTENSION
+#define FX_FAULT_TOLERANT_WRITE_LOG_FILE_EXTENSION
+#endif /* FX_FAULT_TOLERANT_WRITE_LOG_FILE_EXTENSION */
+
+/* Define the maximum size of log file. */
+#define FX_FAULT_TOLERANT_MAXIMUM_LOG_FILE_SIZE   3072
+
+/* For backward compatibility, map the symbols deprecated to FX_FAULT_TOLERANT_MINIMAL_BUFFER_SIZE. */
+#ifndef FX_FAULT_TOLERANT_MINIMAL_CLUSTER
+#define FX_FAULT_TOLERANT_MINIMAL_CLUSTER         FX_FAULT_TOLERANT_MAXIMUM_LOG_FILE_SIZE
+#endif /* FX_FAULT_TOLERANT_MINIMAL_CLUSTER */
+#ifndef FX_FAULT_TOLERANT_MINIMAL_BUFFER_SIZE
+#define FX_FAULT_TOLERANT_MINIMAL_BUFFER_SIZE     FX_FAULT_TOLERANT_MAXIMUM_LOG_FILE_SIZE
+#endif /* FX_FAULT_TOLERANT_MINIMAL_BUFFER_SIZE */
+
+/* Define the states of the fault tolerant module. */
+#define FX_FAULT_TOLERANT_STATE_IDLE              0x00u
+#define FX_FAULT_TOLERANT_STATE_STARTED           0x01u
+#define FX_FAULT_TOLERANT_STATE_SET_FAT_CHAIN     0x02u
+
+/* Define types of logs. */
+#define FX_FAULT_TOLERANT_FAT_LOG_TYPE            1
+#define FX_FAULT_TOLERANT_DIR_LOG_TYPE            2
+#define FX_FAULT_TOLERANT_BITMAP_LOG_TYPE         3
+
+/* Define operations of FAT chain. */
+#define FX_FAULT_TOLERANT_FAT_CHAIN_RECOVER       0     /* Recover new FAT chain. */
+#define FX_FAULT_TOLERANT_FAT_CHAIN_CLEANUP       1     /* Cleanup old FAT chain. */
+
+/* Define flags for FAT chain log. */
+#define FX_FAULT_TOLERANT_FLAG_FAT_CHAIN_VALID    0x01
+#define FX_FAULT_TOLERANT_FLAG_BITMAP_USED        0x02
+
+/* Define size of each section in log file. */
+#define FX_FAULT_TOLERANT_LOG_HEADER_SIZE         sizeof(FX_FAULT_TOLERANT_LOG_HEADER)
+#define FX_FAULT_TOLERANT_FAT_CHAIN_SIZE          sizeof(FX_FAULT_TOLERANT_FAT_CHAIN)
+#define FX_FAULT_TOLERANT_LOG_CONTENT_HEADER_SIZE sizeof(FX_FAULT_TOLERANT_LOG_CONTENT)
+
+/* Define offset of each section in log file. */
+#define FX_FAULT_TOLERANT_FAT_CHAIN_OFFSET        (FX_FAULT_TOLERANT_LOG_HEADER_SIZE)
+#define FX_FAULT_TOLERANT_LOG_CONTENT_OFFSET      (FX_FAULT_TOLERANT_LOG_HEADER_SIZE + FX_FAULT_TOLERANT_FAT_CHAIN_SIZE)
+
+/* Define size of log entries. */
+/* The total size of DIR log entry is variable. 16 is the fixed size of DIR log entry. */
+#define FX_FAULT_TOLERANT_FAT_LOG_ENTRY_SIZE      sizeof(FX_FAULT_TOLERANT_FAT_LOG)
+#define FX_FAULT_TOLERANT_BITMAP_LOG_ENTRY_SIZE   sizeof(FX_FAULT_TOLERANT_BITMAP_LOG)
+#define FX_FAULT_TOLERANT_DIR_LOG_ENTRY_SIZE      sizeof(FX_FAULT_TOLERANT_DIR_LOG)
+
+#ifdef FX_FAULT_TOLERANT_TRANSACTION_FAIL_FUNCTION
+#define FX_FAULT_TOLERANT_TRANSACTION_FAIL _fx_fault_tolerant_transaction_fail
+#else
+/* Define transaction fail for fault tolerant. */
+#define FX_FAULT_TOLERANT_TRANSACTION_FAIL(m)                            \
+    if ((m) -> fx_media_fault_tolerant_enabled == FX_TRUE)               \
+    {                                                                    \
+        (m) -> fx_media_fault_tolerant_transaction_count--;              \
+        if ((m) -> fx_media_fault_tolerant_transaction_count == 0)       \
+        {                                                                \
+            _fx_fault_tolerant_recover(m);                               \
+            _fx_fault_tolerant_reset_log_file(m);                        \
+        }                                                                \
+    }
+
+#endif /* FX_FAULT_TOLERANT_TRANSACTION_FAIL_FUNCTION */
+
+/* Log file format
+ * The entire log file fits into one cluster.
+ *
+ *                      1                   2                   3
+ *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * +                                ID                             +
+ * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * +   Total Log Size (in Bytes)    +        Header Checksum       +      Log Header
+ * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * +  version major + version minor +           reserved           +
+ * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * +      Checksum of FAT chain     +     Flag      |   Reserved   +
+ * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * +                   Insertion Point - Front                     +
+ * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * +            Head cluster of newly created FAT chain            +
+ * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++      FAT Chain
+ * +                 Head cluster of original FAT chain            +
+ * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * +                   Insertion Point - Back                      +
+ * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * +                     Next Deletion Point                       +
+ * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * +     checksum of log content    +      count of log entries    +
+ * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * + (log 0)                        .                              +
+ * +                                .                              +
+ * +                                .                              +
+ * +                                .                              +
+ * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * + (log 1)                        .                              +
+ * +                                .                              +      Log Entries
+ * +                                .                              +
+ * +                                .                              +
+ * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * +                               ...                             +
+ * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * + (log N)                        .                              +
+ * +                                .                              +
+ * +                                .                              +
+ * +                                .                              +
+ * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ *
+ *
+ * Log Header
+ *
+ *  * ID: It is fixed value FX_FAULT_TOLERANT_ID.
+ *  * Total Size: Total size (in bytes) of the log file, including Log Header, FAT Chain and Log Entries
+ *  * Header Checksum: It is the checksum of all data in log header.
+ *  * Version Major: The major version number.
+ *  * Version Minor: The minor version number.
+ *  * Reserved: Reserved for future use.
+ *
+ *  FAT Chain
+ *
+ *  * Checksum of FAT chain: It is the checksum of all data in the FAT Chain section.
+ *  * Flag: 8 bits. The 1-6 bits are not used (from left to right).
+ *      bit 7: When set, bitmap is used in old FAT chain.
+ *      bit 8: When set, FAT chain is valid.
+ *  * Reserved: Reserved for future use.
+ *  * Insertion Point - Front:  The cluster where the newly created chain is attached to
+ *  * Head cluster of new FAT chain. It is the head cluster of new FAT chain.
+ *  * Head cluster of oritinal FAT chain. It is the head cluster of the original FAT chain,
+ *        which will be removed.
+ *  * Inswertion Point - Back:  The original cluster right after the newly created chain is inserted.
+ *  * Next Deletion Point: next session of cluster to delete. It is used during deleting FAT chain.
+ *      The deltion is carried out in stages for perofmrance reasons.  When delting a FAT chain, the
+ *      Next Deletion Point is chosen, and the chain between head and the Next Deletion Point is deleted.
+ *
+ *  Log Entries:
+ *
+ *  * Checksum of log entries: It is the checksum of all data in Log Entries
+ *  * Counter of log entries: It is the counter of all log entries in Log content.
+ *  * log 0 ... log N: Log entries. The formats are described below.
+ */
+
+/* Defined structure of log header.
+
+
+ */
+typedef struct FX_FAULT_TOLERANT_LOG_HEADER_STRUCT
+{
+    ULONG  fx_fault_tolerant_log_header_id;
+    USHORT fx_fault_tolerant_log_header_total_size;
+    USHORT fx_fault_tolerant_log_header_checksum;
+    UCHAR  fx_fault_tolerant_log_header_version_major;
+    UCHAR  fx_fault_tolerant_log_header_version_minor;
+    USHORT fx_fault_tolerant_log_header_reserved;
+} FX_FAULT_TOLERANT_LOG_HEADER;
+
+/* Define structure of FAT chain. */
+typedef struct FX_FAULT_TOLERANT_FAT_CHAIN_STRUCT
+{
+    USHORT fx_fault_tolerant_FAT_chain_checksumm;
+    UCHAR  fx_fault_tolerant_FAT_chain_flag;
+    UCHAR  fx_fault_tolerant_FAT_chain_reserved;
+
+    ULONG  fx_fault_tolerant_FAT_chain_insertion_front;
+    ULONG  fx_fault_tolerant_FAT_chain_head_new;
+    ULONG  fx_fault_tolerant_FAT_chain_head_original;
+    ULONG  fx_fault_tolerant_FAT_chain_insertion_back;
+    ULONG  fx_fault_tolerant_FAT_chain_next_deletion;
+} FX_FAULT_TOLERANT_FAT_CHAIN;
+
+
+/* Define structure of Log content. */
+typedef struct FX_FAULT_TOLERANT_LOG_CONTENT_STRUCT
+{
+    USHORT fx_fault_tolerant_log_content_checksum;
+    USHORT fx_fault_tolerant_log_content_count;
+} FX_FAULT_TOLERANT_LOG_CONTENT;
+
+
+/* 3 types of log entries are defined. */
+/* FAT log format
+ * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * +              type              +           size               +
+ * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * +                             cluster                           +
+ * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * +                              value                            +
+ * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ *
+ * Description:
+ *
+ * Type:     FX_FAULT_TOLERANT_FAT_LOG.
+ * Size:     The size of this log entry.
+ * Cluster:  The cluster number in FAT.
+ * Value:    The value of cluster in FAT.
+ *
+ */
+typedef struct FX_FAULT_TOLERANT_FAT_LOG_STRUCT
+{
+    USHORT fx_fault_tolerant_FAT_log_type;
+    USHORT fx_fault_tolerant_FAT_log_size;
+    ULONG  fx_fault_tolerant_FAT_log_cluster;
+    ULONG  fx_fault_tolerant_FAT_log_value;
+} FX_FAULT_TOLERANT_FAT_LOG;
+
+/* DIR log format
+ * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * +              type              +           size               +
+ * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * +                         sector offset                         +
+ * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * +                           log sector                          +
+ * +                                                               +
+ * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * +                           log data                            +
+ * +                              .                                +
+ * +                              .                                +
+ * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ *
+ * Fields description,
+ *
+ * Type:          FX_FAULT_TOLERANT_DIRECTORY_LOG
+ * Size:          The size of this log entry.
+ * Sector Offset: The offset in original sector this DIR is trying to write to.
+ * Log Sector:    The original sector this DIR is trying to write to.
+ * Log Data:      Content of DIR entries.
+ *
+ */
+typedef struct FX_FAULT_TOLERANT_DIR_LOG_STRUCT
+{
+    USHORT  fx_fault_tolerant_dir_log_type;
+    USHORT  fx_fault_tolerant_dir_log_size;
+    ULONG   fx_fault_tolerant_dir_log_offset;
+    ULONG64 fx_fault_tolerant_dir_log_sector;
+} FX_FAULT_TOLERANT_DIR_LOG;
+
+/* Bitmap log format
+ * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * +              type              +           size               +
+ * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * +                             cluster                           +
+ * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * +                              value                            +
+ * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ *
+ * Description,
+ *
+ * Type:     FX_FAULT_TOLERANT_BITMAP_LOG.
+ * Size:     The size of this log entry.
+ * Cluster:  The cluster number in FAT.
+ * Value:    The value of cluster in FAT.
+ */
+typedef struct FX_FAULT_TOLERANT_BITMAP_LOG_STRUCT
+{
+    USHORT fx_fault_tolerant_bitmap_log_type;
+    USHORT fx_fault_tolerant_bitmap_log_size;
+    ULONG  fx_fault_tolerant_bitmap_log_cluster;
+    ULONG  fx_fault_tolerant_bitmap_log_value;
+} FX_FAULT_TOLERANT_BITMAP_LOG;
+
+
+/* This function checks whether or not the log file exists, and creates the log file if it does not exist. */
+UINT _fx_fault_tolerant_enable(FX_MEDIA *media_ptr, VOID *memory_buffer, UINT memory_size);
+UINT _fxe_fault_tolerant_enable(FX_MEDIA *media_ptr, VOID *memory_buffer, UINT memory_size);
+
+/* This function resets statistics and marks the start of a transaction. */
+UINT _fx_fault_tolerant_transaction_start(FX_MEDIA *media_ptr);
+
+/* This function marks the end of a transaction and completes the log file.
+ * Then it applies all data in the log file to the file system.
+ * Finally it resets the log header section. */
+UINT _fx_fault_tolerant_transaction_end(FX_MEDIA *media_ptr);
+
+/* This function resets the log file. */
+UINT _fx_fault_tolerant_reset_log_file(FX_MEDIA *media_ptr);
+
+/* This function applies the log file to the file system. */
+UINT _fx_fault_tolerant_apply_logs(FX_MEDIA *media_ptr);
+
+/* This function recovers FAT chain. */
+UINT _fx_fault_tolerant_recover(FX_MEDIA *media_ptr);
+
+/* This function adds a FAT log entry. */
+UINT _fx_fault_tolerant_add_FAT_log(FX_MEDIA *media_ptr, ULONG cluster, ULONG value);
+
+/* This function adds a directory log entry. */
+UINT _fx_fault_tolerant_add_dir_log(FX_MEDIA *media_ptr, ULONG64 logical_sector, ULONG offset,
+                                    UCHAR *data, ULONG data_size);
+#ifdef FX_ENABLE_EXFAT
+/* This function adds a bitmap log entry. */
+UINT _fx_fault_tolerant_add_bitmap_log(FX_MEDIA *media_ptr, ULONG cluster, ULONG value);
+
+/* This function adds a checksum log entry. */
+UINT _fx_fault_tolerant_add_checksum_log(FX_MEDIA *media_ptr, ULONG64 logical_sector, ULONG offset, USHORT checksum);
+#endif /* FX_ENABLE_EXFAT */
+
+/* This function sets the FAT chain. */
+UINT _fx_fault_tolerant_set_FAT_chain(FX_MEDIA *media_ptr, UINT use_bitmap, ULONG insertion_front,
+                                      ULONG new_head_cluster, ULONG original_head_cluster, ULONG insertion_back);
+
+/* This function reads a FAT entry from log file. If it doesn't exist in log file, return and read from FAT entry directly. */
+UINT _fx_fault_tolerant_read_FAT(FX_MEDIA *media_ptr, ULONG cluster, ULONG *value, ULONG log_type);
+
+/* This function reads directory sector from log file. */
+UINT _fx_fault_tolerant_read_directory_sector(FX_MEDIA *media_ptr, ULONG64 logical_sector,
+                                              VOID *buffer_ptr, ULONG64 sectors);
+
+/* This function calculates the checksum of the log header. */
+USHORT _fx_fault_tolerant_calculate_checksum(UCHAR *data, UINT len);
+
+/* This function cleans up FAT chain. */
+UINT _fx_fault_tolerant_cleanup_FAT_chain(FX_MEDIA *media_ptr, UINT operation);
+
+/* This function reads log file from file system to memory buffer. */
+UINT _fx_fault_tolerant_read_log_file(FX_MEDIA *media_ptr);
+
+/* This function writes data of one sector from memory to log file in file system. */
+UINT _fx_fault_tolerant_write_log_file(FX_MEDIA *media_ptr, ULONG relative_sector);
+
+/* This function creates log file. */
+UINT _fx_fault_tolerant_create_log_file(FX_MEDIA *media_ptr);
+
+#ifdef FX_FAULT_TOLERANT_TRANSACTION_FAIL_FUNCTION
+/* This function cleans up resources created by fault tolerant when transaction fails. */
+UINT _fx_fault_tolerant_transaction_fail(FX_MEDIA *media_ptr);
+#endif /* FX_FAULT_TOLERANT_TRANSACTION_FAIL_FUNCTION */
+
+
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+#endif /* _FX_FAULT_TOLERANT_H_ */
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/inc/fx_file.h
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/inc/fx_file.h	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/inc/fx_file.h	(revision 30)
@@ -0,0 +1,125 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  COMPONENT DEFINITION                                   RELEASE        */
+/*                                                                        */
+/*    fx_file.h                                           PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This file defines the FileX File component constants, data          */
+/*    definitions, and external references.  It is assumed that fx_api.h  */
+/*    (and fx_port.h) have already been included.                         */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s), and      */
+/*                                            added conditional to        */
+/*                                            disable one line function,  */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+
+#ifndef FX_FILE_H
+#define FX_FILE_H
+
+
+/* Define the external File component function prototypes.  */
+
+#ifndef FX_DISABLE_ONE_LINE_FUNCTION
+UINT _fx_file_allocate(FX_FILE *file_ptr, ULONG size);
+#else
+#define _fx_file_allocate(f, s)                _fx_file_extended_allocate(f, (ULONG64)s);
+#endif /* FX_DISABLE_ONE_LINE_FUNCTION */
+UINT _fx_file_attributes_read(FX_MEDIA *media_ptr, CHAR *file_name, UINT *attributes_ptr);
+UINT _fx_file_attributes_set(FX_MEDIA *media_ptr, CHAR *file_name, UINT attributes);
+UINT _fx_file_best_effort_allocate(FX_FILE *file_ptr, ULONG size, ULONG *actual_size_allocated);
+UINT _fx_file_close(FX_FILE *file_ptr);
+UINT _fx_file_create(FX_MEDIA *media_ptr, CHAR *file_name);
+UINT _fx_file_date_time_set(FX_MEDIA *media_ptr, CHAR *file_name,
+                            UINT year, UINT month, UINT day, UINT hour, UINT minute, UINT second);
+UINT _fx_file_delete(FX_MEDIA *media_ptr, CHAR *file_name);
+UINT _fx_file_open(FX_MEDIA *media_ptr, FX_FILE *file_ptr, CHAR *file_name,
+                   UINT open_type);
+UINT _fx_file_read(FX_FILE *file_ptr, VOID *buffer_ptr, ULONG request_size, ULONG *actual_size);
+#ifndef FX_DISABLE_ONE_LINE_FUNCTION
+UINT _fx_file_relative_seek(FX_FILE *file_ptr, ULONG byte_offset, UINT seek_from);
+#else
+#define _fx_file_relative_seek(f, b, sf)       _fx_file_extended_relative_seek(f, (ULONG64)b, sf);
+#endif /* FX_DISABLE_ONE_LINE_FUNCTION */
+UINT _fx_file_rename(FX_MEDIA *media_ptr, CHAR *old_file_name, CHAR *new_file_name);
+#ifndef FX_DISABLE_ONE_LINE_FUNCTION
+UINT _fx_file_seek(FX_FILE *file_ptr, ULONG byte_offset);
+UINT _fx_file_truncate(FX_FILE *file_ptr, ULONG size);
+UINT _fx_file_truncate_release(FX_FILE *file_ptr, ULONG size);
+#else
+#define _fx_file_seek(f, b)                    _fx_file_extended_seek(f, (ULONG64)b)
+#define _fx_file_truncate(f, s)                _fx_file_extended_truncate(f, (ULONG64)s);
+#define _fx_file_truncate_release(f, s)        _fx_file_extended_truncate_release(f, (ULONG64)s);
+#endif /* FX_DISABLE_ONE_LINE_FUNCTION */
+UINT _fx_file_write(FX_FILE *file_ptr, VOID *buffer_ptr, ULONG size);
+UINT _fx_file_write_notify_set(FX_FILE *file_ptr, VOID (*file_write_notify)(FX_FILE *));
+UINT _fx_file_extended_allocate(FX_FILE *file_ptr, ULONG64 size);
+UINT _fx_file_extended_best_effort_allocate(FX_FILE *file_ptr, ULONG64 size, ULONG64 *actual_size_allocated);
+UINT _fx_file_extended_relative_seek(FX_FILE *file_ptr, ULONG64 byte_offset, UINT seek_from);
+UINT _fx_file_extended_seek(FX_FILE *file_ptr, ULONG64 byte_offset);
+UINT _fx_file_extended_truncate(FX_FILE *file_ptr, ULONG64 size);
+UINT _fx_file_extended_truncate_release(FX_FILE *file_ptr, ULONG64 size);
+
+UINT _fxe_file_allocate(FX_FILE *file_ptr, ULONG size);
+UINT _fxe_file_attributes_read(FX_MEDIA *media_ptr, CHAR *file_name, UINT *attributes_ptr);
+UINT _fxe_file_attributes_set(FX_MEDIA *media_ptr, CHAR *file_name, UINT attributes);
+UINT _fxe_file_best_effort_allocate(FX_FILE *file_ptr, ULONG size, ULONG *actual_size_allocated);
+UINT _fxe_file_close(FX_FILE *file_ptr);
+UINT _fxe_file_create(FX_MEDIA *media_ptr, CHAR *file_name);
+UINT _fxe_file_date_time_set(FX_MEDIA *media_ptr, CHAR *file_name,
+                             UINT year, UINT month, UINT day, UINT hour, UINT minute, UINT second);
+UINT _fxe_file_delete(FX_MEDIA *media_ptr, CHAR *file_name);
+UINT _fxe_file_open(FX_MEDIA *media_ptr, FX_FILE *file_ptr, CHAR *file_name,
+                    UINT open_type, UINT file_control_block_size);
+UINT _fxe_file_read(FX_FILE *file_ptr, VOID *buffer_ptr, ULONG request_size, ULONG *actual_size);
+UINT _fxe_file_relative_seek(FX_FILE *file_ptr, ULONG byte_offset, UINT seek_from);
+UINT _fxe_file_rename(FX_MEDIA *media_ptr, CHAR *old_file_name, CHAR *new_file_name);
+UINT _fxe_file_seek(FX_FILE *file_ptr, ULONG byte_offset);
+UINT _fxe_file_truncate(FX_FILE *file_ptr, ULONG size);
+UINT _fxe_file_truncate_release(FX_FILE *file_ptr, ULONG size);
+UINT _fxe_file_write(FX_FILE *file_ptr, VOID *buffer_ptr, ULONG size);
+UINT _fxe_file_write_notify_set(FX_FILE *file_ptr, VOID (*file_write_notify)(FX_FILE *));
+UINT _fxe_file_extended_allocate(FX_FILE *file_ptr, ULONG64 size);
+UINT _fxe_file_extended_best_effort_allocate(FX_FILE *file_ptr, ULONG64 size, ULONG64 *actual_size_allocated);
+UINT _fxe_file_extended_relative_seek(FX_FILE *file_ptr, ULONG64 byte_offset, UINT seek_from);
+UINT _fxe_file_extended_seek(FX_FILE *file_ptr, ULONG64 byte_offset);
+UINT _fxe_file_extended_truncate(FX_FILE *file_ptr, ULONG64 size);
+UINT _fxe_file_extended_truncate_release(FX_FILE *file_ptr, ULONG64 size);
+
+#endif
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/inc/fx_media.h
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/inc/fx_media.h	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/inc/fx_media.h	(revision 30)
@@ -0,0 +1,114 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  COMPONENT DEFINITION                                   RELEASE        */
+/*                                                                        */
+/*    fx_media.h                                          PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This file defines the FileX Media component constants, data         */
+/*    definitions, and external references.  It is assumed that fx_api.h  */
+/*    (and fx_port.h) have already been included.                         */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+
+#ifndef FX_MEDIA_H
+#define FX_MEDIA_H
+
+
+/* Define the external Media component function prototypes.  */
+
+UINT _fx_media_abort(FX_MEDIA *media_ptr);
+UINT _fx_media_cache_invalidate(FX_MEDIA *media_ptr);
+UINT _fx_media_check(FX_MEDIA *media_ptr, UCHAR *scratch_memory_ptr, ULONG scratch_memory_size, ULONG error_correction_option, ULONG *errors_detected);
+UINT _fx_media_close(FX_MEDIA *media_ptr);
+UINT _fx_media_flush(FX_MEDIA *media_ptr);
+UINT _fx_media_format(FX_MEDIA *media_ptr, VOID (*driver)(FX_MEDIA *media), VOID *driver_info_ptr, UCHAR *memory_ptr, UINT memory_size,
+                      CHAR *volume_name, UINT number_of_fats, UINT directory_entries, UINT hidden_sectors,
+                      ULONG total_sectors, UINT bytes_per_sector, UINT sectors_per_cluster,
+                      UINT heads, UINT sectors_per_track);
+UINT _fx_media_exFAT_format(FX_MEDIA *media_ptr, VOID (*driver)(FX_MEDIA *media), VOID *driver_info_ptr, UCHAR *memory_ptr, UINT memory_size,
+                            CHAR *volume_name, UINT number_of_fats, ULONG64 hidden_sectors, ULONG64 total_sectors, UINT bytes_per_sector, UINT sectors_per_cluster, UINT volume_serial_number, UINT boundary_unit);
+UINT _fx_media_open(FX_MEDIA *media_ptr, CHAR *media_name,
+                    VOID (*media_driver)(FX_MEDIA *), VOID *driver_info_ptr,
+                    VOID *memory_ptr, ULONG memory_size);
+UINT _fx_media_read(FX_MEDIA *media_ptr, ULONG logical_sector, VOID *buffer_ptr);
+UINT _fx_media_space_available(FX_MEDIA *media_ptr, ULONG *available_bytes_ptr);
+UINT _fx_media_volume_get(FX_MEDIA *media_ptr, CHAR *volume_name, UINT volume_source);
+UINT _fx_media_volume_get_extended(FX_MEDIA *media_ptr, CHAR *volume_name, UINT volume_name_buffer_length, UINT volume_source);
+UINT _fx_media_volume_set(FX_MEDIA *media_ptr, CHAR *volume_name);
+UINT _fx_media_write(FX_MEDIA *media_ptr, ULONG logical_sector, VOID *buffer_ptr);
+UINT _fx_media_open_notify_set(FX_MEDIA *media_ptr, VOID (*media_open_notify)(FX_MEDIA *));
+UINT _fx_media_close_notify_set(FX_MEDIA *media_ptr, VOID (*media_close_notify)(FX_MEDIA *));
+UINT _fx_media_extended_space_available(FX_MEDIA *media_ptr, ULONG64 *available_bytes_ptr);
+
+
+UINT _fxe_media_abort(FX_MEDIA *media_ptr);
+UINT _fxe_media_cache_invalidate(FX_MEDIA *media_ptr);
+UINT _fxe_media_check(FX_MEDIA *media_ptr, UCHAR *scratch_memory_ptr, ULONG scratch_memory_size, ULONG error_correction_option, ULONG *errors_detected);
+UINT _fxe_media_close(FX_MEDIA *media_ptr);
+UINT _fxe_media_flush(FX_MEDIA *media_ptr);
+UINT _fxe_media_format(FX_MEDIA *media_ptr, VOID (*driver)(FX_MEDIA *media), VOID *driver_info_ptr, UCHAR *memory_ptr, UINT memory_size,
+                       CHAR *volume_name, UINT number_of_fats, UINT directory_entries, UINT hidden_sectors,
+                       ULONG total_sectors, UINT bytes_per_sector, UINT sectors_per_cluster,
+                       UINT heads, UINT sectors_per_track);
+UINT _fxe_media_exFAT_format(FX_MEDIA *media_ptr, VOID (*driver)(FX_MEDIA *media), VOID *driver_info_ptr, UCHAR *memory_ptr, UINT memory_size,
+                             CHAR *volume_name, UINT number_of_fats, ULONG64 hidden_sectors, ULONG64 total_sectors, UINT bytes_per_sector, UINT sectors_per_cluster, UINT volume_serial_number, UINT boundary_unit);
+UINT _fxe_media_open(FX_MEDIA *media_ptr, CHAR *media_name,
+                     VOID (*media_driver)(FX_MEDIA *), VOID *driver_info_ptr,
+                     VOID *memory_ptr, ULONG memory_size, UINT media_control_block_size);
+UINT _fxe_media_read(FX_MEDIA *media_ptr, ULONG logical_sector, VOID *buffer_ptr);
+UINT _fxe_media_space_available(FX_MEDIA *media_ptr, ULONG *available_bytes_ptr);
+UINT _fxe_media_volume_get(FX_MEDIA *media_ptr, CHAR *volume_name, UINT volume_source);
+UINT _fxe_media_volume_get_extended(FX_MEDIA *media_ptr, CHAR *volume_name, UINT volume_name_buffer_length, UINT volume_source);
+UINT _fxe_media_volume_set(FX_MEDIA *media_ptr, CHAR *volume_name);
+UINT _fxe_media_write(FX_MEDIA *media_ptr, ULONG logical_sector, VOID *buffer_ptr);
+UINT _fxe_media_open_notify_set(FX_MEDIA *media_ptr, VOID (*media_open_notify)(FX_MEDIA *));
+UINT _fxe_media_close_notify_set(FX_MEDIA *media_ptr, VOID (*media_close_notify)(FX_MEDIA *));
+UINT _fxe_media_extended_space_available(FX_MEDIA *media_ptr, ULONG64 *available_bytes_ptr);
+
+
+/* Define the internal Media component function prototypes.  */
+
+ULONG _fx_media_check_FAT_chain_check(FX_MEDIA *media_ptr, ULONG starting_cluster, ULONG *last_valid_cluster, ULONG *total_valid_clusters, UCHAR *logical_fat);
+ULONG _fx_media_check_lost_cluster_check(FX_MEDIA *media_ptr, UCHAR *logical_fat, ULONG total_clusters, ULONG error_correction_option);
+ULONG _fx_media_check_exFAT_lost_cluster_check(FX_MEDIA *media_ptr, UCHAR *logical_fat, ULONG total_clusters, ULONG error_correction_option);
+UINT  _fx_media_boot_info_extract(FX_MEDIA *media_ptr);
+
+#endif
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/inc/fx_system.h
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/inc/fx_system.h	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/inc/fx_system.h	(revision 30)
@@ -0,0 +1,175 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   System                                                              */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  COMPONENT DEFINITION                                   RELEASE        */
+/*                                                                        */
+/*    fx_system.h                                         PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This file defines the FileX system constants and global data        */
+/*    definitions, including external references.  It is assumed that     */
+/*    fx_api.h (and fx_port.h) have already been included.                */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+
+#ifndef FX_SYSTEM_H
+#define FX_SYSTEM_H
+
+
+/* Define System component constants.  */
+
+#define FX_TIMER_ID                 ((ULONG) 0x46585359)
+
+
+/* Define the external System component function prototypes.  */
+
+VOID _fx_system_initialize(VOID);
+UINT _fx_system_date_set(UINT year, UINT month, UINT day);
+UINT _fx_system_time_set(UINT hour, UINT minute, UINT second);
+UINT _fx_system_date_get(UINT *year, UINT *month, UINT *day);
+UINT _fx_system_time_get(UINT *hour, UINT *minute, UINT *second);
+VOID _fx_system_timer_entry(ULONG id);
+
+UINT _fxe_system_date_set(UINT year, UINT month, UINT day);
+UINT _fxe_system_time_set(UINT hour, UINT minute, UINT second);
+UINT _fxe_system_date_get(UINT *year, UINT *month, UINT *day);
+UINT _fxe_system_time_get(UINT *hour, UINT *minute, UINT *second);
+
+
+/* System Component data declarations follow.  */
+
+/* Determine if the initialization function of this component is including
+   this file.  If so, make the data definitions really happen.  Otherwise,
+   make them extern so other functions in the component can access them.  */
+
+#ifdef FX_SYSTEM_INIT
+#define SYSTEM_DECLARE
+#else
+#define SYSTEM_DECLARE extern
+#endif
+
+
+/* Define the head pointer of the opened media list.  */
+
+SYSTEM_DECLARE  FX_MEDIA  *_fx_system_media_opened_ptr;
+
+
+/* Define the variable that holds the number of open media. */
+
+SYSTEM_DECLARE  ULONG  _fx_system_media_opened_count;
+
+
+/* Define the system date variable.  */
+
+SYSTEM_DECLARE  UINT  _fx_system_date;
+
+
+/* Define the system time variable.  */
+
+SYSTEM_DECLARE  UINT  _fx_system_time;
+
+
+/* Define the variable that holds the maximum size of the sector cache.  */
+
+SYSTEM_DECLARE  ULONG  _fx_system_media_max_sector_cache;
+
+
+/* Define the variable that holds the maximum size of the FAT cache.  */
+
+SYSTEM_DECLARE  ULONG  _fx_system_media_max_fat_cache;
+
+
+/* Define the global FileX build options variables. These variables contain a bit
+   map representing how the FileX library was built. The following are the bit
+   field definitions:
+
+    _fx_system_build_options_1:
+
+                    Bit(s)                   Meaning
+
+                    31-24               FX_MAX_LONG_NAME_LEN
+                    23-16               FX_MAX_LAST_NAME_LEN
+                    15-11               Reserved
+                    10                  FX_NO_TIMER defined
+                    9                   FX_SINGLE_THREAD defined
+                    8                   FX_DONT_UPDATE_OPEN_FILES defined
+                    7                   FX_MEDIA_DISABLE_SEARCH_CACHE defined
+                    6                   FX_MEDIA_STATISTICS_DISABLE defined
+                    5                   Reserved
+                    4                   FX_SINGLE_OPEN_LEGACY defined
+                    3                   FX_RENAME_PATH_INHERIT defined
+                    2                   FX_NO_LOCAL_PATH defined
+                    1                   FX_FAULT_TOLERANT_DATA defined
+                    0                   FX_FAULT_TOLERANT defined
+
+    _fx_system_build_options_2:
+
+                    Bit(s)                   Meaning
+
+                    31-16               FX_MAX_SECTOR_CACHE
+                    15-8                FX_FAT_MAP_SIZE
+                    7-0                 FX_MAX_FAT_CACHE
+
+    _fx_system_build_options_3:
+
+                    Bit(s)                   Meaning
+
+                    31-24               Reserved
+                    23-16               FX_UPDATE_RATE_IN_SECONDS
+                    15-0                FX_UPDATE_RATE_IN_TICKS
+
+   Note that values greater than the value that can be represented in the build options
+   bit field are represented as all ones in the bit field. For example, if FX_MAX_LONG_NAME_LEN
+   is 256, the value in the bits 31-24 of _fx_system_build_options_1 is 0xFF, which is 255
+   decimal.  */
+
+SYSTEM_DECLARE  ULONG _fx_system_build_options_1;
+SYSTEM_DECLARE  ULONG _fx_system_build_options_2;
+SYSTEM_DECLARE  ULONG _fx_system_build_options_3;
+
+
+/* Define system timer control block.  If accurate date/time stamps on
+   files is not needed, the define FX_NO_TIMER should be used when
+   compiling fx_system_initialize.c to eliminate the FileX timer.  */
+
+#ifndef FX_NO_TIMER
+SYSTEM_DECLARE  TX_TIMER _fx_system_timer;
+#endif
+
+#endif
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/inc/fx_unicode.h
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/inc/fx_unicode.h	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/inc/fx_unicode.h	(revision 30)
@@ -0,0 +1,110 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Unicode                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  COMPONENT DEFINITION                                   RELEASE        */
+/*                                                                        */
+/*    fx_unicode.h                                        PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This file defines the FileX Unicode component constants, data       */
+/*    definitions, and external references.  It is assumed that fx_api.h  */
+/*    (and fx_port.h) have already been included.                         */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+
+#ifndef FX_UNICODE_H
+#define FX_UNICODE_H
+
+
+/* Define external data for the Unicode component.  */
+
+extern UCHAR   _fx_unicode_temp_long_file_name[FX_MAX_LONG_NAME_LEN];
+extern UCHAR _fx_unicode_search_name[FX_MAX_LONG_NAME_LEN * 2];
+
+
+/* Define the external Unicode component function prototypes.  */
+
+UINT  _fx_unicode_directory_create(FX_MEDIA *media_ptr, UCHAR *source_unicode_name, ULONG source_unicode_length,
+                                   CHAR *short_name);
+UINT  _fx_unicode_directory_rename(FX_MEDIA *media_ptr, UCHAR *old_unicode_name, ULONG old_unicode_length,
+                                   UCHAR *new_unicode_name, ULONG new_unicode_length, CHAR *new_short_name);
+UINT  _fx_unicode_file_create(FX_MEDIA *media_ptr, UCHAR *source_unicode_name, ULONG source_unicode_length,
+                              CHAR *short_name);
+ULONG _fx_unicode_length_get(UCHAR *unicode_name);
+ULONG _fx_unicode_length_get_extended(UCHAR *unicode_name, UINT buffer_length);
+UINT  _fx_unicode_name_get(FX_MEDIA *media_ptr, CHAR *source_short_name,
+                           UCHAR *destination_unicode_name, ULONG *destination_unicode_length);
+UINT  _fx_unicode_name_get_extended(FX_MEDIA *media_ptr, CHAR *source_short_name,
+                           UCHAR *destination_unicode_name, ULONG *destination_unicode_length, ULONG unicode_name_buffer_length);
+UINT  _fx_unicode_file_rename(FX_MEDIA *media_ptr, UCHAR *old_unicode_name, ULONG old_unicode_length,
+                              UCHAR *new_unicode_name, ULONG new_unicode_length, CHAR *new_short_name);
+UINT  _fx_unicode_short_name_get(FX_MEDIA *media_ptr, UCHAR *source_unicode_name, ULONG source_unicode_length,
+                                 CHAR *destination_short_name);
+UINT  _fx_unicode_short_name_get_extended(FX_MEDIA *media_ptr, UCHAR *source_unicode_name, ULONG source_unicode_length,
+                                 CHAR *destination_short_name, ULONG short_name_buffer_length);
+
+UINT _fxe_unicode_directory_create(FX_MEDIA *media_ptr, UCHAR *source_unicode_name, ULONG source_unicode_length,
+                                   CHAR *short_name);
+UINT _fxe_unicode_directory_rename(FX_MEDIA *media_ptr, UCHAR *old_unicode_name, ULONG old_unicode_length,
+                                   UCHAR *new_unicode_name, ULONG new_unicode_length, CHAR *new_short_name);
+UINT _fxe_unicode_file_create(FX_MEDIA *media_ptr, UCHAR *source_unicode_name, ULONG source_unicode_length,
+                              CHAR *short_name);
+UINT _fxe_unicode_file_rename(FX_MEDIA *media_ptr, UCHAR *old_unicode_name, ULONG old_unicode_length,
+                              UCHAR *new_unicode_name, ULONG new_unicode_length, CHAR *new_short_name);
+UINT _fxe_unicode_name_get(FX_MEDIA *media_ptr, CHAR *source_short_name,
+                           UCHAR *destination_unicode_name, ULONG *destination_unicode_length);
+UINT _fxe_unicode_name_get_extended(FX_MEDIA *media_ptr, CHAR *source_short_name,
+                           UCHAR *destination_unicode_name, ULONG *destination_unicode_length, ULONG unicode_name_buffer_length);
+UINT _fxe_unicode_short_name_get(FX_MEDIA *media_ptr, UCHAR *source_unicode_name, ULONG source_unicode_length,
+                                 CHAR *destination_short_name);
+UINT _fxe_unicode_short_name_get_extended(FX_MEDIA *media_ptr, UCHAR *source_unicode_name, ULONG source_unicode_length,
+                                 CHAR *destination_short_name, ULONG short_name_buffer_length);                                 
+
+/* Define the internal Unicode component function prototypes.  */
+
+UINT  _fx_unicode_directory_search(FX_MEDIA *media_ptr, FX_DIR_ENTRY *entry_ptr,
+                                   UCHAR *short_name, ULONG short_name_buffer_length, 
+                                   UCHAR *unicode_name, ULONG *unicode_name_length, ULONG unicode_name_buffer_length);
+UINT _fx_unicode_directory_entry_read(FX_MEDIA *media_ptr, FX_DIR_ENTRY *source_dir,
+                                      ULONG *entry_ptr, FX_DIR_ENTRY *destination_ptr,
+                                      UCHAR *unicode_name, ULONG *unicode_size);
+UINT _fx_unicode_directory_entry_change(FX_MEDIA *media_ptr, FX_DIR_ENTRY *entry_ptr, UCHAR *unicode_name, ULONG unicode_name_length);
+
+
+#endif
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/inc/fx_user_sample.h
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/inc/fx_user_sample.h	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/inc/fx_user_sample.h	(revision 30)
@@ -0,0 +1,261 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   User Specific                                                       */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  PORT SPECIFIC C INFORMATION                            RELEASE        */
+/*                                                                        */
+/*    fx_user.h                                           PORTABLE C      */
+/*                                                           6.1.10       */
+/*                                                                        */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This file contains user defines for configuring FileX in specific   */
+/*    ways. This file will have an effect only if the application and     */
+/*    FileX library are built with FX_INCLUDE_USER_DEFINE_FILE defined.   */
+/*    Note that all the defines in this file may also be made on the      */
+/*    command line when building FileX library and application objects.   */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s), and      */
+/*                                            added product constants     */
+/*                                            to enable code              */
+/*                                            size optimization,          */
+/*                                            resulting in version 6.1    */
+/*  03-02-2021     William E. Lamie         Modified comment(s), and      */
+/*                                            added standalone support,   */
+/*                                            resulting in version 6.1.5  */
+/*  01-31-2022     Bhupendra Naphade        Modified comment(s), and      */
+/*                                            added product constant to   */
+/*                                            support variable sector     */
+/*                                            size in exFAT,              */
+/*                                            resulting in version 6.1.10 */
+/*                                                                        */
+/**************************************************************************/
+
+#ifndef FX_USER_H
+#define FX_USER_H
+
+
+/* Define various build options for the FileX port.  The application should either make changes
+   here by commenting or un-commenting the conditional compilation defined OR supply the defines
+   though the compiler's equivalent of the -D option.  */
+
+
+/* Override various options with default values already assigned in fx_api.h or fx_port.h. Please
+   also refer to fx_port.h for descriptions on each of these options.  */
+
+
+/* Defines the maximum size of long file names supported by FileX. The default value is 33. The
+   minimum value is 13 and the maximum value is 256.  */
+
+/*#define FX_MAX_LONG_NAME_LEN            256   */
+/*#define FX_MAX_LAST_NAME_LEN            256   */      /* Must be as large or larger than FX_MAX_LONG_NAME_LEN */
+
+
+/* Defines the maximum number of logical sectors that can be cached by FileX. The cache memory
+   supplied to FileX at fx_media_open determines how many sectors can actually be cached.  */
+
+/*#define FX_MAX_SECTOR_CACHE             256   */      /* Minimum value is 2, all other values must be power of 2.  */
+
+
+/* Defines the size in bytes of the bit map used to update the secondary FAT sectors. The larger the value the
+   less unnecessary secondary FAT sector writes.   */
+
+/*#define FX_FAT_MAP_SIZE                 128  */       /* Minimum value is 1, no maximum value.  */
+
+
+/* Defines the number of entries in the FAT cache.  */
+
+/*#define FX_MAX_FAT_CACHE                16   */       /* Minimum value is 8, all values must be a power of 2.  */
+
+
+/* Defines the number of seconds the time parameters are updated in FileX.  */
+
+/*#define FX_UPDATE_RATE_IN_SECONDS       10   */
+
+
+/* Defines the number of ThreadX timer ticks required to achieve the update rate specified by
+   FX_UPDATE_RATE_IN_SECONDS defined previously. By default, the ThreadX timer tick is 10ms,
+   so the default value for this constant is 1000.  */
+
+/*#define FX_UPDATE_RATE_IN_TICKS         1000 */
+
+
+/* Defined, FileX is built without update to the time parameters.  */
+
+/*#define FX_NO_TIMER  */
+
+
+/* Defined, FileX does not update already opened files.  */
+
+/*#define FX_DONT_UPDATE_OPEN_FILES   */
+
+
+/* Defined, the file search cache optimization is disabled.  */
+
+/*#define FX_MEDIA_DISABLE_SEARCH_CACHE  */
+
+
+/* Defined, the direct read sector update of cache is disabled.  */
+
+/*#define FX_DISABLE_DIRECT_DATA_READ_CACHE_FILL  */
+
+
+/* Defined, gathering of media statistics is disabled.  */
+
+/*#define FX_MEDIA_STATISTICS_DISABLE  */
+
+
+/* Defined, legacy single open logic for the same file is enabled.  */
+
+/*#define FX_SINGLE_OPEN_LEGACY   */
+
+
+/* Defined, renaming inherits path information.  */
+
+/*#define FX_RENAME_PATH_INHERIT   */
+
+
+/* Defined, local path logic is disabled.  */
+
+/*#define FX_NO_LOCAL_PATH   */
+
+
+/* Defined, FileX is able to access exFAT file system. 
+
+   FileX supports the Microsoft exFAT file system format. 
+   Your use of exFAT technology in your products requires a separate 
+   license from Microsoft. Please see the following link for further 
+   details on exFAT licensing:
+
+   https://www.microsoft.com/en-us/legal/intellectualproperty/mtl/exfat-licensing.aspx
+*/
+
+/* #define FX_ENABLE_EXFAT */
+
+
+/* Define bitmap cache size for exFAT. Size should be minimum one sector size and maximum 4096. 
+   For applications using muliple media devices with varing sector size, the value should be set to the 
+   size of largest sector size */
+
+/* #define FX_EXFAT_MAX_CACHE_SIZE      512 */
+
+
+/* Define FileX internal protection macros.  If FX_SINGLE_THREAD is defined,
+   these protection macros are effectively disabled.  However, for multi-thread
+   uses, the macros are setup to utilize a ThreadX mutex for multiple thread 
+   access control into an open media.  */
+
+/* #define FX_SINGLE_THREAD   */
+
+
+/* Defined, Filex will be used in standalone mode (without ThreadX) */
+
+/* #define FX_STANDALONE_ENABLE */
+
+
+/* Defined, data sector write requests are flushed immediately to the driver.  */
+
+/*#define FX_FAULT_TOLERANT_DATA  */
+
+
+/* Defined, system sector write requests (including FAT and directory entry requests)
+   are flushed immediately to the driver.  */
+
+/*#define FX_FAULT_TOLERANT   */
+
+
+/* Defined, enables 64-bits sector addresses used in I/O driver.  */
+
+/*#define FX_DRIVER_USE_64BIT_LBA   */
+
+
+/* Defined, enables FileX fault tolerant service.  */
+
+/*#define FX_ENABLE_FAULT_TOLERANT   */
+
+
+/* Define byte offset in boot sector where the cluster number of the Fault Tolerant Log file is.
+   Note that this field (byte 116 to 119) is marked as reserved by FAT 12/16/32/exFAT specification. */
+
+/*#define FX_FAULT_TOLERANT_BOOT_INDEX      116 */
+
+/* Below FX_DISABLE_XXX macros can be used for code size optimization required for memory 
+   critical aplications */
+
+/* Defined, error checking is disabled.  */
+
+/*#define FX_DISABLE_ERROR_CHECKING   */
+
+
+/* Defined, cache is disabled.  */
+
+/*#define FX_DISABLE_CACHE   */
+
+
+/* Defined, file close is disabled.  */
+
+/*#define FX_DISABLE_FILE_CLOSE   */
+
+
+/* Defined, fast open is disabled.  */
+
+/*#define FX_DISABLE_FAST_OPEN   */
+
+
+/* Defined, force memory operations are disabled.  */
+
+/*#define FX_DISABLE_FORCE_MEMORY_OPERATION   */
+
+
+/* Defined, build options is disabled.  */
+
+/*#define FX_DISABLE_BUILD_OPTIONS   */
+
+
+/* Defined, one line function is disabled.  */
+
+/*#define FX_DISABLE_ONE_LINE_FUNCTION   */
+
+
+/* Defined, FAT entry refresh is disabled.  */
+
+/*#define FX_DIABLE_FAT_ENTRY_REFRESH   */
+
+
+/* Defined, consecutive detect is disabled.  */
+
+/*#define FX_DISABLE_CONSECUTIVE_DETECT   */
+
+
+#endif
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/inc/fx_utility.h
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/inc/fx_utility.h	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/inc/fx_utility.h	(revision 30)
@@ -0,0 +1,126 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Utility                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  COMPONENT DEFINITION                                   RELEASE        */
+/*                                                                        */
+/*    fx_utility.h                                        PORTABLE C      */
+/*                                                           6.1.10       */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This file defines the FileX Utility component constants, data       */
+/*    definitions, and external references.  It is assumed that fx_api.h  */
+/*    (and fx_port.h) have already been included.                         */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*  01-31-2022     Bhupendra Naphade        Modified comment(s), and      */
+/*                                            changed prototype for       */
+/*                                            exFAT size calculate        */
+/*                                            utility function,           */
+/*                                            resulting in version 6.1.10 */
+/*                                                                        */
+/**************************************************************************/
+
+#ifndef FX_UTILITY_H
+#define FX_UTILITY_H
+
+
+/* Define the internal Utility component function prototypes.  */
+
+UINT    _fx_utility_16_unsigned_read(UCHAR *source_ptr);
+VOID    _fx_utility_16_unsigned_write(UCHAR *dest_ptr, UINT value);
+ULONG   _fx_utility_32_unsigned_read(UCHAR *source_ptr);
+VOID    _fx_utility_32_unsigned_write(UCHAR *dest_ptr, ULONG value);
+ULONG64 _fx_utility_64_unsigned_read(UCHAR *source_ptr);
+VOID    _fx_utility_64_unsigned_write(UCHAR *dest_ptr, ULONG64 value);
+VOID    _fx_utility_memory_copy(UCHAR *source_ptr, UCHAR *dest_ptr, ULONG size);
+VOID    _fx_utility_memory_set(UCHAR *dest_ptr, UCHAR value, ULONG size);
+FX_CACHED_SECTOR
+       *_fx_utility_logical_sector_cache_entry_read(FX_MEDIA *media_ptr, ULONG64 logical_sector, FX_CACHED_SECTOR **previous_cache_entry);
+UINT    _fx_utility_logical_sector_read(FX_MEDIA *media_ptr, ULONG64 logical_sector,
+                                        VOID *buffer_ptr, ULONG sectors, UCHAR sector_type);
+UINT    _fx_utility_logical_sector_write(FX_MEDIA *media_ptr, ULONG64 logical_sector,
+                                         VOID *buffer_ptr, ULONG sectors, UCHAR sector_type);
+UINT    _fx_utility_logical_sector_flush(FX_MEDIA *media_ptr, ULONG64 starting_sector, ULONG64 sectors, UINT invalidate);
+UINT    _fx_utility_FAT_entry_read(FX_MEDIA *media_ptr, ULONG cluster, ULONG *entry_ptr);
+UINT    _fx_utility_FAT_entry_write(FX_MEDIA *media_ptr, ULONG cluster, ULONG next_cluster);
+UINT    _fx_utility_FAT_flush(FX_MEDIA *media_ptr);
+UINT    _fx_utility_FAT_map_flush(FX_MEDIA *media_ptr);
+ULONG   _fx_utility_FAT_sector_get(FX_MEDIA *media_ptr, ULONG cluster);
+UINT    _fx_utility_string_length_get(CHAR *string, UINT max_length);
+
+
+#ifdef FX_ENABLE_EXFAT
+
+/* Define the exFAT Utility function prototypes.  */
+
+UINT _fx_utility_exFAT_cluster_free(FX_MEDIA *media_ptr, UCHAR *work_ptr);
+UINT _fx_utility_exFAT_geometry_check(FX_MEDIA *media_ptr, UCHAR *sector_buffer);
+UINT _fx_utility_exFAT_system_area_checksum_verify(FX_MEDIA_PTR media_ptr,
+                                                   UCHAR *sector_buffer, ULONG boot_sector_offset,
+                                                   ULONG *calculated_checksum);
+VOID _fx_utility_exFAT_size_calculate(UINT bytes_per_sector, ULONG boundary_unit, ULONG64 size_in_sectors, ULONG sectors_per_cluster,
+                                      ULONG *sectors_per_fat_ptr, ULONG *fat_offset_ptr, ULONG *cluster_heap_offset_ptr);
+UINT _fx_utility_exFAT_system_area_format(FX_MEDIA *media_ptr, ULONG boundary_unit,
+                                          ULONG *system_area_checksum_ptr, UCHAR *memory_ptr, UINT memory_size);
+UINT _fx_utility_exFAT_system_sector_write(FX_MEDIA *media_ptr, UCHAR *data_buffer, ULONG64 logical_sector,
+                                           ULONG sector_count, ULONG sector_type);
+UINT _fx_utility_exFAT_system_area_checksum_write(FX_MEDIA *media_ptr, UCHAR *sector_buffer,
+                                                  ULONG *system_area_checksum_ptr);
+
+
+/* Define the exFAT utility function prototypes.  */
+
+UINT   _fx_utility_exFAT_bitmap_start_sector_get(FX_MEDIA *media_ptr, ULONG *start_sector);
+UINT   _fx_utility_exFAT_bitmap_cache_update(FX_MEDIA *media_ptr, ULONG cluster);
+UINT   _fx_utility_exFAT_bitmap_flush(FX_MEDIA *media_ptr);
+UINT   _fx_utility_exFAT_bitmap_initialize(FX_MEDIA *media_ptr);
+UINT   _fx_utility_exFAT_bitmap_cache_prepare(FX_MEDIA *media_ptr, ULONG cluster);
+UINT   _fx_utility_exFAT_cluster_state_get(FX_MEDIA *media_ptr, ULONG cluster, UCHAR *cluster_state);
+UINT   _fx_utility_exFAT_cluster_state_set(FX_MEDIA *media_ptr, ULONG cluster, UCHAR new_cluster_state);
+UINT   _fx_utility_exFAT_bitmap_free_cluster_find(FX_MEDIA *media_ptr, ULONG start, ULONG *free_cluster);
+USHORT _fx_utility_exFAT_upcase_get(USHORT character);
+USHORT _fx_utility_exFAT_name_hash_get(CHAR *name);
+USHORT _fx_utility_exFAT_unicode_name_hash_get(CHAR *unicode_name, ULONG unicode_length);
+USHORT _fx_utility_exFAT_upcase_get(USHORT character);
+UINT   _fx_utility_absolute_path_get(CHAR *base_path, CHAR *new_path, CHAR *absolute_path);
+UINT   _fx_utility_token_length_get(CHAR *path);
+UINT   _fx_utility_exFAT_allocate_new_cluster(FX_MEDIA *media_ptr, FX_DIR_ENTRY *directory_ptr, ULONG *last_cluster, ULONG *cluster);
+
+
+#endif /* FX_ENABLE_EXFAT */
+
+
+#endif
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_attributes_read.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_attributes_read.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_attributes_read.c	(revision 30)
@@ -0,0 +1,156 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_directory.h"
+#include "fx_file.h"
+#include "fx_utility.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_directory_attributes_read                       PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function first attempts to find the specified directory.  If   */
+/*    found, the attribute read request is valid and the directory entry  */
+/*    will be read in order to pickup the directory's attributes.         */
+/*    Otherwise, if the directory is not found, the appropriate error     */
+/*    code is returned to the caller.                                     */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    directory_name                        Directory name pointer        */
+/*    attributes_ptr                        Return attributes pointer     */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_search                  Search for the file name in   */
+/*                                          the directory structure       */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_directory_attributes_read(FX_MEDIA *media_ptr, CHAR *directory_name, UINT *attributes_ptr)
+{
+
+UINT                   status;
+FX_DIR_ENTRY           dir_entry;
+
+#ifdef TX_ENABLE_EVENT_TRACE
+TX_TRACE_BUFFER_ENTRY *trace_event;
+ULONG                  trace_timestamp;
+#endif
+
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of times this service has been called.  */
+    media_ptr -> fx_media_directory_attributes_reads++;
+#endif
+
+    /* Setup pointer to media name buffer.  */
+    dir_entry.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
+
+    /* Clear the short name string.  */
+    dir_entry.fx_dir_entry_short_name[0] =  0;
+
+    /* Check the media to make sure it is open.  */
+    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
+    {
+
+        /* Return the media not opened error.  */
+        return(FX_MEDIA_NOT_OPEN);
+    }
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_DIRECTORY_ATTRIBUTES_READ, media_ptr, directory_name, 0, 0, FX_TRACE_DIRECTORY_EVENTS, &trace_event, &trace_timestamp)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+    /* Search the system for the supplied file name.  */
+    status =  _fx_directory_search(media_ptr, directory_name, &dir_entry, FX_NULL, FX_NULL);
+
+    /* Determine if the search was successful.  */
+    if (status != FX_SUCCESS)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the error code.  */
+        return(status);
+    }
+
+    /* Check to make sure the found entry is a file.  */
+    if ((dir_entry.fx_dir_entry_attributes & (UCHAR)(FX_DIRECTORY)) == 0)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the not a file error code.  */
+        return(FX_NOT_DIRECTORY);
+    }
+
+    /* Place the current attributes into the destination.  */
+    *attributes_ptr =  (UINT)dir_entry.fx_dir_entry_attributes;
+
+    /* Update the trace event with the attributes read.  */
+    FX_TRACE_EVENT_UPDATE(trace_event, trace_timestamp, FX_TRACE_DIRECTORY_ATTRIBUTES_READ, 0, 0, dir_entry.fx_dir_entry_attributes, 0)
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* File attribute read is complete, return successful status.  */
+    return(FX_SUCCESS);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_attributes_set.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_attributes_set.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_attributes_set.c	(revision 30)
@@ -0,0 +1,205 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_directory.h"
+#include "fx_file.h"
+#include "fx_utility.h"
+#ifdef FX_ENABLE_FAULT_TOLERANT
+#include "fx_fault_tolerant.h"
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_directory_attributes_set                        PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function first attempts to find the specified directory.  If   */
+/*    found, the attribute set request is valid and the directory will    */
+/*    be modified with the new attributes.  Otherwise, if the directory   */
+/*    is not found, the appropriate error code is returned to the caller. */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    directory_name                        Directory name pointer        */
+/*    attributes                            New dir attributes            */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_entry_write             Write the new directory entry */
+/*    _fx_directory_search                  Search for the file name in   */
+/*                                            the directory structure     */
+/*    _fx_fault_tolerant_transaction_start  Start fault tolerant          */
+/*                                            transaction                 */
+/*    _fx_fault_tolerant_transaction_end    End fault tolerant transaction*/
+/*    _fx_fault_tolerant_recover            Recover FAT chain             */
+/*    _fx_fault_tolerant_reset_log_file     Reset the log file            */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_directory_attributes_set(FX_MEDIA *media_ptr, CHAR *directory_name, UINT attributes)
+{
+
+UINT         status;
+FX_DIR_ENTRY dir_entry;
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of times this service has been called.  */
+    media_ptr -> fx_media_directory_attributes_sets++;
+#endif
+
+    /* Setup pointer to media name buffer.  */
+    dir_entry.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
+
+    /* Clear the short name string.  */
+    dir_entry.fx_dir_entry_short_name[0] =  0;
+
+    /* Check the media to make sure it is open.  */
+    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
+    {
+
+        /* Return the media not opened error.  */
+        return(FX_MEDIA_NOT_OPEN);
+    }
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_DIRECTORY_ATTRIBUTES_SET, media_ptr, directory_name, attributes, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+    /* Check for write protect at the media level (set by driver).  */
+    if (media_ptr -> fx_media_driver_write_protect)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return write protect error.  */
+        return(FX_WRITE_PROTECT);
+    }
+
+    /* Search the system for the supplied file name.  */
+    status =  _fx_directory_search(media_ptr, directory_name, &dir_entry, FX_NULL, FX_NULL);
+
+    /* Determine if the search was successful.  */
+    if (status != FX_SUCCESS)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the error code.  */
+        return(status);
+    }
+
+    /* Check to make sure the found entry is a directory.  */
+    if ((dir_entry.fx_dir_entry_attributes & (UCHAR)(FX_DIRECTORY)) == 0)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the not a file error code.  */
+        return(FX_NOT_DIRECTORY);
+    }
+
+    /* Place the new attributes in the directory entry. Make sure that the
+       directory bit of the attributes is never changed. */
+    dir_entry.fx_dir_entry_attributes =  (UCHAR)(attributes | FX_DIRECTORY);
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    /* Start transaction. */
+    _fx_fault_tolerant_transaction_start(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Now write out the directory entry.  */
+#ifdef FX_ENABLE_EXFAT
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+
+        status = _fx_directory_exFAT_entry_write(media_ptr, &dir_entry, UPDATE_FILE);
+    }
+    else
+    {
+#endif /* FX_ENABLE_EXFAT */
+
+        status = _fx_directory_entry_write(media_ptr, &dir_entry);
+
+#ifdef FX_ENABLE_EXFAT
+    }
+#endif /* FX_ENABLE_EXFAT */
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    /* Check for a bad status.  If the return status is not FX_SUCCESS, finish
+       the fault tolerant transaction without flushing the logs. */
+    if (status != FX_SUCCESS)
+    {
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+    }
+    else
+    {
+
+        /* End transaction. */
+        status = _fx_fault_tolerant_transaction_end(media_ptr);
+    }
+
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* File attribute set is complete, return status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_create.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_create.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_create.c	(revision 30)
@@ -0,0 +1,904 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_directory.h"
+#include "fx_file.h"
+#include "fx_utility.h"
+#ifdef FX_ENABLE_FAULT_TOLERANT
+#include "fx_fault_tolerant.h"
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_directory_create                                PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function first attempts to find the specified directory.       */
+/*    If found, the create request is invalid and an error is returned    */
+/*    to the caller.  After the file name verification is made, a search  */
+/*    for a free directory entry will be made.  If nothing is available,  */
+/*    an error will be returned to the caller.  Otherwise, if all is      */
+/*    okay, an empty directory will be created.                           */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    directory_name                        Directory name                */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_entry_write             Write the new directory entry */
+/*    _fx_directory_name_extract            Pickup next part of name      */
+/*    _fx_directory_search                  Search for the file name in   */
+/*                                          the directory structure       */
+/*    _fx_directory_free_search             Search for a free directory   */
+/*                                            entry                       */
+/*    _fx_utility_exFAT_bitmap_free_cluster_find                          */
+/*                                            Find exFAT free cluster     */
+/*    _fx_utility_exFAT_cluster_state_set   Set cluster state             */
+/*    _fx_utility_FAT_flush                 Flush written FAT entries     */
+/*    _fx_utility_FAT_entry_read            Read a FAT entry              */
+/*    _fx_utility_FAT_entry_write           Write a FAT entry             */
+/*    _fx_utility_logical_sector_flush      Flush the written log sector  */
+/*    _fx_utility_logical_sector_read       Read logical sector           */
+/*    _fx_fault_tolerant_transaction_start  Start fault tolerant          */
+/*                                            transaction                 */
+/*    _fx_fault_tolerant_transaction_end    End fault tolerant transaction*/
+/*    _fx_fault_tolerant_recover            Recover FAT chain             */
+/*    _fx_fault_tolerant_reset_log_file     Reset the log file            */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_directory_create(FX_MEDIA *media_ptr, CHAR *directory_name)
+{
+
+UINT         status;
+ULONG        FAT_index;
+ULONG        FAT_value;
+UINT         sectors;
+ULONG        total_clusters;
+CHAR        *work_ptr;
+ULONG64      logical_sector;
+ULONG        i;
+FX_DIR_ENTRY dir_entry;
+FX_DIR_ENTRY sub_dir_entry;
+FX_DIR_ENTRY search_directory;
+
+#ifdef FX_ENABLE_EXFAT
+ULONG64      dir_size;
+#endif /* FX_ENABLE_EXFAT */
+FX_INT_SAVE_AREA
+
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of times this service has been called.  */
+    media_ptr -> fx_media_directory_creates++;
+#endif
+
+    /* Determine if the supplied name is less than the maximum supported name size. The
+       maximum name (FX_MAX_LONG_NAME_LEN) is defined in fx_api.h.  */
+    i =  0;
+    work_ptr =  (CHAR *)directory_name;
+    while (*work_ptr && (i < FX_MAX_LONG_NAME_LEN))
+    {
+
+        /* Determine if the character designates a new path.  */
+        if ((*work_ptr == '\\') || (*work_ptr == '/'))
+        {
+            /* Yes, reset the name size.  */
+            i =  0;
+        }
+        /* Check for leading spaces.  */
+        else if ((*work_ptr != ' ') || (i != 0))
+        {
+
+            /* No leading spaces, increment the name size.  */
+            i++;
+        }
+
+        /* Move to the next character.  */
+        work_ptr++;
+    }
+
+    /* Determine if the supplied name is valid.  */
+    if ((i == 0) || (i >= FX_MAX_LONG_NAME_LEN))
+    {
+
+        /* Return an invalid name value.  */
+        return(FX_INVALID_NAME);
+    }
+
+    /* Setup pointer to media name buffer.  */
+    dir_entry.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
+
+    /* Setup search directory pointer to another media name buffer.  */
+    search_directory.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN * 2;
+
+    /* Clear the short name string.  */
+    dir_entry.fx_dir_entry_short_name[0] =  0;
+
+    /* Clear the search short name string.  */
+    search_directory.fx_dir_entry_short_name[0] =  0;
+
+    /* Check the media to make sure it is open.  */
+    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
+    {
+
+        /* Return the media not opened error.  */
+        return(FX_MEDIA_NOT_OPEN);
+    }
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_DIRECTORY_CREATE, media_ptr, directory_name, 0, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+    /* Check for write protect at the media level (set by driver).  */
+    if (media_ptr -> fx_media_driver_write_protect)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return write protect error.  */
+        return(FX_WRITE_PROTECT);
+    }
+
+    /* Make sure there is at least one cluster remaining for the new file.  */
+    if (!media_ptr -> fx_media_available_clusters)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return a no-space error.  */
+        return(FX_NO_MORE_SPACE);
+    }
+
+    /* Search the system for the supplied directory name.  */
+    status =  _fx_directory_search(media_ptr, directory_name, &dir_entry, &search_directory, &work_ptr);
+
+    /* Determine if the search was successful.  */
+    if (status == FX_SUCCESS)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Directory found - Return the error code.  */
+        return(FX_ALREADY_CREATED);
+    }
+
+    /* Determine if there is anything left after the name.  */
+    if (_fx_directory_name_extract(work_ptr, &dir_entry.fx_dir_entry_name[0]))
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Extra information after the file name, return an invalid name
+           error.  */
+        return(FX_INVALID_PATH);
+    }
+
+#ifdef FX_ENABLE_EXFAT
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+        if (((dir_entry.fx_dir_entry_name[0] == '.') && (dir_entry.fx_dir_entry_name[1] == 0)) ||
+            ((dir_entry.fx_dir_entry_name[0] == '.') && (dir_entry.fx_dir_entry_name[1] == '.') && (dir_entry.fx_dir_entry_name[2] == 0)))
+        {
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* We don't need '.' or '..' dirs for exFAT.  */
+            return(FX_ALREADY_CREATED);
+        }
+    }
+
+    /* Save the directory entry size.  */
+    dir_size = search_directory.fx_dir_entry_file_size;
+#endif /* FX_ENABLE_EXFAT */
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    /* Start transaction. */
+    _fx_fault_tolerant_transaction_start(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Find a free slot for the new directory.  */
+    status =  _fx_directory_free_search(media_ptr, &search_directory, &dir_entry);
+
+    /* Determine if the search was successful.  */
+    if (status != FX_SUCCESS)
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the error code.  */
+        return(status);
+    }
+
+    /* Now allocate a cluster for our new sub-directory entry.  */
+#ifdef FX_ENABLE_EXFAT
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+
+        /* Find free cluster from exFAT media.  */
+        status = _fx_utility_exFAT_bitmap_free_cluster_find(media_ptr,
+                                                            media_ptr -> fx_media_cluster_search_start,
+                                                            &FAT_index);
+
+        /* Check for a bad status.  */
+        if (status != FX_SUCCESS)
+        {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+            FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* Return the bad status.  */
+            return(status);
+        }
+    }
+    else
+    {
+#endif /* FX_ENABLE_EXFAT */
+
+        FAT_index    =      media_ptr -> fx_media_cluster_search_start;
+        total_clusters =    media_ptr -> fx_media_total_clusters;
+
+        /* Loop to find the first available cluster.  */
+        do
+        {
+
+            /* Make sure we don't go past the FAT table.  */
+            if (!total_clusters)
+            {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* Something is wrong with the media - the desired clusters were
+                   not found in the FAT table.  */
+                return(FX_NO_MORE_SPACE);
+            }
+
+            /* Read FAT entry.  */
+            status =  _fx_utility_FAT_entry_read(media_ptr, FAT_index, &FAT_value);
+
+            /* Check for a bad status.  */
+            if (status != FX_SUCCESS)
+            {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* Return the bad status.  */
+                return(status);
+            }
+
+            /* Decrement the total cluster count.  */
+            total_clusters--;
+
+            /* Determine if the FAT entry is free.  */
+            if (FAT_value == FX_FREE_CLUSTER)
+            {
+
+                /* Move cluster search pointer forward.  */
+                media_ptr -> fx_media_cluster_search_start =  FAT_index + 1;
+
+                /* Determine if this needs to be wrapped.  */
+                if (media_ptr -> fx_media_cluster_search_start >= (media_ptr -> fx_media_total_clusters + FX_FAT_ENTRY_START))
+                {
+
+                    /* Wrap the search to the beginning FAT entry.  */
+                    media_ptr -> fx_media_cluster_search_start =  FX_FAT_ENTRY_START;
+                }
+
+                /* Break this loop.  */
+                break;
+            }
+            else
+            {
+
+                /* FAT entry is not free... Advance the FAT index.  */
+                FAT_index++;
+
+                /* Determine if we need to wrap the FAT index around.  */
+                if (FAT_index >= (media_ptr -> fx_media_total_clusters + FX_FAT_ENTRY_START))
+                {
+
+                    /* Wrap the search to the beginning FAT entry.  */
+                    FAT_index =  FX_FAT_ENTRY_START;
+                }
+            }
+        } while (FX_TRUE);
+#ifdef FX_ENABLE_EXFAT
+    }
+#endif /* FX_ENABLE_EXFAT */
+
+    /* Decrease the number of available clusters for the media.  */
+    media_ptr -> fx_media_available_clusters--;
+
+    /* Defer the writing of the FAT entry until the directory's first sector
+       has been properly written. If a power loss occurs prior to writing
+       the FAT entry, it will not result in a lost cluster.  */
+
+    /* Populate the directory entry.  */
+
+    /* Isolate the file name.  */
+    _fx_directory_name_extract(work_ptr, &dir_entry.fx_dir_entry_name[0]);
+
+    /* Lockout interrupts for time/date access.  */
+    FX_DISABLE_INTS
+
+    /* Set time and date stamps.  */
+    dir_entry.fx_dir_entry_time =  _fx_system_time;
+    dir_entry.fx_dir_entry_date =  _fx_system_date;
+
+    /* Restore interrupts.  */
+    FX_RESTORE_INTS
+
+    /* Set the attributes for the file.  */
+    dir_entry.fx_dir_entry_attributes =  FX_DIRECTORY;
+
+#ifdef FX_ENABLE_EXFAT
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+        dir_entry.fx_dir_entry_file_size =
+            media_ptr -> fx_media_sectors_per_cluster * media_ptr -> fx_media_bytes_per_sector;
+        dir_entry.fx_dir_entry_available_file_size = dir_entry.fx_dir_entry_file_size;
+
+        /* Don't use FAT by default.  */
+        dir_entry.fx_dir_entry_dont_use_fat = (CHAR)((INT)((search_directory.fx_dir_entry_dont_use_fat & 1) << 1) | 1);
+    }
+    else
+    {
+#endif /* FX_ENABLE_EXFAT */
+
+        /* Set file size to 0. */
+        dir_entry.fx_dir_entry_file_size =  0;
+
+#ifdef FX_ENABLE_EXFAT
+    }
+#endif /* FX_ENABLE_EXFAT */
+
+    /* Set the cluster to EOF.  */
+    dir_entry.fx_dir_entry_cluster =    FAT_index;
+
+    /* Is there a leading dot?  */
+    if (dir_entry.fx_dir_entry_name[0] == '.')
+    {
+
+        /* Yes, toggle the hidden attribute bit.  */
+        dir_entry.fx_dir_entry_attributes |=  FX_HIDDEN;
+    }
+
+    /* In previous versions, the new directory was written here.  It
+       is now at the bottom of the file - after the FAT and the initial
+       sub-directory is written out.  This makes the directory create
+       more fault tolerant.  */
+
+    /* Calculate the first sector of the sub-directory file.  */
+    logical_sector =    ((ULONG) media_ptr -> fx_media_data_sector_start) +
+                         (((ULONG64) FAT_index - FX_FAT_ENTRY_START) *
+                         ((ULONG) media_ptr -> fx_media_sectors_per_cluster));
+
+    /* Pickup the number of sectors for the initial sub-directory cluster.  */
+    sectors =  media_ptr -> fx_media_sectors_per_cluster;
+
+    /* Read the first logical sector associated with the allocated
+       cluster.  */
+    status =  _fx_utility_logical_sector_read(media_ptr, logical_sector,
+                                              media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
+
+    /* Determine if an error occurred.  */
+    if (status != FX_SUCCESS)
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return error code.  */
+        return(status);
+    }
+
+    /* Clear the entire first sector of the new sub-directory cluster.  */
+    work_ptr =  (CHAR *)media_ptr -> fx_media_memory_buffer;
+    i =  0;
+    while (i < media_ptr -> fx_media_bytes_per_sector)
+    {
+
+        /* Clear 4 bytes.  */
+        *((ULONG *)work_ptr) =  (ULONG)0;
+
+        /* Increment pointer.  */
+        work_ptr =  work_ptr + sizeof(ULONG);
+
+        /* Increment counter.  */
+        i =  i + (ULONG)sizeof(ULONG);
+    }
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    if (media_ptr -> fx_media_fault_tolerant_enabled == FX_TRUE)
+    {
+
+        /* Write back. */
+        status =  _fx_utility_logical_sector_write(media_ptr, logical_sector,
+                                                   media_ptr -> fx_media_memory_buffer, (ULONG)1, FX_DIRECTORY_SECTOR);
+
+        /* Determine if an error occurred.  */
+        if (status != FX_SUCCESS)
+        {
+            FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* Return error code.  */
+            return(status);
+        }
+
+        /* Force flush the internal logical sector cache.  */
+        status =  _fx_utility_logical_sector_flush(media_ptr, logical_sector, sectors, FX_TRUE);
+
+        /* Determine if the write was successful.  */
+        if (status != FX_SUCCESS)
+        {
+            FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* Return the error code.  */
+            return(status);
+        }
+    }
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Determine if there are more sectors to clear in the first cluster of the new
+       sub-directory.  */
+    if (sectors > 1)
+    {
+
+        /* Yes, invalidate all cached sectors that are contained in the newly allocated first
+           cluster of the directory.  */
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        if (media_ptr -> fx_media_fault_tolerant_enabled == FX_FALSE)
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+        {
+
+            /* Flush the internal logical sector cache.  */
+            status =  _fx_utility_logical_sector_flush(media_ptr, logical_sector + 1, ((ULONG64)(sectors - 1)), FX_TRUE);
+
+            /* Determine if the write was successful.  */
+            if (status != FX_SUCCESS)
+            {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* Return the error code.  */
+                return(status);
+            }
+        }
+
+        /* Clear all additional sectors of new sub-directory.  */
+        sectors--;
+        while (sectors)
+        {
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+            /* Increment the number of driver write sector(s) requests.  */
+            media_ptr -> fx_media_driver_write_requests++;
+#endif
+
+            /* Build Write request to the driver.  */
+            media_ptr -> fx_media_driver_request =          FX_DRIVER_WRITE;
+            media_ptr -> fx_media_driver_status =           FX_IO_ERROR;
+            media_ptr -> fx_media_driver_buffer =           media_ptr -> fx_media_memory_buffer;
+#ifdef FX_DRIVER_USE_64BIT_LBA
+            media_ptr -> fx_media_driver_logical_sector =   logical_sector + ((ULONG)sectors);
+#else
+            media_ptr -> fx_media_driver_logical_sector =   (ULONG)logical_sector + ((ULONG)sectors);
+#endif
+            media_ptr -> fx_media_driver_sectors =          1;
+            media_ptr -> fx_media_driver_sector_type =      FX_DIRECTORY_SECTOR;
+
+            /* Set the system write flag since we are writing a directory sector.  */
+            media_ptr -> fx_media_driver_system_write =  FX_TRUE;
+
+            /* If trace is enabled, insert this event into the trace buffer.  */
+            FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_WRITE, media_ptr, ((ULONG)logical_sector) + ((ULONG)sectors), 1, media_ptr -> fx_media_memory_buffer, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+            /* Invoke the driver to write the sector.  */
+                (media_ptr -> fx_media_driver_entry) (media_ptr);
+
+            /* Clear the system write flag.  */
+            media_ptr -> fx_media_driver_system_write =  FX_FALSE;
+
+            /* Determine if an error occurred.  */
+            if (media_ptr -> fx_media_driver_status != FX_SUCCESS)
+            {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* Return error code.  */
+                return(media_ptr -> fx_media_driver_status);
+            }
+
+            /* Decrease the number of sectors to clear.  */
+            sectors--;
+        }
+    }
+
+#ifdef FX_ENABLE_EXFAT
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+
+        /* Build Write request to the driver.  */
+        media_ptr -> fx_media_driver_request =          FX_DRIVER_WRITE;
+        media_ptr -> fx_media_driver_status =           FX_IO_ERROR;
+        media_ptr -> fx_media_driver_buffer =           media_ptr -> fx_media_memory_buffer;
+        media_ptr -> fx_media_driver_logical_sector =   (ULONG)logical_sector;
+        media_ptr -> fx_media_driver_sectors =          1;
+        media_ptr -> fx_media_driver_sector_type =      FX_DIRECTORY_SECTOR;
+
+        /* Set the system write flag since we are writing a directory sector.  */
+        media_ptr -> fx_media_driver_system_write =  FX_TRUE;
+
+        /* If trace is enabled, insert this event into the trace buffer.  */
+        FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_WRITE, media_ptr, ((ULONG)logical_sector) + ((ULONG)sectors), 1, media_ptr -> fx_media_memory_buffer, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+        /* Invoke the driver to write the sector.  */
+            (media_ptr -> fx_media_driver_entry) (media_ptr);
+
+        /* Clear the system write flag.  */
+        media_ptr -> fx_media_driver_system_write =  FX_FALSE;
+
+        /* Determine if an error occurred.  */
+        if (media_ptr -> fx_media_driver_status != FX_SUCCESS)
+        {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+            FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* Return error code.  */
+            return(media_ptr -> fx_media_driver_status);
+        }
+
+        /* Mark the cluster as used.  */
+        status = _fx_utility_exFAT_cluster_state_set(media_ptr, FAT_index, FX_EXFAT_BITMAP_CLUSTER_OCCUPIED);
+
+        /* Check for a bad status.  */
+        if (status != FX_SUCCESS)
+        {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+            FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* Return the bad status.  */
+            return(status);
+        }
+
+        /* Move cluster search pointer forward. */
+        media_ptr -> fx_media_cluster_search_start = FAT_index + 1;
+
+        /* Determine if this needs to be wrapped. */
+        if (media_ptr -> fx_media_cluster_search_start >= media_ptr -> fx_media_total_clusters + FX_FAT_ENTRY_START)
+        {
+
+            /* Wrap the search to the beginning FAT entry. */
+            media_ptr -> fx_media_cluster_search_start = FX_FAT_ENTRY_START;
+        }
+
+        if (search_directory.fx_dir_entry_name[0])
+        {
+
+            /* Not root directory.  */
+            /* Copy the date and time from the actual sub-directory.  */
+            search_directory.fx_dir_entry_time = dir_entry.fx_dir_entry_time;
+            search_directory.fx_dir_entry_date = dir_entry.fx_dir_entry_date;
+
+            /* Check if the directory size has changed.  */
+            if (search_directory.fx_dir_entry_file_size == dir_size)
+            {
+
+                /* Not changed, we need only update time stamps.  */
+                status = _fx_directory_exFAT_entry_write(media_ptr, &search_directory, UPDATE_FILE);
+            }
+            else
+            {
+
+                /* Directory size changed, update time stamps and the stream size.  */
+                status = _fx_directory_exFAT_entry_write(media_ptr, &search_directory, UPDATE_STREAM);
+            }
+
+            /* Check for a bad status.  */
+            if (status != FX_SUCCESS)
+            {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* Return the bad status.  */
+                return(status);
+            }
+        }
+    }
+    else
+    {
+#endif /* FX_ENABLE_EXFAT */
+
+        /* Now setup the first sector with the initial sub-directory information.  */
+
+        /* Copy the base directory entry to the sub-directory entry.  */
+        sub_dir_entry =  dir_entry;
+
+        /* Setup pointer to media name buffer.  */
+        sub_dir_entry.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer + (FX_MAX_LONG_NAME_LEN * 3);
+
+        /* Set the directory entry name to all blanks.  */
+        work_ptr =  &sub_dir_entry.fx_dir_entry_name[0];
+        for (i = 0; i < (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE); i++)
+        {
+            *work_ptr++ = ' ';
+        }
+
+        sub_dir_entry.fx_dir_entry_long_name_present = 0;
+
+        /* Now build the "." directory entry.  */
+        sub_dir_entry.fx_dir_entry_name[0] =        '.';
+        sub_dir_entry.fx_dir_entry_name[1] =        0;
+        sub_dir_entry.fx_dir_entry_log_sector =     logical_sector;
+        sub_dir_entry.fx_dir_entry_byte_offset =    0;
+
+        /* Write the directory's first entry.  */
+        status =  _fx_directory_entry_write(media_ptr, &sub_dir_entry);
+
+        /* Check for error condition.  */
+        if (status != FX_SUCCESS)
+        {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+            FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* Return error status.  */
+            return(status);
+        }
+
+        /* Now build the ".." directory entry.  */
+
+        /* Determine if the search directory is the root.  */
+        if (search_directory.fx_dir_entry_name[0])
+        {
+
+            /* Previous directory is not the root directory.  */
+
+            /* Copy into the working directory entry.  */
+            sub_dir_entry =  search_directory;
+
+            /* Copy the date and time from the actual sub-directory.  */
+            sub_dir_entry.fx_dir_entry_time =  dir_entry.fx_dir_entry_time;
+            sub_dir_entry.fx_dir_entry_date =  dir_entry.fx_dir_entry_date;
+
+            /* Adjust pointer to media name buffer.  */
+            sub_dir_entry.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer + (FX_MAX_LONG_NAME_LEN * 3);
+
+            /* Change the name to ".."  */
+            work_ptr =  &sub_dir_entry.fx_dir_entry_name[0];
+            for (i = 0; i < (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE); i++)
+            {
+                *work_ptr++ = ' ';
+            }
+
+            sub_dir_entry.fx_dir_entry_name[0] =  '.';
+            sub_dir_entry.fx_dir_entry_name[1] =  '.';
+            sub_dir_entry.fx_dir_entry_name[2] =   0;
+
+            sub_dir_entry.fx_dir_entry_long_name_present = 0;
+
+            /* Set file size to 0. */
+            sub_dir_entry.fx_dir_entry_file_size =  0;
+
+            /* Change the logical sector for this entry.  */
+            sub_dir_entry.fx_dir_entry_log_sector =  logical_sector;
+        }
+        else
+        {
+
+            /* Just modify the current directory since the parent
+               directory is the root.  */
+            sub_dir_entry.fx_dir_entry_name[1] =  '.';
+            sub_dir_entry.fx_dir_entry_name[2] =   0;
+
+            /* Clear the cluster to indicate the root directory.  */
+            sub_dir_entry.fx_dir_entry_cluster =  0;
+        }
+
+        /* Setup the byte offset.  */
+        sub_dir_entry.fx_dir_entry_byte_offset =  FX_DIR_ENTRY_SIZE;
+
+        /* Write the directory's second entry.  */
+        status =  _fx_directory_entry_write(media_ptr, &sub_dir_entry);
+
+        /* Check for error condition.  */
+        if (status != FX_SUCCESS)
+        {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+            FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* Return error status.  */
+            return(status);
+        }
+
+        /* Write an EOF in the found FAT entry.  */
+        status =  _fx_utility_FAT_entry_write(media_ptr, FAT_index, media_ptr -> fx_media_fat_last);
+
+        /* Check for a bad status.  */
+        if (status != FX_SUCCESS)
+        {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+            FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* Return the bad status.  */
+            return(status);
+        }
+
+#ifdef FX_ENABLE_EXFAT
+    }
+#endif /* FX_ENABLE_EXFAT */
+
+#ifdef FX_FAULT_TOLERANT
+
+    /* Flush the cached individual FAT entries */
+    _fx_utility_FAT_flush(media_ptr);
+#endif
+
+    /* Now write out the new directory entry.  */
+#ifdef FX_ENABLE_EXFAT
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+        status = _fx_directory_exFAT_entry_write(media_ptr, &dir_entry, UPDATE_FULL);
+    }
+    else
+    {
+#endif /* FX_ENABLE_EXFAT */
+
+        status = _fx_directory_entry_write(media_ptr, &dir_entry);
+#ifdef FX_ENABLE_EXFAT
+    }
+#endif /* FX_ENABLE_EXFAT */
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    /* Check for a bad status.  */
+    if (status != FX_SUCCESS)
+    {
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the bad status.  */
+        return(status);
+    }
+
+    /* End transaction. */
+    status = _fx_fault_tolerant_transaction_end(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* Directory create is complete, return status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_default_get.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_default_get.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_default_get.c	(revision 30)
@@ -0,0 +1,106 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_directory.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_directory_default_get                           PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function returns the pointer of the last path provided to the  */
+/*    fx_directory_default_set function.                                  */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    return_path_name                      Destination string pointer    */
+/*                                            address                     */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_directory_default_get(FX_MEDIA *media_ptr, CHAR **return_path_name)
+{
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of times this service has been called.  */
+    media_ptr -> fx_media_directory_default_gets++;
+#endif
+
+    /* Check the media to make sure it is open.  */
+    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
+    {
+
+        /* Return the media not opened error.  */
+        return(FX_MEDIA_NOT_OPEN);
+    }
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_DIRECTORY_DEFAULT_GET, media_ptr, return_path_name, 0, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+    /* Return the last pointer supplied to the set default directory function.  */
+    *return_path_name = media_ptr -> fx_media_default_path.fx_path_string;
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* Return successful status.  */
+    return(FX_SUCCESS);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_default_get_copy.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_default_get_copy.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_default_get_copy.c	(revision 30)
@@ -0,0 +1,114 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_directory.h"
+#include "fx_utility.h"
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_directory_default_get_copy                      PORTABLE C      */
+/*                                                           6.1.6        */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function copies the last path provided to the                  */
+/*    fx_directory_default_set function into the specified buffer.        */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    return_path_name_buffer               Destination buffer for name   */
+/*    return_path_name_buffer_size          Size of buffer pointed to by  */
+/*                                            return_path_name_buffer     */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s), verified */
+/*                                            memcpy usage,               */
+/*                                            resulting in version 6.1    */
+/*  04-02-2021     William E. Lamie         Modified comment(s), verified */
+/*                                            memcpy usage,               */
+/*                                            resulting in version 6.1.6  */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_directory_default_get_copy(FX_MEDIA *media_ptr, CHAR *return_path_name_buffer, UINT return_path_name_buffer_size)
+{
+
+UINT    status;
+CHAR    *return_path_name;
+UINT    path_name_length_with_null_terminator;
+
+
+    /* Get the pointer to the path.  */
+    status =  _fx_directory_default_get(media_ptr, &return_path_name);
+    if (status == FX_SUCCESS)
+    {
+
+        /* Get the length of the path.  */
+        path_name_length_with_null_terminator =  _fx_utility_string_length_get(return_path_name, FX_MAXIMUM_PATH) + 1;
+
+        /* Can it fit in the user's buffer? */
+        if (path_name_length_with_null_terminator <= return_path_name_buffer_size)
+        {
+
+            /* Copy the path name into the user's buffer.  */
+            _fx_utility_memory_copy((UCHAR *) return_path_name, (UCHAR *) return_path_name_buffer, path_name_length_with_null_terminator); /* Use case of memcpy is verified. */
+        }
+        else
+        {
+
+            /* Buffer is too small. Return error.  */
+            return(FX_BUFFER_ERROR);
+        }
+
+    }
+
+    /* Return successful status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_default_set.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_default_set.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_default_set.c	(revision 30)
@@ -0,0 +1,453 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_file.h"
+#include "fx_utility.h"
+#include "fx_directory.h"
+#ifdef FX_ENABLE_EXFAT
+#include "fx_directory_exFAT.h"
+#endif /* FX_ENABLE_EXFAT */
+
+#ifndef FX_NO_LOCAL_PATH
+FX_LOCAL_PATH_SETUP
+#endif
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_directory_default_set                           PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function sets the default directory of the media to the path   */
+/*    specified by the caller.  If this path is not found, an error code  */
+/*    is returned.                                                        */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    new_path_name                         New path to set current       */
+/*                                            working directory to        */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_search                  Search for the directory name */
+/*                                          in the directory structure    */
+/*    _fx_utility_absolute_path_get         Get absolute path             */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_directory_default_set(FX_MEDIA *media_ptr, CHAR *new_path_name)
+{
+
+UINT         status;
+FX_DIR_ENTRY dir_entry;
+CHAR        *path_string_ptr;
+UINT         path_string_capacity;
+FX_PATH     *path_ptr;
+UINT         i;
+
+#ifdef FX_ENABLE_EXFAT
+CHAR         abs_str[FX_MAXIMUM_PATH]; /* TODO: possible will be better to use dynamic memory for exFAT only.  */
+#endif /* FX_ENABLE_EXFAT */
+
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of times this service has been called.  */
+    media_ptr -> fx_media_directory_default_sets++;
+#endif
+
+    /* Setup pointer to media name buffer.  */
+    dir_entry.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
+
+    /* Clear the short name string.  */
+    dir_entry.fx_dir_entry_short_name[0] =  0;
+
+    /* Clear the long name string.  */
+    dir_entry.fx_dir_entry_name[0] =  (CHAR)0;
+
+    /* Check the media to make sure it is open.  */
+    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
+    {
+
+        /* Return the media not opened error.  */
+        return(FX_MEDIA_NOT_OPEN);
+    }
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_DIRECTORY_DEFAULT_SET, media_ptr, new_path_name, 0, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+    /* Setup the path string pointer to the start of the current path.  */
+    path_string_ptr =  &(media_ptr -> fx_media_default_path.fx_path_string[0]);
+
+#ifdef FX_ENABLE_EXFAT
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+
+        /* Get the absolute path.  */
+        if (_fx_utility_absolute_path_get(path_string_ptr, new_path_name, abs_str) == FX_SUCCESS)
+        {
+
+            new_path_name = &(abs_str[0]);
+        }
+        else
+        {
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* Invalid Path - Return the error code.  */
+            return(FX_INVALID_PATH);
+        }
+    }
+#endif /* FX_ENABLE_EXFAT */
+
+    /* Look for a root directory selection.  */
+    if ((!new_path_name) || (((new_path_name[0] == '\\') || (new_path_name[0] == '/')) && (new_path_name[1] == (CHAR)0)))
+    {
+
+        /* Set the media current working directory to the root.  */
+        media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_name[0] =  (CHAR) 0;
+        media_ptr -> fx_media_default_path.fx_path_string[0] =                       (CHAR) 0;
+        media_ptr -> fx_media_default_path.fx_path_string[FX_MAXIMUM_PATH - 2] =     (CHAR) 0;
+    }
+    else
+    {
+
+        /* Search the system for the supplied path and directory name.  */
+        status =  _fx_directory_search(media_ptr, new_path_name, &dir_entry, FX_NULL, FX_NULL);
+
+        /* Determine if the search failed or if the entry found is not a
+           directory.  */
+        if ((status != FX_SUCCESS) || (!(dir_entry.fx_dir_entry_attributes & FX_DIRECTORY)))
+        {
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* Invalid Path - Return the error code.  */
+            return(FX_INVALID_PATH);
+        }
+
+        /* Now update the current path string.  */
+
+        /* Setup the path string's capacity.  */
+        path_string_capacity =  FX_MAXIMUM_PATH - 1;
+
+        /* Determine if the new path is relative from the current path.  */
+        if ((new_path_name[0] != '\\') && (new_path_name[0] != '/'))
+        {
+
+            /* Yes, a relative path was found.  */
+
+            /* First check for a local path pointer stored in the thread control block.
+               This is only available in ThreadX Version 4 and above.  */
+#ifndef FX_NO_LOCAL_PATH
+            if (_tx_thread_current_ptr -> tx_thread_filex_ptr)
+            {
+
+            CHAR *saved_name_ptr;
+
+                /* First, save the name pointer of the default path.  */
+                saved_name_ptr =  media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_name;
+
+                /* Setup the default path pointer to the local path.  */
+                path_ptr =  (FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr;
+
+                /* Copy the local path to the default path.  */
+                media_ptr -> fx_media_default_path =  *path_ptr;
+
+                /* Restore the name pointer of the default path.  */
+                media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_name =  saved_name_ptr;
+
+                /* Set the path pointer to the default pointer.  */
+                path_ptr =  &media_ptr -> fx_media_default_path;
+            }
+            else
+            {
+
+                /* Setup the default path to the global media path.  */
+                path_ptr =  &media_ptr -> fx_media_default_path;
+            }
+#else
+
+            /* Setup the default path to the global media path.  */
+            path_ptr =  &media_ptr -> fx_media_default_path;
+#endif
+
+            /* First, check the current path for string overflow.  If this is set,
+               don't attempt to update the current path with relative information.
+               The path won't be valid again until a complete path is given.  */
+            if (path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] == '*')
+            {
+
+                /* Yes, don't update the string, just finish the path set processing.  */
+
+                /* Determine if we are at the root directory.  */
+                if (!dir_entry.fx_dir_entry_cluster)
+                {
+                    /* Set the current directory back to the root directory.  */
+                    path_ptr -> fx_path_directory.fx_dir_entry_name[0] =  (CHAR) 0;
+
+                    /* Set name to NULL.  */
+                    dir_entry.fx_dir_entry_name[0] =  (CHAR) 0;
+
+                    /* Clear the current path string.  */
+                    path_ptr -> fx_path_string[0] =  (CHAR)0;
+
+                    /* Clear the overflow flag in the current path string... just in
+                       case! */
+                    path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] =  (CHAR)0;
+                }
+
+                /* Copy the new directory entry into the media control block.  */
+                path_ptr -> fx_path_directory =  dir_entry;
+
+                /* Copy the name into the path name buffer.  */
+                for (i = 0; dir_entry.fx_dir_entry_name[i]; i++)
+                {
+                    path_ptr -> fx_path_name_buffer[i] =  dir_entry.fx_dir_entry_name[i];
+                }
+
+                /* Reassign the pointer.  */
+                path_ptr -> fx_path_directory.fx_dir_entry_name =  path_ptr -> fx_path_name_buffer;
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* Default directory set is complete, return status.  */
+                return(FX_SUCCESS);
+            }
+
+            /* Move the current path starting pointer to the end of the current
+               path string.  */
+            while ((path_string_capacity) && (*path_string_ptr != FX_NULL))
+            {
+                path_string_ptr++;
+                path_string_capacity--;
+            }
+
+            /* If room, place the \ character in the path string.  */
+            if (path_string_capacity)
+            {
+
+                /* There is room, place the directory marker in the string.  */
+                *path_string_ptr++ =  '\\';
+                path_string_capacity--;
+            }
+        }
+        else
+        {
+
+            /* Setup the default path pointer.  */
+
+            /* First check for a local path pointer stored in the thread control block.
+               This is only available in ThreadX Version 4 and above.  */
+#ifndef FX_NO_LOCAL_PATH
+            if (_tx_thread_current_ptr -> tx_thread_filex_ptr)
+            {
+
+            CHAR *saved_name_ptr;
+
+                /* First, save the name pointer of the default path.  */
+                saved_name_ptr =  media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_name;
+
+                /* Setup the default path pointer to the local path.  */
+                path_ptr =  (FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr;
+
+                /* Copy the local path to the default path.  */
+                media_ptr -> fx_media_default_path =  *path_ptr;
+
+                /* Restore the name pointer of the default path.  */
+                media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_name =  saved_name_ptr;
+
+                /* Set the path pointer to the default pointer.  */
+                path_ptr =  &media_ptr -> fx_media_default_path;
+            }
+            else
+            {
+
+                /* Setup the default path to the global media path.  */
+                path_ptr =  &media_ptr -> fx_media_default_path;
+            }
+#else
+
+            /* Setup the default path to the global media path.  */
+            path_ptr =  &media_ptr -> fx_media_default_path;
+#endif
+
+            /* Complete path name given.  Check to see if we need to clear an
+               overflow character from a previous current path string update.  */
+            if (path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] == '*')
+            {
+                path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] = (CHAR)0;
+            }
+        }
+
+        /* Copy what we can into the current path.  */
+        while (*new_path_name)
+        {
+
+            /* Determine if there is a ".." character sequence that specifies the
+               previous path.  */
+            if ((*new_path_name == '.') && (*(new_path_name + 1) == '.'))
+            {
+
+                /* Yes, a backward path is found.  The current path pointer
+                   must be moved back to just after the previous \ character.  */
+
+                /* Skip the current \0 that is at the end of the current path.  */
+                path_string_capacity =  path_string_capacity + 2;
+                path_string_ptr =       path_string_ptr - 2;
+
+                while (path_string_capacity <= (FX_MAXIMUM_PATH - 1))
+                {
+
+                    /* Move the current path pointer backwards until
+                       a \ character is found.  */
+
+                    if ((*path_string_ptr == '\\') || (*path_string_ptr == '/'))
+                    {
+
+                        /* Yes, we have successfully backed up one directory.  */
+                        break;
+                    }
+
+                    /* Backup another character.  */
+                    path_string_capacity++;
+                    path_string_ptr--;
+                }
+
+                /* Adjust the new directory pointer past the .. characters  */
+                new_path_name =  new_path_name + 2;
+            }
+            else
+            {
+
+                /* Normal characters that need to be copied into the current path.  */
+
+                if (path_string_capacity)
+                {
+
+                    /* Copy character from the new path into the current path string.  */
+                    *path_string_ptr++ =  *new_path_name++;
+
+                    path_string_capacity--;
+                }
+                else
+                {
+
+                    /* No more room in the current path string!  */
+                    break;
+                }
+            }
+        }
+
+        /* Determine if there is still room in the current path string.  */
+        if (path_string_capacity)
+        {
+
+            /* Yes, there is still room, place a NULL character at the
+               end of the path.  */
+            *path_string_ptr =  (CHAR)FX_NULL;
+        }
+        else
+        {
+
+            /* No more room.  Determine if the entire path was successfully
+               copied into the current path.  */
+            if (*new_path_name)
+            {
+
+                /* No, we couldn't fit the entire path.  Place a "*" character
+                   at the end to indicate that we had overflow.  Note that
+                   the path is kept just the the directory default get call, so
+                   the new default path is valid.  */
+                path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] =  '*';
+            }
+        }
+
+        /* Determine if we are at the root directory.  */
+#ifdef FX_ENABLE_EXFAT
+        if ((!dir_entry.fx_dir_entry_cluster) && (media_ptr -> fx_media_FAT_type != FX_exFAT))
+#else
+        if (!dir_entry.fx_dir_entry_cluster)
+#endif
+        {
+
+            /* Set the current directory back to the root directory.  */
+            dir_entry.fx_dir_entry_name[0] =      (CHAR)0;
+            path_ptr -> fx_path_name_buffer[0] =  (CHAR)0;
+        }
+
+        /* Copy the new directory entry into the media control block.  */
+        path_ptr -> fx_path_directory =  dir_entry;
+
+        /* Copy the name.  */
+        for (i = 0; dir_entry.fx_dir_entry_name[i]; i++)
+        {
+            path_ptr -> fx_path_name_buffer[i] =  dir_entry.fx_dir_entry_name[i];
+        }
+
+        /* Reassign the pointer.  */
+        path_ptr -> fx_path_directory.fx_dir_entry_name =  path_ptr -> fx_path_name_buffer;
+    }
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* Default directory set is complete, return status.  */
+    return(FX_SUCCESS);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_delete.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_delete.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_delete.c	(revision 30)
@@ -0,0 +1,589 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_directory.h"
+#include "fx_file.h"
+#include "fx_utility.h"
+#ifdef FX_ENABLE_EXFAT
+#include "fx_directory_exFAT.h"
+#endif /* FX_ENABLE_EXFAT */
+#ifdef FX_ENABLE_FAULT_TOLERANT
+#include "fx_fault_tolerant.h"
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_directory_delete                                PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function first attempts to find the specified directory.       */
+/*    If found, the directory is examined to make sure it is empty.  If   */
+/*    the directory is not empty, an error code is returned to the        */
+/*    caller.  Otherwise, the directory will be deleted and its clusters  */
+/*    will be made available.                                             */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    directory_name                        Directory name to delete      */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_entry_read              Read a directory entry        */
+/*    _fx_directory_entry_write             Write the new directory entry */
+/*    _fx_directory_search                  Search for the file name in   */
+/*                                          the directory structure       */
+/*    _fx_utility_logical_sector_flush      Flush the written log sector  */
+/*    _fx_utility_exFAT_cluster_state_set   Set cluster state             */
+/*    _fx_utility_FAT_entry_read            Read FAT entries to calculate */
+/*                                            the sub-directory size      */
+/*    _fx_utility_FAT_entry_write           Write FAT entry               */
+/*    _fx_utility_FAT_flush                 Flush FAT cache               */
+/*    _fx_fault_tolerant_transaction_start  Start fault tolerant          */
+/*                                            transaction                 */
+/*    _fx_fault_tolerant_transaction_end    End fault tolerant transaction*/
+/*    _fx_fault_tolerant_recover            Recover FAT chain             */
+/*    _fx_fault_tolerant_reset_log_file     Reset the log file            */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_directory_delete(FX_MEDIA *media_ptr, CHAR *directory_name)
+{
+
+UINT         status;
+ULONG        cluster, next_cluster;
+ULONG        i, directory_size;
+FX_DIR_ENTRY dir_entry;
+FX_DIR_ENTRY search_directory;
+FX_DIR_ENTRY search_entry;
+
+#ifdef FX_ENABLE_EXFAT
+ULONG        clusters_count;
+ULONG        bytes_per_cluster;
+#endif /* FX_ENABLE_EXFAT */
+
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of times this service has been called.  */
+    media_ptr -> fx_media_directory_deletes++;
+#endif
+
+    /* Setup pointer to media name buffer.  */
+    dir_entry.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
+
+    /* Setup search pointer to media name buffer.  */
+    search_directory.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN * 2;
+
+    /* Setup search entry pointer to media name buffer.  */
+    search_entry.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN * 3;
+
+    /* Clear the short name string of the three file names that will be worked with.  */
+    dir_entry.fx_dir_entry_short_name[0] =  0;
+    search_directory.fx_dir_entry_short_name[0] =  0;
+    search_entry.fx_dir_entry_short_name[0] =  0;
+
+    /* Check the media to make sure it is open.  */
+    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
+    {
+
+        /* Return the media not opened error.  */
+        return(FX_MEDIA_NOT_OPEN);
+    }
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_DIRECTORY_DELETE, media_ptr, directory_name, 0, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    /* Start transaction. */
+    _fx_fault_tolerant_transaction_start(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Check for write protect at the media level (set by driver).  */
+    if (media_ptr -> fx_media_driver_write_protect)
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return write protect error.  */
+        return(FX_WRITE_PROTECT);
+    }
+
+    /* Search the system for the supplied directory name.  */
+    status =  _fx_directory_search(media_ptr, directory_name, &dir_entry, FX_NULL, FX_NULL);
+
+    /* Determine if the search was successful.  */
+    if (status != FX_SUCCESS)
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the error code.  */
+        return(status);
+    }
+
+    /* Check to make sure the found entry is a directory.  */
+    if (!(dir_entry.fx_dir_entry_attributes & (UCHAR)(FX_DIRECTORY)))
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the not a directory error code.  */
+        return(FX_NOT_DIRECTORY);
+    }
+
+    /* Check if the entry is read only */
+    if (dir_entry.fx_dir_entry_attributes & (UCHAR)(FX_READ_ONLY))
+    {
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the not a directory error code.  */
+        return(FX_WRITE_PROTECT);
+    }
+
+    /* Copy the directory entry to the search directory structure for
+       looking at the specified sub-directory contents.  */
+    search_directory =  dir_entry;
+
+    /* Ensure that the search directory's last search cluster is cleared.  */
+    search_directory.fx_dir_entry_last_search_cluster =  0;
+
+#ifdef FX_ENABLE_EXFAT
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+        directory_size = (ULONG)search_directory.fx_dir_entry_file_size / FX_DIR_ENTRY_SIZE;
+    }
+    else
+    {
+#endif /* FX_ENABLE_EXFAT */
+
+        /* Calculate the directory size by counting the allocated
+           clusters for it.  */
+        i =        0;
+        cluster =  search_directory.fx_dir_entry_cluster;
+        while (cluster < media_ptr -> fx_media_fat_reserved)
+        {
+
+            /* Increment the cluster count.  */
+            i++;
+
+            /* Read the next FAT entry.  */
+            status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
+
+            /* Check the return status.  */
+            if (status != FX_SUCCESS)
+            {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* Return the bad status.  */
+                return(status);
+            }
+
+            if ((cluster < FX_FAT_ENTRY_START) || (cluster == next_cluster) || (i > media_ptr -> fx_media_total_clusters))
+            {
+#ifdef FX_ENABLE_FAULT_TOLERANT
+               FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* Return the bad status.  */
+                return(FX_FAT_READ_ERROR);
+            }
+
+            cluster = next_cluster;
+        }
+
+        /* Now we can calculate the directory size.  */
+        directory_size =  (((ULONG)media_ptr -> fx_media_bytes_per_sector) *
+                           ((ULONG)media_ptr -> fx_media_sectors_per_cluster) * i) /
+                           (ULONG)FX_DIR_ENTRY_SIZE;
+
+        /* Also save this in the directory entry so we don't have to
+           calculate it later.  */
+        search_directory.fx_dir_entry_file_size =  directory_size;
+#ifdef FX_ENABLE_EXFAT
+    }
+#endif /* FX_ENABLE_EXFAT */
+
+    /* Make sure the new name is not in the current directory.  */
+#ifdef FX_ENABLE_EXFAT
+    if (directory_size > 0)
+    {
+
+        /* exFAT directories do not record '.' and '..' directories.  */
+        if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+        {
+            i = 0;
+        }
+        else
+        {
+            i = 2;
+        }
+#else
+        /* The first two entries are skipped because they are just part of the sub-directory.  */
+        i = 2;
+#endif /* FX_ENABLE_EXFAT */
+
+        do
+        {
+
+            /* Read an entry from the directory.  */
+            status = _fx_directory_entry_read(media_ptr, &search_directory, &i, &search_entry);
+
+            /* Check for error status.  */
+            if (status != FX_SUCCESS)
+            {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* Return error condition.  */
+                return(status);
+            }
+
+            /* Determine if this is the last directory entry.  */
+#ifdef FX_ENABLE_EXFAT
+            if (search_entry.fx_dir_entry_type == FX_EXFAT_DIR_ENTRY_TYPE_END_MARKER)
+#else
+            if (search_entry.fx_dir_entry_name[0] == FX_DIR_ENTRY_DONE)
+#endif /* FX_ENABLE_EXFAT */
+            {
+                break;
+            }
+
+#ifdef FX_ENABLE_EXFAT
+            if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+            {
+
+                /* Skip '.' and '..' folders if exists.  */
+                if ((i == 1) && (search_entry.fx_dir_entry_type == FX_EXFAT_DIR_ENTRY_TYPE_FILE_DIRECTORY) &&
+                    (search_entry.fx_dir_entry_name[0] == '.') &&
+                    (search_entry.fx_dir_entry_name[1] == 0))
+                {
+
+                    continue;
+                }
+                if ((i == 2) && (search_entry.fx_dir_entry_type == FX_EXFAT_DIR_ENTRY_TYPE_FILE_DIRECTORY) &&
+                    (search_entry.fx_dir_entry_name[0] == '.') && (search_entry.fx_dir_entry_name[1] == '.') &&
+                    (search_entry.fx_dir_entry_name[2] == 0))
+                {
+
+                    continue;
+                }
+            }
+#endif /* FX_ENABLE_EXFAT */
+
+            /* Determine if this is an empty entry.  */
+#ifdef FX_ENABLE_EXFAT
+            if (search_entry.fx_dir_entry_type != FX_EXFAT_DIR_ENTRY_TYPE_FREE)
+#else
+            if ((UCHAR)search_entry.fx_dir_entry_name[0] != (UCHAR)FX_DIR_ENTRY_FREE)
+#endif /* FX_ENABLE_EXFAT */
+            {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* Return error status.  */
+                return(FX_DIR_NOT_EMPTY);
+            }
+
+            i++;
+        } while (i < directory_size);
+#ifdef FX_ENABLE_EXFAT
+    }
+#endif /* FX_ENABLE_EXFAT */
+
+    /* At this point, we are going to delete the empty directory.  */
+
+#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
+
+    /* Invalidate the directory search saved information.  */
+    media_ptr -> fx_media_last_found_name[0] =  FX_NULL;
+#endif
+
+    /* Mark the sub-directory entry as available.  */
+    dir_entry.fx_dir_entry_name[0] =  (CHAR)FX_DIR_ENTRY_FREE;
+    dir_entry.fx_dir_entry_short_name[0] =  (CHAR)FX_DIR_ENTRY_FREE;
+
+    /* Now write out the directory entry.  */
+#ifdef FX_ENABLE_EXFAT
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+
+        status =  _fx_directory_exFAT_entry_write(media_ptr, &dir_entry, UPDATE_DELETE);
+    }
+    else
+    {
+#endif /* FX_ENABLE_EXFAT */
+        status =  _fx_directory_entry_write(media_ptr, &dir_entry);
+#ifdef FX_ENABLE_EXFAT
+    }
+#endif /* FX_ENABLE_EXFAT */
+
+    /* Determine if the write was successful.  */
+    if (status != FX_SUCCESS)
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the error code.  */
+        return(status);
+    }
+
+#ifdef FX_ENABLE_EXFAT
+    bytes_per_cluster =  ((ULONG)media_ptr -> fx_media_bytes_per_sector) *
+        ((ULONG)media_ptr -> fx_media_sectors_per_cluster);
+
+    i = 0;
+
+    clusters_count = (ULONG)((search_directory.fx_dir_entry_file_size + bytes_per_cluster - 1) / bytes_per_cluster - 1);
+#endif /* FX_ENABLE_EXFAT */
+
+    /* Walk through the directory's clusters and release them.  */
+    cluster =  search_directory.fx_dir_entry_cluster;
+
+    while (cluster < media_ptr -> fx_media_fat_reserved)
+    {
+
+        /* Increment the cluster count.  */
+        i++;
+
+#ifdef FX_ENABLE_EXFAT
+
+        /* Read the next FAT entry.  */
+        if (search_directory.fx_dir_entry_dont_use_fat & 1)
+        {
+
+            /* Check for file size range */
+            if (i - 1 >= clusters_count)
+            {
+                next_cluster = FX_LAST_CLUSTER_exFAT;
+            }
+            else
+            {
+                next_cluster = cluster + 1;
+            }
+        }
+        else
+        {
+
+#endif /* FX_ENABLE_EXFAT */
+
+            /* Read the next FAT entry.  */
+            status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
+
+            /* Check the return status.  */
+            if (status != FX_SUCCESS)
+            {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* Return the bad status.  */
+                return(status);
+            }
+#ifdef FX_ENABLE_EXFAT
+        }
+#endif /* FX_ENABLE_EXFAT */
+
+        if ((cluster < FX_FAT_ENTRY_START) || (cluster == next_cluster) || (i > media_ptr -> fx_media_total_clusters))
+        {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+            FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* Return the bad status.  */
+            return(FX_FAT_READ_ERROR);
+        }
+
+        /* Release the current cluster.  */
+#ifdef FX_ENABLE_EXFAT
+        if (!(search_directory.fx_dir_entry_dont_use_fat & 1))
+        {
+#endif /* FX_ENABLE_EXFAT */
+
+            status =  _fx_utility_FAT_entry_write(media_ptr, cluster, FX_FREE_CLUSTER);
+
+            /* Check the return status.  */
+            if (status != FX_SUCCESS)
+            {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* Return the bad status.  */
+                return(status);
+            }
+#ifdef FX_ENABLE_EXFAT
+        }
+
+        if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+        {
+
+            /* Mark the cluster as free.  */
+            status = _fx_utility_exFAT_cluster_state_set(media_ptr, cluster, FX_EXFAT_BITMAP_CLUSTER_FREE);
+
+            /* Check the return status.  */
+            if (status != FX_SUCCESS)
+            {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* Return the bad status.  */
+                return(status);
+            }
+        }
+#endif /* FX_ENABLE_EXFAT */
+
+        /* Increment the number of available clusters for the media.  */
+        media_ptr -> fx_media_available_clusters++;
+
+        /* Copy next cluster to current cluster.  */
+        cluster =  next_cluster;
+    }
+
+#ifdef FX_FAULT_TOLERANT
+
+    /* Flush the cached individual FAT entries */
+    _fx_utility_FAT_flush(media_ptr);
+#endif
+
+    /* Flush the logical sector cache.  */
+    status =  _fx_utility_logical_sector_flush(media_ptr, ((ULONG64) 1), (ULONG64)(media_ptr -> fx_media_sectors_per_FAT), FX_FALSE);
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    /* Check for a bad status.  */
+    if (status != FX_SUCCESS)
+    {
+
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the bad status.  */
+        return(status);
+    }
+
+    /* End transaction. */
+    status = _fx_fault_tolerant_transaction_end(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* Directory delete is complete, return status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_entry_read.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_entry_read.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_entry_read.c	(revision 30)
@@ -0,0 +1,786 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_directory.h"
+#include "fx_utility.h"
+#ifdef FX_ENABLE_EXFAT
+#include "fx_directory_exFAT.h"
+
+
+
+#endif /* FX_ENABLE_EXFAT */
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_directory_entry_read                            PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function reads the supplied directory entry from the supplied  */
+/*    source directory.  If the supplied directory entry is NULL, then    */
+/*    the root directory is assumed.                                      */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    source_dir                            Source directory entry        */
+/*    entry_ptr                             Directory entry number        */
+/*    destination_ptr                       Pointer to destination for    */
+/*                                            the directory entry         */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*    *entry_ptr should point to the 8:3 entry if it is a long name       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_exFAT_entry_read        Read exFAT entries            */
+/*    _fx_utility_FAT_entry_read            Read a FAT entry              */
+/*    _fx_utility_logical_sector_read       Read directory sector         */
+/*    _fx_utility_16_unsigned_read          Read a UINT from memory       */
+/*    _fx_utility_32_unsigned_read          Read a ULONG from memory      */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    FileX System Functions                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+#ifdef FX_ENABLE_EXFAT
+UINT  _fx_directory_entry_read_FAT(FX_MEDIA *media_ptr, FX_DIR_ENTRY *source_dir,
+                                   ULONG *entry_ptr, FX_DIR_ENTRY *destination_ptr)
+#else
+UINT  _fx_directory_entry_read(FX_MEDIA *media_ptr, FX_DIR_ENTRY *source_dir,
+                               ULONG *entry_ptr, FX_DIR_ENTRY *destination_ptr)
+#endif /* FX_ENABLE_EXFAT */
+{
+
+UINT   i, j, card, dotflag, get_short_name;
+UINT   number_of_lfns;
+UINT   status;
+ULONG  cluster, next_cluster = 0;
+UINT   relative_cluster;
+UINT   relative_sector;
+ULONG  logical_sector;
+ULONG  byte_offset;
+ULONG  bytes_per_cluster;
+UCHAR *read_ptr;
+CHAR  *short_name_ptr;
+ULONG  entry = *entry_ptr;
+
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of directory entry read requests.  */
+    media_ptr -> fx_media_directory_entry_reads++;
+#endif
+
+    /* Extended port-specific processing macro, which is by default defined to white space.  */
+    FX_DIRECTORY_ENTRY_READ_EXTENSION
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_DIR_ENTRY_READ, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+    /* Calculate the byte offset of this directory entry.  */
+    byte_offset =  entry * FX_DIR_ENTRY_SIZE;
+
+    /* Determine if a sub-directory or FAT32 root directory is specified.  */
+#ifdef FX_ENABLE_EXFAT
+    if ((source_dir) || (media_ptr -> fx_media_FAT_type == FX_FAT32))
+#else
+    if ((source_dir) || (media_ptr -> fx_media_32_bit_FAT))
+#endif
+    {
+
+        /* Yes, a sub-directory is present.  */
+
+        /* Calculate the number of bytes per cluster.  */
+        bytes_per_cluster =  ((ULONG)media_ptr -> fx_media_bytes_per_sector) *
+            ((ULONG)media_ptr -> fx_media_sectors_per_cluster);
+
+        /* Check for invalid value.  */
+        if (bytes_per_cluster == 0)
+        {
+
+            /* Invalid media, return error.  */
+            return(FX_MEDIA_INVALID);
+        }
+
+        /* Now determine the relative cluster in the sub-directory file.  */
+        relative_cluster =   (UINT)(byte_offset / bytes_per_cluster);
+
+        /* Calculate the byte offset within the cluster.  */
+        byte_offset =  byte_offset % bytes_per_cluster;
+
+        /* Now figure out the relative sector within the cluster.  */
+        relative_sector =    (UINT)(byte_offset / ((ULONG)media_ptr -> fx_media_bytes_per_sector));
+
+        /* Read the directory sector into the internal memory buffer.  */
+
+        /* Determine if there is a sub-directory.  */
+        if (source_dir)
+        {
+
+            /* Determine if this source directory has valid information from the previous call.  */
+            if ((source_dir -> fx_dir_entry_last_search_cluster) &&
+                (source_dir -> fx_dir_entry_last_search_relative_cluster <= relative_cluster) &&
+                (source_dir -> fx_dir_entry_last_search_log_sector == source_dir -> fx_dir_entry_log_sector) &&
+                (source_dir -> fx_dir_entry_last_search_byte_offset == source_dir -> fx_dir_entry_byte_offset))
+            {
+
+                /* Use the previous information to start the search.  */
+                cluster =  source_dir -> fx_dir_entry_last_search_cluster;
+
+                /* Setup the relative cluster index to the saved relative cluster.  */
+                i =  source_dir -> fx_dir_entry_last_search_relative_cluster;
+
+                /* Clear the search cluster.  It will be updated prior to successful return.  */
+                source_dir -> fx_dir_entry_last_search_cluster =  0;
+            }
+            else
+            {
+
+                /* Nothing from the previous directory read, just setup the starting cluster to the
+                   beginning of the sub-directory.  */
+                cluster =  source_dir -> fx_dir_entry_cluster;
+
+                /* Setup the relative cluster index to zero.  */
+                i =  0;
+            }
+        }
+        else
+        {
+
+            /* No, setup the starting cluster to the FAT32 root cluster.  */
+            cluster =  media_ptr -> fx_media_root_cluster_32;
+
+            /* Setup the relative cluster index to zero.  */
+            i =  0;
+        }
+
+        /* Loop to position to the appropriate cluster.  */
+        while (i < relative_cluster)
+        {
+
+            /* Check the value of the new cluster - it must be a valid cluster number
+               or something is really wrong!  */
+            if ((cluster < FX_FAT_ENTRY_START) || (cluster >= media_ptr -> fx_media_fat_reserved))
+            {
+
+                /* Send error message back to caller.  */
+                return(FX_FILE_CORRUPT);
+            }
+
+            /* Read the next cluster.  */
+            status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
+
+            /* There is a potential for loop, but hardly anything can be done */
+
+            /* Check for I/O error.  */
+            if (status != FX_SUCCESS)
+            {
+
+                /* Return error code.  */
+                return(status);
+            }
+
+            /* Setup the actual cluster.  */
+            cluster = next_cluster;
+
+            /* Increment the relative cluster number.  */
+            i++;
+        }
+
+        /* At this point, the directory data sector needs to be read.  */
+        logical_sector =    ((ULONG)media_ptr -> fx_media_data_sector_start) +
+            (((ULONG)cluster - FX_FAT_ENTRY_START) *
+             ((ULONG)media_ptr -> fx_media_sectors_per_cluster)) +
+            relative_sector;
+
+        /* Read the logical directory sector.  */
+        status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) logical_sector,
+                                                  media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
+
+        /* Determine if an error occurred.  */
+        if (status != FX_SUCCESS)
+        {
+
+            /* Return error code.  */
+            return(status);
+        }
+
+        /* Calculate the byte offset within this sector.  */
+        byte_offset =  byte_offset % media_ptr -> fx_media_bytes_per_sector;
+    }
+    else
+    {
+
+        /* Read the entry from the root directory.  */
+
+        /* Determine which sector the requested root directory entry is in.  */
+        logical_sector =  (byte_offset / media_ptr -> fx_media_bytes_per_sector) +
+            (ULONG)media_ptr -> fx_media_root_sector_start;
+
+        /* Read the logical directory sector.  */
+        status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) logical_sector,
+                                                  media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
+
+        /* Determine if an error occurred.  */
+        if (status != FX_SUCCESS)
+        {
+
+            /* Return error code.  */
+            return(status);
+        }
+
+        /* Set the cluster and relative variables (not used in this case) to avoid any compiler
+           warnings.  */
+        relative_cluster =  relative_sector =  cluster =  0;
+
+        /* Now calculate the byte offset into this sector.  */
+        byte_offset =  byte_offset -
+            ((logical_sector - (ULONG)media_ptr -> fx_media_root_sector_start) *
+             media_ptr -> fx_media_bytes_per_sector);
+    }
+
+    /* Setup a pointer into the buffer.  */
+    read_ptr =  (UCHAR *)media_ptr -> fx_media_memory_buffer + (UINT)byte_offset;
+
+    /* Save the logical sector and byte offset in the returned directory entry.  */
+    destination_ptr -> fx_dir_entry_log_sector =       logical_sector;
+    destination_ptr -> fx_dir_entry_byte_offset =      byte_offset;
+
+    /* Clear the short file name information.  */
+    destination_ptr -> fx_dir_entry_long_name_shorted =  0;
+    destination_ptr -> fx_dir_entry_short_name[0]     =  0;
+
+    /* Setup short name pointer.  */
+    short_name_ptr =  destination_ptr -> fx_dir_entry_name;
+
+    /* Check if long file name exists.  */
+    get_short_name =  0;
+    if ((*(read_ptr + 11) == (UCHAR)FX_LONG_NAME) && (*read_ptr != (UCHAR)FX_DIR_ENTRY_FREE))
+    {
+
+        /* Collate the long name. */
+
+        /* Pickup the file name length.  */
+        i = (((UINT)(*read_ptr & (UCHAR)0x1f) - 1) * FX_LONG_NAME_ENTRY_LEN) & 0xFFFFFFFF;
+
+        /* Save the number of LFN entries.  */
+        number_of_lfns =  (UINT)(*read_ptr & (UCHAR)0x1f);
+
+        /* Check the file name size.  */
+        if (i >= (FX_MAX_LONG_NAME_LEN - 1))
+        {
+
+            /* Name is too big, shorten it.  */
+            get_short_name = 1;
+            destination_ptr -> fx_dir_entry_long_name_shorted =  (UINT)(*read_ptr & (UCHAR)0x1f);
+        }
+        else
+        {
+
+            /* Size of name is fine, save pointer to short file name.  */
+            short_name_ptr = destination_ptr -> fx_dir_entry_short_name;
+
+            /* Loop to make sure the long file name is NULL terminated.  */
+            j = i + FX_LONG_NAME_ENTRY_LEN + 1;
+            do
+            {
+                /* Place a NULL in the long name.  */
+                destination_ptr -> fx_dir_entry_name[i] =  0;
+
+                /* Position to the next entry.  */
+                i++;
+            } while ((i < j) && (i < FX_MAX_LONG_NAME_LEN));
+        }
+
+        /* Loop to pickup the rest of the name.  */
+        do
+        {
+
+            /* Get the lower 5 bit containing the cardinality.  */
+            card = (UINT)(*read_ptr & (UCHAR)0x1f) - 1;
+
+            /* For simplicity no checksum or cardinality checking is done */
+            if (get_short_name == 0)
+            {
+
+                /* Loop to pickup name.  */
+                for (i = 1, j = 0; i < FX_DIR_ENTRY_SIZE; i += 2)
+                {
+
+                    if ((i == 11) || (i == 26))
+                    {
+                        continue;
+                    }
+
+                    /* i = 12, 27 is not generated due to +=2 */
+                    if (i == 13)
+                    {
+                        i = 12;
+                        continue; /* this time next unicode is byte offset 14*/
+                    }
+
+                    /* Determine if there is an actual unicode character present.  */
+                    if (read_ptr[i + 1])
+                    {
+
+                        /* Extended byte is non-zero, make sure both bytes of the unicode entry are not
+                           all ones, since this is a normal case.  */
+                        if ((read_ptr[i + 1] != (UCHAR)0xFF) || (read_ptr[i] != (UCHAR)0xFF))
+                        {
+
+                            /* Name is an actual unicode name, shorten it.  */
+                            get_short_name = 1;
+
+                            /* Save the number of directory entries the LFN has.  This will be
+                               used later when updating the 8.3 portion of the LFN.  */
+                            destination_ptr -> fx_dir_entry_long_name_shorted =  number_of_lfns;
+
+                            /* Setup short name pointer.  */
+                            short_name_ptr =  destination_ptr -> fx_dir_entry_name;
+                        }
+                    }
+
+                    /* Determine if the character is NULL.  */
+                    if ((read_ptr[i] == FX_NULL) || (read_ptr[i] == (UCHAR)0xFF))
+                    {
+                        continue;
+                    }
+
+                    /* Determine if the name is too big.  */
+                    if ((card * 13 + j) >= (FX_MAX_LONG_NAME_LEN - 1))
+                    {
+
+                        /* Name is actually too big, shorten it.  */
+                        get_short_name =  1;
+
+                        /* Save the number of directory entries the LFN has.  This will be
+                           used later when updating the 8.3 portion of the LFN.  */
+                        destination_ptr -> fx_dir_entry_long_name_shorted =  number_of_lfns;
+
+                        /* Also reposition the short name pointer.  */
+                        short_name_ptr =  destination_ptr -> fx_dir_entry_name;
+
+                        break;
+                    }
+
+                    /* Each entry contains 13 unicode and first byte ASCII, second byte is extended. */
+                    destination_ptr -> fx_dir_entry_name[13 * card + j] = (CHAR)read_ptr[i];
+
+                    j++;
+                }
+            }
+
+            /* Determine if a new sector needs to be read.  */
+            if (byte_offset + FX_DIR_ENTRY_SIZE >= media_ptr -> fx_media_bytes_per_sector)
+            {
+
+                /* Determine if a sub-directory or FAT32 root directory is specified.  */
+                if ((source_dir) || (media_ptr -> fx_media_32_bit_FAT))
+                {
+
+                    /* Determine the next sector of the directory entry.  */
+                    if (relative_sector < (media_ptr -> fx_media_sectors_per_cluster - 1))
+                    {
+
+                        /* More sectors in this cluster.  */
+
+                        /* Simply increment the logical sector.  */
+                        logical_sector++;
+
+                        /* Increment the relative sector.  */
+                        relative_sector++;
+                    }
+                    else
+                    {
+
+                        /* We need to move to the next cluster.  */
+
+                        /* Pickup the next cluster.  */
+                        status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
+
+                        /* Check for I/O error.  */
+                        if (status != FX_SUCCESS)
+                        {
+
+                            /* Return error code.  */
+                            return(status);
+                        }
+
+                        /* Copy next cluster to the current cluster.  */
+                        cluster =  next_cluster;
+
+                        /* Check the value of the new cluster - it must be a valid cluster number
+                           or something is really wrong!  */
+                        if ((cluster < FX_FAT_ENTRY_START) || (cluster >= media_ptr -> fx_media_fat_reserved))
+                        {
+
+                            /* Send error message back to caller.  */
+                            return(FX_FILE_CORRUPT);
+                        }
+
+                        /* Now increment the relative cluster.  */
+                        relative_cluster++;
+
+                        /* Setup the relative sector (this is zero for subsequent cluster.  */
+                        relative_sector =  0;
+
+                        /* Calculate the next logical sector.  */
+                        logical_sector =   ((ULONG)media_ptr -> fx_media_data_sector_start) +
+                            (((ULONG)cluster - FX_FAT_ENTRY_START) *
+                             ((ULONG)media_ptr -> fx_media_sectors_per_cluster));
+                    }
+                }
+                else
+                {
+
+                    /* Non-FAT 32 root directory.  */
+
+                    /* Advance to the next sector.  */
+                    logical_sector++;
+
+                    /* Determine if the logical sector is valid.  */
+                    if (logical_sector >= (ULONG)(media_ptr -> fx_media_root_sector_start + media_ptr -> fx_media_root_sectors))
+                    {
+
+                        /* Trying to read past root directory - send error message back to caller.  */
+                        return(FX_FILE_CORRUPT);
+                    }
+                }
+
+                /* Read the new sector.  */
+                status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) logical_sector,
+                                                          media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
+
+                /* Check I/O status.  */
+                if (status != FX_SUCCESS)
+                {
+                    return(status);
+                }
+
+                /* Set the byte offset to 0 for new sector.  */
+                byte_offset = 0;
+            }
+            else
+            {
+
+                /* Calculate the new byte offset.  */
+                byte_offset += FX_DIR_ENTRY_SIZE;
+            }
+
+            /* Calculate the next read pointer.  */
+            read_ptr =  (UCHAR *)media_ptr -> fx_media_memory_buffer + (UINT) byte_offset;
+
+            /* Move to the next entry.  */
+            entry++;
+        } while (card > 0);
+
+        /* Set flag indicating long file name is present.  */
+        destination_ptr -> fx_dir_entry_long_name_present = 1;
+    }
+    else
+    {
+        /* No long file name is present.  */
+        get_short_name = 1;
+    }
+
+    /* Determine if we need to clear the long name flag.  */
+    if (get_short_name == 1)
+    {
+
+        /* Clear the long name flag.  */
+        destination_ptr -> fx_dir_entry_long_name_present =  0;
+    }
+
+    /* Pickup the short file name.  */
+    short_name_ptr[0] =  0;
+    dotflag =  0;
+    for (i = 0, j = 0; i < (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE); i++)
+    {
+
+        /* Check for a NULL.  */
+        if ((CHAR)read_ptr[i] == 0)
+        {
+            break;
+        }
+
+        /* Check for a dot.  This happens for the first two directory entries, no
+           extra dot is needed.  */
+        if ((CHAR)read_ptr[i] == '.')
+        {
+            dotflag =  2;
+        }
+
+        /* Check for a space.  */
+        if ((CHAR)read_ptr[i] == ' ')
+        {
+            /* Put a dot if a character comes after space.  */
+            if (dotflag == 0)
+            {
+                dotflag =  1;
+            }
+            continue;
+        }
+
+        /* Check for the main short file name size.  */
+        if (i == FX_DIR_NAME_SIZE)
+        {
+            /* Check to see if we need to insert a dot.  */
+            if (dotflag == 0)
+            {
+                dotflag =  1;
+            }
+        }
+
+        /* Check to see if we need to add a dot.  */
+        if (dotflag == 1)
+        {
+            /* Add dot to short file name.  */
+            short_name_ptr[j++] =  '.';
+            dotflag =  2;    /* no more dot for spaces */
+        }
+
+        /* Copy a character.  */
+        short_name_ptr[j] =  (CHAR)read_ptr[i];
+
+        /* Increment size.  */
+        j++;
+    }
+
+    /* Determine if a long file name is present and its associated short file
+       name is actually free.  */
+    if ((destination_ptr -> fx_dir_entry_long_name_present) && (((UCHAR)short_name_ptr[0]) == (UCHAR)FX_DIR_ENTRY_FREE))
+    {
+
+        /* Yes, the short file name is really free even though long file name entries directly precede it.
+           In this case, simply place the free directory marker at the front of the long file name.  */
+        destination_ptr -> fx_dir_entry_name[0] =  (CHAR)FX_DIR_ENTRY_FREE;
+        short_name_ptr[0] =  (CHAR)0;
+    }
+
+    /* Determine if the short name pointer is NULL while the read pointer is
+       non-NULL.  */
+    if ((short_name_ptr[0] == 0) && (read_ptr[0] == ' '))
+    {
+
+        /* This condition can occur with an all blank volume name.  Simply
+           copy the volume name to the short name in this case.  */
+        for (j = 0; j < (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE); j++)
+        {
+
+            /* Copy a byte of the volume name.  */
+            short_name_ptr[j] =  (CHAR)read_ptr[j];
+        }
+    }
+
+    /* Set end of string to null.  */
+    short_name_ptr[j] = 0;
+
+    /* Load up the destination directory entry.  */
+    read_ptr += (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE);
+
+    /* Copy the attribute into the destination.  */
+    destination_ptr -> fx_dir_entry_attributes =  *read_ptr++;
+
+    /* Pickup the reserved byte.  */
+    destination_ptr -> fx_dir_entry_reserved =  *read_ptr++;
+
+    /* Check for an undocumented NT file name feature for optimizing the storage
+       of all lower case file names that otherwise are valid 8.3 file names. The
+       following reserved bit definitions are present:
+
+         BIT3 - set if 8.3 is all in lower case and no extended filename.
+         BIT4 - set for file, clear for directory entry if no extended filename.
+
+       This is true for all NT systems. Prior to NT follows MSDOS FAT documentation and
+       is set to 0x00, all bits cleared. Therefore if BIT3 is set force lowercase.  */
+    if ((get_short_name) && (destination_ptr -> fx_dir_entry_reserved & 0x08))
+    {
+
+        /* Microsoft undocumented NT file name feature... convert short name to lower
+           case.  */
+        for (j = 0; j <= (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE) && (short_name_ptr[j] != 0x00); j++)
+        {
+
+            /* Determine if an upper case character is present.  */
+            if ((short_name_ptr[j] >= 'A') && (short_name_ptr[j] <= 'Z'))
+            {
+
+                /* Yes, an upper case character is present. Force it to lower case.  */
+                short_name_ptr[j] =  (CHAR)(short_name_ptr[j] + 32);
+            }
+        }
+    }
+
+    /* Pickup the created time in milliseconds.  */
+    destination_ptr -> fx_dir_entry_created_time_ms =  *read_ptr++;
+
+    /* Pickup the created time.  */
+    destination_ptr -> fx_dir_entry_created_time =  _fx_utility_16_unsigned_read(read_ptr);
+    read_ptr =  read_ptr + 2;  /* Always 2 bytes */
+
+    /* Pickup the created date.  */
+    destination_ptr -> fx_dir_entry_created_date =  _fx_utility_16_unsigned_read(read_ptr);
+    read_ptr =  read_ptr + 2;  /* Always 2 bytes */
+
+    /* Pickup the last accessed date.  */
+    destination_ptr -> fx_dir_entry_last_accessed_date =  _fx_utility_16_unsigned_read(read_ptr);
+    read_ptr =  read_ptr + 2;  /* Always 2 bytes */
+
+    /* read the upper 2 bytes of starting cluster - required only for 32 bit FAT */
+    if (media_ptr -> fx_media_32_bit_FAT)
+    {
+
+        /* FAT32 only.  */
+        destination_ptr -> fx_dir_entry_cluster =  _fx_utility_16_unsigned_read(read_ptr);
+        destination_ptr -> fx_dir_entry_cluster <<= 16;
+    }
+    else
+    {
+        /* Not required for non FAT32.  */
+        destination_ptr -> fx_dir_entry_cluster =  0;
+    }
+
+    /* Advance the read pointer.  */
+    read_ptr =  read_ptr + 2;  /* Always 2 bytes */
+
+    /* Copy the time into the destination.  */
+    destination_ptr -> fx_dir_entry_time =  _fx_utility_16_unsigned_read(read_ptr);
+    read_ptr =  read_ptr + 2;  /* Always 2 bytes */
+
+    /* Copy the date into the destination.  */
+    destination_ptr -> fx_dir_entry_date =  _fx_utility_16_unsigned_read(read_ptr);
+    read_ptr =  read_ptr + 2;  /* Always 2 bytes */
+
+    /* Copy the starting cluster into the destination.  */
+    destination_ptr -> fx_dir_entry_cluster +=  _fx_utility_16_unsigned_read(read_ptr);
+    read_ptr =  read_ptr + 2;  /* Always 2 bytes */
+
+    /* Copy the file size into the destination.  */
+    destination_ptr -> fx_dir_entry_file_size =  _fx_utility_32_unsigned_read(read_ptr);
+
+    /* Clear the destination search specific fields.  */
+    destination_ptr -> fx_dir_entry_last_search_cluster =           0;
+    destination_ptr -> fx_dir_entry_last_search_relative_cluster =  0;
+    destination_ptr -> fx_dir_entry_last_search_log_sector =        0;
+    destination_ptr -> fx_dir_entry_last_search_byte_offset =       0;
+
+    /* Remember the entry number.  */
+    destination_ptr -> fx_dir_entry_number =  entry;
+
+    /* Return entry number.  */
+    *entry_ptr =  entry;
+
+    /* Determine if we should remember the last cluster and relative cluster.  */
+    if (source_dir)
+    {
+
+        /* Yes, remember the last cluster and relative cluster for a subsequent call
+           to read a directory entry.  */
+        source_dir -> fx_dir_entry_last_search_cluster =           cluster;
+        source_dir -> fx_dir_entry_last_search_relative_cluster =  relative_cluster;
+
+        /* Also remember several other items that are unique to the directory... just to verify that the
+           search information can be used.  */
+        source_dir -> fx_dir_entry_last_search_log_sector =        source_dir -> fx_dir_entry_log_sector;
+        source_dir -> fx_dir_entry_last_search_byte_offset =       source_dir -> fx_dir_entry_byte_offset;
+    }
+#ifdef FX_ENABLE_EXFAT
+    destination_ptr -> fx_dir_entry_dont_use_fat = 0;
+
+    /* If a file whose first byte of long name is read, fx_dir_entry_short_name will not be empty. */
+    /* If a free dir_entry is obtained, fx_dir_entry_short_name[0] will not be assigned as 0 around Line 623 in this file. */
+    /* If there is only a free dir_entry without front long name dir_entries, fx_dir_entry_name[0] will be assigned by the loop around Line 568. */
+    if (((UCHAR)destination_ptr -> fx_dir_entry_name[0] == FX_DIR_ENTRY_FREE) && ((UCHAR)destination_ptr -> fx_dir_entry_short_name[0] == 0))
+    {
+        destination_ptr -> fx_dir_entry_type = FX_EXFAT_DIR_ENTRY_TYPE_FREE;
+    }
+    else if ((UCHAR)destination_ptr -> fx_dir_entry_name[0] == FX_DIR_ENTRY_DONE)
+    {
+        destination_ptr -> fx_dir_entry_type = FX_EXFAT_DIR_ENTRY_TYPE_END_MARKER;
+    }
+    else
+    {
+        destination_ptr -> fx_dir_entry_type = FX_EXFAT_DIR_ENTRY_TYPE_FILE_DIRECTORY;
+    }
+#endif /* FX_ENABLE_EXFAT */
+
+    /* Return success to the caller.  */
+    return(FX_SUCCESS);
+}
+
+
+#ifdef FX_ENABLE_EXFAT
+UINT  _fx_directory_entry_read_ex(FX_MEDIA *media_ptr, FX_DIR_ENTRY *source_dir,
+                                  ULONG *entry_ptr, FX_DIR_ENTRY *destination_ptr, UINT hash)
+{
+UINT status = FX_SUCCESS;
+
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+        status =
+            _fx_directory_exFAT_entry_read(
+                media_ptr, source_dir, entry_ptr, destination_ptr, hash, FX_FALSE, NULL, NULL);
+    }
+    else
+    {
+        status =
+            _fx_directory_entry_read_FAT(media_ptr, source_dir, entry_ptr, destination_ptr);
+    }
+
+    return(status);
+}
+
+
+UINT  _fx_directory_entry_read(FX_MEDIA *media_ptr, FX_DIR_ENTRY *source_dir,
+                               ULONG *entry_ptr, FX_DIR_ENTRY *destination_ptr)
+{
+
+    return(_fx_directory_entry_read_ex(media_ptr, source_dir, entry_ptr, destination_ptr, 0));
+}
+#endif /* FX_ENABLE_EXFAT */
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_entry_write.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_entry_write.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_entry_write.c	(revision 30)
@@ -0,0 +1,1152 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_directory.h"
+#include "fx_utility.h"
+#ifdef FX_ENABLE_FAULT_TOLERANT
+#include "fx_fault_tolerant.h"
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_directory_entry_write                           PORTABLE C      */
+/*                                                           6.1.5        */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function writes the supplied directory entry to the specified  */
+/*    logical sector and offset.                                          */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    entry_ptr                             Pointer to directory entry    */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_FAT_entry_read            Read a new FAT entry          */
+/*    _fx_utility_logical_sector_read       Read directory sector         */
+/*    _fx_utility_logical_sector_write      Write directory sector        */
+/*    _fx_utility_16_unsigned_write         Write a UINT from memory      */
+/*    _fx_utility_32_unsigned_write         Write a ULONG from memory     */
+/*    _fx_fault_tolerant_add_dir_log        Add directory redo log        */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    FileX System Functions                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*  03-02-2021     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1.5  */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_directory_entry_write(FX_MEDIA *media_ptr, FX_DIR_ENTRY *entry_ptr)
+{
+
+UCHAR *work_ptr, *sector_base_ptr;
+UINT   status, temp, entry, delete_flag;
+UINT   i, j, k, l, card, len, dotfound, dotpos, match;
+UCHAR  checksum, eof_marker;
+CHAR   alpha;
+CHAR   shortname[FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE + 1];
+ULONG  logical_sector, relative_sector;
+ULONG  byte_offset;
+ULONG  cluster, next_cluster;
+
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+UCHAR *changed_ptr;
+UINT   changed_size;
+ULONG  changed_offset;
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of directory entry write requests.  */
+    media_ptr -> fx_media_directory_entry_writes++;
+#endif
+
+    /* Extended port-specific processing macro, which is by default defined to white space.  */
+    FX_DIRECTORY_ENTRY_WRITE_EXTENSION
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_DIR_ENTRY_WRITE, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+    /* Determine if this is entry is being deleted.  */
+    if (((UCHAR)entry_ptr -> fx_dir_entry_name[0] == (UCHAR)FX_DIR_ENTRY_FREE) &&
+        ((UCHAR)entry_ptr -> fx_dir_entry_short_name[0] == (UCHAR)FX_DIR_ENTRY_FREE))
+    {
+
+        /* Yes, this is a request to delete the entry. Set the flag to remember this.  */
+        delete_flag =  FX_TRUE;
+
+        /* Null the short file name.  */
+        entry_ptr -> fx_dir_entry_short_name[0] =  0;
+    }
+    else
+    {
+
+        /* Not a deleted entry. Set the flag to false.  */
+        delete_flag =  FX_FALSE;
+    }
+
+    /* Pickup the byte offset of the entry.  */
+    byte_offset = entry_ptr -> fx_dir_entry_byte_offset;
+
+    /* Pickup the logical sector of the entry.  */
+    logical_sector = (ULONG)entry_ptr -> fx_dir_entry_log_sector;
+
+    /* Figure out where what cluster we are in.  */
+    if (logical_sector >= (ULONG)(media_ptr -> fx_media_data_sector_start))
+    {
+
+        /* Calculate the cluster that this logical sector is in.  */
+        cluster =  (logical_sector - media_ptr -> fx_media_data_sector_start) / (media_ptr -> fx_media_sectors_per_cluster) + FX_FAT_ENTRY_START;
+
+        /* Calculate the relative cluster.  */
+        relative_sector =  logical_sector -  (((ULONG)media_ptr -> fx_media_data_sector_start) +
+                                              (((ULONG)cluster - FX_FAT_ENTRY_START) *
+                                               ((ULONG)media_ptr -> fx_media_sectors_per_cluster)));
+    }
+    else
+    {
+
+        /* Clear the cluster and the relative sector.  */
+        cluster =  0;
+        relative_sector =  0;
+    }
+
+    /* Read the logical directory sector.  */
+    status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) entry_ptr -> fx_dir_entry_log_sector,
+                                              media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
+
+    /* Determine if an error occurred.  */
+    if (status != FX_SUCCESS)
+    {
+
+        /* Return the error status.  */
+        return(status);
+    }
+
+    /* Setup a pointer into the buffer.  */
+    sector_base_ptr = (UCHAR *)media_ptr -> fx_media_memory_buffer;
+    work_ptr =  sector_base_ptr + (UINT)entry_ptr -> fx_dir_entry_byte_offset;
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    /* Initialize data for fault tolerant. */
+    changed_ptr = work_ptr;
+    changed_size = 0;
+    changed_offset = entry_ptr -> fx_dir_entry_byte_offset;
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Determine if a long file name is present.  */
+    if (entry_ptr -> fx_dir_entry_long_name_present)
+    {
+
+        /* Yes, long name is present - prepare short name and write out this name.  */
+        for (len = 0, i = 0, dotpos = 0, dotfound = 0; entry_ptr -> fx_dir_entry_name[len]; len++)
+        {
+
+            /* Check for a dot.  */
+            if (entry_ptr -> fx_dir_entry_name[len] == '.')
+            {
+
+                /* Check for leading dot. */
+                if (len == 0)
+                {
+                    /* Yes, this is a leading dot. */
+                    continue;
+                }
+
+                /* Yes, a dot is present.  From this position the extension will
+                   be written.  */
+                dotfound = i;
+                dotpos   = len + 1;
+                continue;
+            }
+
+            /* Check for non-space and within the short file name length.  */
+            if ((entry_ptr -> fx_dir_entry_name[len] != ' ') && (i < 8))
+            {
+
+                /* Copy characters into the short file name area.  */
+                shortname[i] = entry_ptr -> fx_dir_entry_name[len];
+                i++;
+            }
+        }
+
+        /* Fill remaining short file name with spaces.  */
+        for (j = i; j < FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE; j++)
+        {
+            shortname[j] =  ' ';
+        }
+
+        /* Determine if a dot was encountered.  */
+        if (dotpos)
+        {
+
+            /* Process relative to the dot position.  */
+            if (entry_ptr -> fx_dir_entry_name[dotpos])
+            {
+                shortname[8] = entry_ptr -> fx_dir_entry_name[dotpos++];
+            }
+            if (entry_ptr -> fx_dir_entry_name[dotpos])
+            {
+                shortname[9] = entry_ptr -> fx_dir_entry_name[dotpos++];
+            }
+            if (entry_ptr -> fx_dir_entry_name[dotpos])
+            {
+                shortname[10] = entry_ptr -> fx_dir_entry_name[dotpos++];
+            }
+
+            /* Determine if additional spaces are needed.  */
+            i = dotfound;
+
+            for (; dotfound <= 7; dotfound++)
+            {
+                /* Add space...  */
+                shortname[dotfound] = ' ';
+            }
+        }
+
+        /* Each entry contains 13 unicode entries.  Calculate the remainder.  */
+        if (len % 13 == 0)
+        {
+            card =  len / 13;
+        }
+        else
+        {
+            card =  len / 13 + 1;
+        }
+
+        /* Default the name match to true.  */
+        match =  FX_TRUE;
+
+        /* Loop through the newly derived short name and the original name and look
+           for a non-matching character.  */
+        l =  0;
+        k =  0;
+        while (k < FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE)
+        {
+
+            /* Determine if a space is detected in the short name. If so,
+               advance to the extension index.  */
+            if (shortname[k] == ' ')
+            {
+
+                /* The first pad space was detected. First, check for a name
+                   without an extension.  */
+                if (entry_ptr -> fx_dir_entry_name[l] == FX_NULL)
+                {
+
+                    /* All is okay, get out of the loop!  */
+                    break;
+                }
+
+                /* Now check for a period in the long name... if not, there is a non-match!  */
+                if (entry_ptr -> fx_dir_entry_name[l] != '.')
+                {
+
+                    /* Set the match flag to false and exit the loop.  */
+                    match =  FX_FALSE;
+                    break;
+                }
+
+                /* Otherwise move short file name index to the extension area and
+                   increment the long file name index.  */
+                k =  8;
+                l++;
+
+                /* Restart the loop at the top.  */
+                continue;
+            }
+
+            /* Check for the dot for the 8.3 match... it is no longer in the
+               shortname but possibly still present in the long name.  */
+            if ((k == 8) && (entry_ptr -> fx_dir_entry_name[l] == '.'))
+            {
+
+                /* Yes, handle the implicit dot in the shortname by
+                   positioning past it in the long name.  */
+                l++;
+            }
+
+            /* Do the names match?  */
+            if (shortname[k] != entry_ptr -> fx_dir_entry_name[l])
+            {
+
+                /* No, the names do not match, set the match flag to false and
+                   exit the loop.  */
+                match =  FX_FALSE;
+                break;
+            }
+
+            /* Move the indices forward.  */
+            k++;
+            l++;
+        }
+
+        /* Check if there is a dot in the name, but no extension in the short name.  In this case, 
+           we should create a mangled short name.  */
+        if ((dotpos) && (shortname[8] == ' '))
+        {
+        
+            /* Something left.. the names do not match!  */
+            match =  FX_FALSE;
+        }
+
+        /* One final check to make sure there is nothing left on the long file name.  */
+        if (entry_ptr -> fx_dir_entry_name[l])
+        {
+
+            /* Something left.. the names do not match!  */
+            match =  FX_FALSE;
+        }
+
+        /* Determine if the derived short name matches exactly the long file name. If so
+           we don't need to mangle the name with a numeric value based on its entry.  */
+        if (match == FX_FALSE)
+        {
+
+            /* Name does not match, create a mangled name.  */
+
+            /* Generate short file name from LFN.  */
+            entry = entry_ptr -> fx_dir_entry_number;
+
+            /* Name suffice is between 000 and FFFF in hex, calculate this short file
+               name's numeric component.  */
+            entry = entry % 0x10000;
+
+            /* Build short name of the format xxx~NNNN.ext.  */
+            if (i > 3)
+            {
+                i = 3;
+            }
+            shortname[i++] = '~';
+
+            /* Loop to build the numeric part of the name.  */
+            for (l = 0; l < 4; l++)
+            {
+                
+                /* Shift down the entry number based on the numeric position.  */
+                if (l == 0)
+                {
+                    temp =  ((entry >> 12) & 0xf);
+                }
+                else if (l == 1)
+                {
+                     temp = ((entry >> 8) & 0xf);
+                }
+                else if (l == 2)
+                {
+                     temp = ((entry >> 4) & 0xf);
+                }
+                else
+                {
+                     temp = ((entry) & 0xf);
+                }
+                
+                /* Now build hex value.  */
+                if (temp > 9)
+                    shortname[i++] =  (CHAR)('A' + (temp - 10));
+                else
+                    shortname[i++] =  (CHAR)('0' + temp);
+            }
+        }
+
+        /* Set end of short string to NULL.   */
+        shortname[11] = 0;
+
+        /* Determine if the first character of the short file name is the directory free
+           value. If so, it must be changed.  */
+        if (((UCHAR)shortname[0] == (UCHAR)FX_DIR_ENTRY_FREE) && (delete_flag == FX_FALSE))
+        {
+
+            /* Change to 0x8F to be compatible with what DOS does.  */
+            shortname[0] =  (CHAR)0x8F;
+        }
+
+        /* Loop to convert the new short file name to upper case.  */
+        for (i = 0; i < (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE); i++)
+        {
+
+            /* Pickup shortname character.  */
+            alpha = shortname[i];
+
+            /* Determine if character is lower case.  */
+            if ((alpha >= 'a') && (alpha <= 'z'))
+            {
+
+                /* Store the character - converted to upper case.  */
+                alpha =  (CHAR)(alpha - ((CHAR)0x20));
+            }
+
+            /* Now store the short name character.  */
+            shortname[i] =  alpha;
+        }
+
+        /* Determine if there already is a short name and we are not deleting the entry.  */
+        if (entry_ptr -> fx_dir_entry_short_name[0] != 0)
+        {
+
+            /* Yes, override the calculated shortname with the original 8.3 name.  */
+
+            /* Clear the short file name area.  */
+            for (i = 0; i < FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE; i++)
+            {
+                shortname[i] = ' ';
+            }
+
+            /* Loop to copy the original short file name.  */
+            for (i = 0, j = 0; j < FX_DIR_NAME_SIZE; i++, j++)
+            {
+
+                /* Check for end of copy conditions.  */
+                if ((UCHAR)entry_ptr -> fx_dir_entry_short_name[i] == '.')
+                {
+                    break;
+                }
+                if ((UCHAR)entry_ptr -> fx_dir_entry_short_name[i] == 0)
+                {
+                    break;
+                }
+
+                /* Pickup the character.  */
+                alpha =  entry_ptr -> fx_dir_entry_short_name[i];
+
+                /* Copy file name character.  */
+                shortname[j] =  alpha;
+            }
+
+            /* Determine if there is anything left in the short file name.  */
+            if ((UCHAR)entry_ptr -> fx_dir_entry_short_name[i] != 0)
+            {
+
+                /* Pickup remaining characters.  */
+                for (i++, j = FX_DIR_NAME_SIZE; j < FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE; i++, j++)
+                {
+
+                    /* If NULL is encountered, stop the copying.  */
+                    if ((UCHAR)entry_ptr -> fx_dir_entry_short_name[i] == 0)
+                    {
+                        break;
+                    }
+
+                    /* Pickup the character.  */
+                    alpha =  entry_ptr -> fx_dir_entry_short_name[i];
+
+                    /* Copy file name character.  */
+                    shortname[j] =  alpha;
+                }
+            }
+
+            /* Loop to make sure the short name is upper case.  */
+            for (j = 0; j < (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE); j++)
+            {
+
+                /* Pickup the character.  */
+                alpha =  shortname[j];
+
+                /* Determine if character is lower case.  */
+                if ((alpha >= 'a') && (alpha <= 'z'))
+                {
+
+                    /* Store the character - converted to upper case.  */
+                    alpha =  (CHAR)(alpha - ((CHAR)0x20));
+                }
+
+                /* Copy file name character.  */
+                shortname[j] =  alpha;
+            }
+
+            /* Determine if the first character of the short file name is the directory free
+               value. If so, it must be changed.  */
+            if (((UCHAR)shortname[0]) == ((UCHAR)FX_DIR_ENTRY_FREE))
+            {
+
+                /* Change to 0x8F to be compatible with what DOS does.  */
+                shortname[0] =  (CHAR)0x8F;
+            }
+        }
+
+        /* Loop to calculate the checksum.  */
+        for (i = checksum = 0; i < FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE; i++)
+        {
+
+            /* Calculate the checksum.  */
+            checksum = (UCHAR)((UCHAR)(((checksum & 1) << 7) | ((checksum & (UCHAR)0xfe) >> 1)) + shortname[i]);
+        }
+
+        /* Set the last entry mark.  */
+        work_ptr[0] =  (UCHAR)(0x40 | card);
+
+        /* Loop to process remainder of long file name entry.  */
+        while (card > 0)
+        {
+
+            /* Clear eof marker.  */
+            eof_marker = 0;
+
+            /* Determine if the entry is free.  */
+            if ((UCHAR)shortname[0] == (UCHAR)FX_DIR_ENTRY_FREE)
+            {
+                /* Yes, place delete marker.  */
+                work_ptr[0] =  (UCHAR)FX_DIR_ENTRY_FREE;
+            }
+
+            /* Setup various long file name fields.  */
+            work_ptr[11] = FX_LONG_NAME;
+            work_ptr[12] = 0;
+            work_ptr[13] = checksum;
+            work_ptr[26] = 0;
+            work_ptr[27] = 0;
+
+            /* Loop through file name fields.  */
+            for (i = 1, j = 13 * (card - 1); i < FX_DIR_ENTRY_SIZE; i += 2)
+            {
+
+                /* Process relative to specific fields.  */
+                if ((i == 11) || (i == 26))
+                {
+                    continue;
+                }
+
+                if (i == 13)
+                {
+                    i = 12;
+                    continue;
+                }
+
+                /* Determine if the EOF marker is present.  */
+                if (eof_marker)
+                {
+
+                    work_ptr[i] = eof_marker;
+                    work_ptr[i + 1] = eof_marker;
+                }
+                else
+                {
+                    work_ptr[i] = (UCHAR)entry_ptr -> fx_dir_entry_name[j];
+                    work_ptr[i + 1] = 0;
+                }
+
+                if (entry_ptr -> fx_dir_entry_name[j] == 0)
+                {
+
+                    /* end of name, pad with 0xff.  */
+                    eof_marker =  (UCHAR)0xff;
+                }
+
+                j++;
+            }
+
+            /* Move to the next directory entry.  */
+            work_ptr += FX_DIR_ENTRY_SIZE;
+            byte_offset += FX_DIR_ENTRY_SIZE;
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+            /* Update changed_size. */
+            changed_size += FX_DIR_ENTRY_SIZE;
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+            /* Determine if the entry overlaps into the next sector.  */
+            if (byte_offset >= media_ptr -> fx_media_bytes_per_sector)
+            {
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                if (media_ptr -> fx_media_fault_tolerant_enabled)
+                {
+
+                    /* Redirect this request to log file. */
+                    status = _fx_fault_tolerant_add_dir_log(media_ptr, logical_sector, changed_offset, changed_ptr, changed_size);
+                }
+                else
+                {
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                    /* Write current logical sector out.  */
+                    status =  _fx_utility_logical_sector_write(media_ptr, (ULONG64) logical_sector,
+                                                               sector_base_ptr, ((ULONG) 1), FX_DIRECTORY_SECTOR);
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                }
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                /* Determine if an error occurred.  */
+                if (status != FX_SUCCESS)
+                {
+
+                    /* Return the error status.  */
+                    return(status);
+                }
+
+                /* Determine if we are in the root directory.  */
+                if (logical_sector >= (ULONG)(media_ptr -> fx_media_data_sector_start))
+                {
+
+                    /* Determine the next sector of the directory entry.  */
+                    if (relative_sector < (media_ptr -> fx_media_sectors_per_cluster - 1))
+                    {
+
+                        /* More sectors in this cluster.  */
+
+                        /* Simply increment the logical sector.  */
+                        logical_sector++;
+
+                        /* Increment the relative sector.  */
+                        relative_sector++;
+                    }
+                    else
+                    {
+
+                        /* We need to move to the next cluster.  */
+
+                        /* Pickup the next cluster.  */
+                        status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
+
+                        /* Check for I/O error.  */
+                        if (status != FX_SUCCESS)
+                        {
+
+                            /* Return error code.  */
+                            return(status);
+                        }
+
+                        /* Copy next cluster to the current cluster.  */
+                        cluster =  next_cluster;
+
+                        /* Check the value of the new cluster - it must be a valid cluster number
+                           or something is really wrong!  */
+                        if ((cluster < FX_FAT_ENTRY_START) || (cluster >= media_ptr -> fx_media_fat_reserved))
+                        {
+
+                            /* Send error message back to caller.  */
+                            return(FX_FILE_CORRUPT);
+                        }
+
+                        /* Setup the relative sector (this is zero for subsequent cluster.  */
+                        relative_sector =  0;
+
+                        /* Calculate the next logical sector.  */
+                        logical_sector =   ((ULONG)media_ptr -> fx_media_data_sector_start) +
+                            (((ULONG)cluster - FX_FAT_ENTRY_START) *
+                             ((ULONG)media_ptr -> fx_media_sectors_per_cluster));
+                    }
+                }
+                else
+                {
+
+                    /* Increment the logical sector.  */
+                    logical_sector++;
+
+                    /* Determine if the logical sector is valid.  */
+                    if (logical_sector >= (ULONG)(media_ptr -> fx_media_data_sector_start))
+                    {
+
+                        /* We have exceeded the root directory.  */
+
+                        /* Send error message back to caller.  */
+                        return(FX_FILE_CORRUPT);
+                    }
+                }
+
+                /* Read the sector.  */
+                status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) logical_sector,
+                                                          media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
+
+                /* Determine if an error occurred.  */
+                if (status != FX_SUCCESS)
+                {
+
+                    /* Return the error status.  */
+                    return(status);
+                }
+
+                /* Setup logical sector.  */
+                sector_base_ptr = media_ptr -> fx_media_memory_buffer;
+
+                /* Setup a fresh byte offset.  */
+                byte_offset = 0;
+
+                /* Setup a new pointer into the buffer.  */
+                work_ptr = sector_base_ptr;
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                /* Initialize data for fault tolerant. */
+                changed_ptr = work_ptr;
+                changed_size = 0;
+                changed_offset = 0;
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+            }
+
+            /* Decrement loop control.  */
+            card--;
+            work_ptr[0] = (UCHAR)card;
+        }
+
+        /* Determine if there is a short name.  */
+        if (entry_ptr -> fx_dir_entry_short_name[0] == 0)
+        {
+
+            /* Loop to copy the new short file name.  */
+            for (i = 0; i < (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE); i++)
+            {
+
+                /* Pickup shortname character.  */
+                alpha = shortname[i];
+
+                /* Now store the short name character.  */
+                *work_ptr++ =  (UCHAR)alpha;
+            }
+        }
+        else
+        {
+
+            /* Clear the short file name area.  */
+            for (i = 0; i < FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE; i++)
+            {
+                work_ptr[i] = ' ';
+            }
+
+            /* Loop to copy the old short file name.  */
+            for (i = 0, j = 0; j < FX_DIR_NAME_SIZE; i++, j++)
+            {
+
+                /* Check for end of copy conditions.  */
+                if ((UCHAR)entry_ptr -> fx_dir_entry_short_name[i] == '.')
+                {
+                    break;
+                }
+                if ((UCHAR)entry_ptr -> fx_dir_entry_short_name[i] == 0)
+                {
+                    break;
+                }
+
+                /* Copy file name character.  */
+                work_ptr[j] =  (UCHAR)entry_ptr -> fx_dir_entry_short_name[i];
+            }
+
+            /* Determine if there is anything left in the short file name.  */
+            if ((UCHAR)entry_ptr -> fx_dir_entry_short_name[i] != 0)
+            {
+
+                /* Pickup remaining characters.  */
+                for (i++, j = FX_DIR_NAME_SIZE; j < FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE; i++, j++)
+                {
+
+                    /* If NULL is encountered, stop the copying.  */
+                    if ((UCHAR)entry_ptr -> fx_dir_entry_short_name[i] == 0)
+                    {
+                        break;
+                    }
+
+                    /* Copy file name character.  */
+                    work_ptr[j] =  (UCHAR)entry_ptr -> fx_dir_entry_short_name[i];
+                }
+            }
+
+            /* Adjust the work pointer accordingly.  */
+            work_ptr += (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE);
+        }
+    }
+    else
+    {
+
+        /* Determine if long name was shorted.  */
+        if (entry_ptr -> fx_dir_entry_long_name_shorted > 0)
+        {
+
+            /* Check for a valid short name.  */
+            if ((UCHAR)(0x40 | entry_ptr -> fx_dir_entry_long_name_shorted) == (UCHAR)(*work_ptr))
+            {
+
+                /* Loop through the file name.  */
+                for (j = 0; j < entry_ptr -> fx_dir_entry_long_name_shorted; j++)
+                {
+
+                    /* Check for a free entry to be written.  */
+                    if ((UCHAR)entry_ptr -> fx_dir_entry_name[0] == (UCHAR)FX_DIR_ENTRY_FREE)
+                    {
+                        /* Delete long parts.  */
+                        work_ptr[0] =  (UCHAR)FX_DIR_ENTRY_FREE;
+                    }
+
+                    /* Setup pointers for the name write.  */
+                    work_ptr += FX_DIR_ENTRY_SIZE;
+                    byte_offset += FX_DIR_ENTRY_SIZE;
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                    /* Update changed_size. */
+                    changed_size += FX_DIR_ENTRY_SIZE;
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                    /* Determine if the write is within the current sector.   */
+                    if (byte_offset >= media_ptr -> fx_media_bytes_per_sector)
+                    {
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                        if (media_ptr -> fx_media_fault_tolerant_enabled)
+                        {
+
+                            /* Redirect this request to log file. */
+                            status = _fx_fault_tolerant_add_dir_log(media_ptr, (ULONG64) logical_sector, changed_offset, changed_ptr, changed_size);
+                        }
+                        else
+                        {
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                            /* Write the current sector out.  */
+                            status =  _fx_utility_logical_sector_write(media_ptr, (ULONG64) logical_sector,
+                                                                       sector_base_ptr, ((ULONG) 1), FX_DIRECTORY_SECTOR);
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                        }
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                        /* Determine if an error occurred.  */
+                        if (status != FX_SUCCESS)
+                        {
+
+                            /* Return the error status.  */
+                            return(status);
+                        }
+
+                        /* Determine if we are in the root directory.  */
+                        if (logical_sector >= (ULONG)(media_ptr -> fx_media_data_sector_start))
+                        {
+
+                            /* Determine the next sector of the directory entry.  */
+                            if (relative_sector < (media_ptr -> fx_media_sectors_per_cluster - 1))
+                            {
+
+                                /* More sectors in this cluster.  */
+
+                                /* Simply increment the logical sector.  */
+                                logical_sector++;
+
+                                /* Increment the relative sector.  */
+                                relative_sector++;
+                            }
+                            else
+                            {
+
+                                /* We need to move to the next cluster.  */
+
+                                /* Pickup the next cluster.  */
+                                status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
+
+                                /* Check for I/O error.  */
+                                if (status != FX_SUCCESS)
+                                {
+
+                                    /* Return error code.  */
+                                    return(status);
+                                }
+
+                                /* Copy next cluster to the current cluster.  */
+                                cluster =  next_cluster;
+
+                                /* Check the value of the new cluster - it must be a valid cluster number
+                                   or something is really wrong!  */
+                                if ((cluster < FX_FAT_ENTRY_START) || (cluster >= media_ptr -> fx_media_fat_reserved))
+                                {
+
+                                    /* Send error message back to caller.  */
+                                    return(FX_FILE_CORRUPT);
+                                }
+
+                                /* Setup the relative sector (this is zero for subsequent cluster.  */
+                                relative_sector =  0;
+
+                                /* Calculate the next logical sector.  */
+                                logical_sector =   ((ULONG)media_ptr -> fx_media_data_sector_start) +
+                                    (((ULONG)cluster - FX_FAT_ENTRY_START) *
+                                     ((ULONG)media_ptr -> fx_media_sectors_per_cluster));
+                            }
+                        }
+                        else
+                        {
+
+                            /* Increment the logical sector.  */
+                            logical_sector++;
+
+                            /* Determine if the logical sector is valid.  */
+                            if (logical_sector >= (ULONG)(media_ptr -> fx_media_data_sector_start))
+                            {
+
+                                /* We have exceeded the root directory.  */
+
+                                /* Send error message back to caller.  */
+                                return(FX_FILE_CORRUPT);
+                            }
+                        }
+
+                        /* Read the next logical sector.  */
+                        status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) logical_sector,
+                                                                  media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
+
+                        /* Determine if an error occurred.  */
+                        if (status != FX_SUCCESS)
+                        {
+
+                            /* Return the error status.  */
+                            return(status);
+                        }
+
+                        /* Move to the next sector buffer.  */
+                        sector_base_ptr = media_ptr -> fx_media_memory_buffer;
+
+                        /* Setup new buffer pointers.  */
+                        byte_offset =  0;
+                        work_ptr = sector_base_ptr;
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                        /* Initialize data for fault tolerant. */
+                        changed_ptr = work_ptr;
+                        changed_size = 0;
+                        changed_offset = 0;
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+                    }
+                }
+            }
+        }
+
+        /* This is an 8.3 name.  First clear the directory name.  */
+        for (j = 0; j < FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE; j++)
+        {
+            work_ptr[j] = ' ';
+        }
+
+        /* Copy leading dots in case of first two entries of a directory.  */
+        for (i = 0; (UCHAR)entry_ptr -> fx_dir_entry_name[i] == '.'; i++)
+        {
+            work_ptr[i] = '.';
+        }
+
+        /* Determine if there are more characters to copy.  */
+        if ((UCHAR)entry_ptr -> fx_dir_entry_name[i] != 0)
+        {
+
+            /* Copy directory name.  */
+            for (i = 0, j = 0; j < FX_DIR_NAME_SIZE; i++, j++)
+            {
+
+                /* Check for end of copy conditions.  */
+                if ((UCHAR)entry_ptr -> fx_dir_entry_name[i] == '.')
+                {
+                    break;
+                }
+                if ((UCHAR)entry_ptr -> fx_dir_entry_name[i] == 0)
+                {
+                    break;
+                }
+
+                /* Pickup shortname character.  */
+                alpha = entry_ptr -> fx_dir_entry_name[i];
+
+                /* Determine if character is lower case.  */
+                if ((alpha >= 'a') && (alpha <= 'z'))
+                {
+
+                    /* Store the character - converted to upper case.  */
+                    alpha =  (CHAR)(alpha - ((CHAR)0x20));
+                }
+
+                /* Copy a name character.  */
+                work_ptr[j] =  (UCHAR)alpha;
+            }
+        }
+
+        /* Determine if there are more characters in the name.  */
+        if ((UCHAR)entry_ptr -> fx_dir_entry_name[i] != 0)
+        {
+
+            /* Loop to copy the remainder of the name.  */
+            for (i++, j = FX_DIR_NAME_SIZE; j < FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE; i++, j++)
+            {
+
+                /* Check for end of copy conditions.  */
+                if ((UCHAR)entry_ptr -> fx_dir_entry_name[i] == 0)
+                {
+                    break;
+                }
+
+                /* Pickup shortname character.  */
+                alpha = entry_ptr -> fx_dir_entry_name[i];
+
+                /* Determine if character is lower case.  */
+                if ((alpha >= 'a') && (alpha <= 'z'))
+                {
+
+                    /* Store the character - converted to upper case.  */
+                    alpha =  (CHAR)(alpha - ((CHAR)0x20));
+                }
+
+                /* Copy a name character.  */
+                work_ptr[j] =  (UCHAR)alpha;
+            }
+        }
+
+        /* Move to the next entry.  */
+        work_ptr += (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE);
+    }
+
+    /* Write out the 8.3 part of the name. */
+
+    /* Copy the attribute into the destination.  */
+    *work_ptr++ =  entry_ptr -> fx_dir_entry_attributes;
+
+    /* Copy the reserved byte.  */
+    *work_ptr++ =  entry_ptr -> fx_dir_entry_reserved;
+
+    /* Copy the created time in milliseconds.  */
+    *work_ptr++ =  entry_ptr -> fx_dir_entry_created_time_ms;
+
+    /* Copy the created time.  */
+    _fx_utility_16_unsigned_write(work_ptr, entry_ptr -> fx_dir_entry_created_time);
+    work_ptr =  work_ptr + 2;  /* Always 2 bytes  */
+
+    /* Copy the created date.  */
+    _fx_utility_16_unsigned_write(work_ptr, entry_ptr -> fx_dir_entry_created_date);
+    work_ptr =  work_ptr + 2;  /* Always 2 bytes  */
+
+    /* Copy the last accessed date.  */
+    _fx_utility_16_unsigned_write(work_ptr, entry_ptr -> fx_dir_entry_last_accessed_date);
+    work_ptr =  work_ptr + 2;  /* Always 2 bytes  */
+
+    /* Determine if a FAT32 entry is present.  */
+    if (media_ptr -> fx_media_32_bit_FAT)
+    {
+
+        /* Yes, FAT32 is present, store upper half of cluster.  */
+        temp = (entry_ptr -> fx_dir_entry_cluster >> 16);
+        _fx_utility_16_unsigned_write(work_ptr, temp);
+    }
+    else
+    {
+
+        /* No, FAT16 or FAT12 is present, just write a 0 for
+           the upper half of the cluster.  */
+        _fx_utility_16_unsigned_write(work_ptr, 0);
+    }
+
+    /* Advance the entry pointer.  */
+    work_ptr =  work_ptr + 2;  /* Always 2 bytes  */
+
+    /* Copy the time into the destination.  */
+    _fx_utility_16_unsigned_write(work_ptr, entry_ptr -> fx_dir_entry_time);
+    work_ptr =  work_ptr + 2;  /* Always 2 bytes  */
+
+    /* Copy the date into the destination.  */
+    _fx_utility_16_unsigned_write(work_ptr, entry_ptr -> fx_dir_entry_date);
+    work_ptr =  work_ptr + 2;  /* Always 2 bytes  */
+
+    /* Copy the starting cluster into the destination.  */
+    _fx_utility_16_unsigned_write(work_ptr, (UINT)entry_ptr -> fx_dir_entry_cluster);
+    work_ptr =  work_ptr + 2;  /* Always 2 bytes  */
+
+    /* Copy the file size into the destination.  */
+    _fx_utility_32_unsigned_write(work_ptr, (ULONG)entry_ptr -> fx_dir_entry_file_size);
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    /* Update changed_size. */
+    changed_size += FX_DIR_ENTRY_SIZE;
+
+    if (media_ptr -> fx_media_fault_tolerant_enabled &&
+        (media_ptr -> fx_media_fault_tolerant_state & FX_FAULT_TOLERANT_STATE_STARTED))
+    {
+
+        /* Redirect this request to log file. */
+        status = _fx_fault_tolerant_add_dir_log(media_ptr, (ULONG64) logical_sector, changed_offset, changed_ptr, changed_size);
+    }
+    else
+    {
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Write the directory sector to the media.  */
+        status =  _fx_utility_logical_sector_write(media_ptr, (ULONG64) logical_sector,
+                                                   sector_base_ptr, ((ULONG) 1), FX_DIRECTORY_SECTOR);
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    }
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Determine if an error occurred.  */
+    if (status != FX_SUCCESS)
+    {
+
+        /* Return the error status.  */
+        return(status);
+    }
+
+#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
+
+    /* Determine if there is a previously found directory entry in the directory
+       search cache.  */
+    if (media_ptr -> fx_media_last_found_name[0])
+    {
+
+        /* Determine if the cached search directory entry matches the directory entry being
+           written.  */
+        if ((entry_ptr -> fx_dir_entry_log_sector == media_ptr -> fx_media_last_found_entry.fx_dir_entry_log_sector) &&
+            (entry_ptr -> fx_dir_entry_byte_offset == media_ptr -> fx_media_last_found_entry.fx_dir_entry_byte_offset))
+        {
+
+            /* Yes, this entry is the same as the one currently in the directory search cache.
+               Update various fields in the directory search cache with the information being
+               written now.  */
+            media_ptr -> fx_media_last_found_entry.fx_dir_entry_cluster =         entry_ptr -> fx_dir_entry_cluster;
+            media_ptr -> fx_media_last_found_entry.fx_dir_entry_file_size =       entry_ptr -> fx_dir_entry_file_size;
+            media_ptr -> fx_media_last_found_entry.fx_dir_entry_attributes =      entry_ptr -> fx_dir_entry_attributes;
+            media_ptr -> fx_media_last_found_entry.fx_dir_entry_time =            entry_ptr -> fx_dir_entry_time;
+            media_ptr -> fx_media_last_found_entry.fx_dir_entry_date =            entry_ptr -> fx_dir_entry_date;
+            media_ptr -> fx_media_last_found_entry.fx_dir_entry_reserved =        entry_ptr -> fx_dir_entry_reserved;
+            media_ptr -> fx_media_last_found_entry.fx_dir_entry_created_time_ms = entry_ptr -> fx_dir_entry_created_time_ms;
+            media_ptr -> fx_media_last_found_entry.fx_dir_entry_created_time =    entry_ptr -> fx_dir_entry_created_time;
+            media_ptr -> fx_media_last_found_entry.fx_dir_entry_created_date =    entry_ptr -> fx_dir_entry_created_date;
+        }
+    }
+#endif
+
+    /* Return success to the caller.  */
+    return(FX_SUCCESS);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_exFAT_entry_read.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_exFAT_entry_read.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_exFAT_entry_read.c	(revision 30)
@@ -0,0 +1,718 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+
+
+#ifdef FX_ENABLE_EXFAT
+#include "fx_utility.h"
+#include "fx_directory_exFAT.h"
+#include "fx_directory.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_directory_exFAT_entry_read                      PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function reads the supplied directory entry from the supplied  */
+/*    source directory.  If the supplied directory entry is NULL, then    */
+/*    the root directory is assumed.                                      */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    source_dir                            Source directory entry        */
+/*    entry_ptr                             Directory entry number        */
+/*    destination_ptr                       Pointer to destination for    */
+/*                                            the directory entry         */
+/*    hash                                  Hash value of the file name   */
+/*    skip                                  Skip reading file name        */
+/*    unicode_name                          Destination for unicode name  */
+/*    unicode_length                        Destination for unicode name  */
+/*                                            length                      */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*    *entry_ptr should point to the 8:3 entry if it is a long name       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_FAT_entry_read            Read a FAT entry              */
+/*    _fx_utility_logical_sector_read       Read directory sector         */
+/*    _fx_utility_16_unsigned_read          Read a USHORT from memory     */
+/*    _fx_utility_32_unsigned_read          Read a ULONG from memory      */
+/*    _fx_utility_64_unsigned_read          Read a ULONG64 from memory    */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    _fx_directory_entry_read                                            */
+/*    _fx_directory_free_search                                           */
+/*    _fx_directory_next_full_entry_find                                  */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_directory_exFAT_entry_read(FX_MEDIA *media_ptr, FX_DIR_ENTRY *source_dir,
+                                     ULONG *entry_ptr, FX_DIR_ENTRY *destination_ptr,
+                                     UINT hash, UINT skip, UCHAR *unicode_name, UINT *unicode_length)
+{
+
+UINT    status = FX_SUCCESS;
+UCHAR   i;
+UCHAR   j;
+ULONG   cluster = 0, next_cluster = 0;
+ULONG64 next_logical_sector;
+UINT    relative_cluster;
+UINT    relative_sector = 0;
+ULONG64 logical_sector;
+ULONG   byte_offset;
+ULONG   bytes_per_cluster;
+UCHAR  *read_ptr;
+UCHAR   secondary_count;
+UCHAR   name_length = 0;
+UCHAR   name_pos = 0;
+UCHAR   copy_size = 0;
+USHORT  checksum = 0;
+USHORT  file_checksum;
+ULONG   date_time;
+UCHAR   dont_use_fat;
+ULONG   clusters_count = 0;
+
+
+    /* Calculate the byte offset of this directory entry.  */
+    byte_offset =  (*entry_ptr) * FX_DIR_ENTRY_SIZE;
+
+    /* Calculate the number of bytes per cluster.  */
+    bytes_per_cluster =  ((ULONG)media_ptr -> fx_media_bytes_per_sector) *
+        ((ULONG)media_ptr -> fx_media_sectors_per_cluster);
+
+    /* Now determine the relative cluster in the sub-directory file.  */
+    relative_cluster =   (UINT)(byte_offset / bytes_per_cluster);
+
+    /* Calculate the byte offset within the cluster.  */
+    byte_offset =  byte_offset % bytes_per_cluster;
+
+    /* Now figure out the relative sector within the cluster.  */
+    relative_sector =    (UINT)(byte_offset / ((ULONG)media_ptr -> fx_media_bytes_per_sector));
+
+    /* Read the directory sector into the internal memory buffer.  */
+
+    /* Determine if there is a sub-directory.  */
+    if (source_dir)
+    {
+
+        /* Yes, setup the starting cluster to that of the sub-directory.  */
+        cluster =  source_dir -> fx_dir_entry_cluster;
+
+        /* Save the cluster count for the directory entry.  */
+        clusters_count = (ULONG)((source_dir -> fx_dir_entry_file_size + bytes_per_cluster - 1) / bytes_per_cluster - 1);
+    }
+    else
+    {
+
+        /* No, setup the starting cluster to the exFAT root directory cluster.  */
+        cluster =  media_ptr -> fx_media_root_cluster_32;
+    }
+
+    /* Loop to position to the appropriate cluster.  */
+    for (i = 0;; i++)
+    {
+
+        /* Check the value of the new cluster - it must be a valid cluster number
+           or something is really wrong!  */
+        if ((cluster < FX_FAT_ENTRY_START) || (cluster > FX_RESERVED_1_exFAT))
+        {
+
+            /* Send error message back to caller.  */
+            return(FX_FILE_CORRUPT);
+        }
+
+        /* Read the next cluster. First check if FAT is used.  */
+        if ((source_dir) && (source_dir -> fx_dir_entry_dont_use_fat & 1))
+        {
+
+            /* FAT is not used. Check for file size range.  */
+            if (i >= clusters_count)
+            {
+
+                /* We are at the last cluster, set next cluster to LAST CLUSTER.  */
+                next_cluster =  FX_LAST_CLUSTER_exFAT;
+            }
+            else
+            {
+
+                /* The next cluster is just after the current cluster.  */
+                next_cluster =  cluster + 1;
+            }
+        }
+        else
+        {
+
+            /* FAT is used, call FAT read function to get the next cluster.  */
+            status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
+
+            /* Check for I/O error.  */
+            if (status != FX_SUCCESS)
+            {
+
+                /* Return error code.  */
+                return(status);
+            }
+        }
+
+        /* Are we positioned to the appropriate cluster?  */
+        if (i < relative_cluster)
+        {
+            cluster = next_cluster;
+        }
+        else
+        {
+            break;
+        }
+    }
+
+    /* At this point, the directory data sector needs to be read.  */
+    logical_sector =    ((ULONG)media_ptr -> fx_media_data_sector_start) +
+        (((ULONG64)cluster - FX_FAT_ENTRY_START) *
+         ((ULONG)media_ptr -> fx_media_sectors_per_cluster)) +
+        relative_sector;
+
+    /* Determine if next sector is in next cluster or in next sector.  */
+    if ((bytes_per_cluster - byte_offset) >= (ULONG)media_ptr -> fx_media_bytes_per_sector)
+    {
+
+        /* Move to the next logical sector.   */
+        next_logical_sector = logical_sector + 1;
+    }
+    else
+    {
+        /* No, calculate the next logical sector.  */
+        if ((next_cluster >= FX_FAT_ENTRY_START) && (next_cluster <= FX_RESERVED_1_exFAT))
+        {
+            next_logical_sector =    ((ULONG)media_ptr -> fx_media_data_sector_start) +
+                (((ULONG64)next_cluster - FX_FAT_ENTRY_START) * ((ULONG)media_ptr -> fx_media_sectors_per_cluster));
+        }
+        else
+        {
+            next_logical_sector = 0; /* No such sector possible.  */
+        }
+    }
+
+    /* Read the logical directory sector.  */
+    status =  _fx_utility_logical_sector_read(media_ptr, ((ULONG64) logical_sector),
+                                              media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
+
+    /* Determine if an error occurred.  */
+    if (status != FX_SUCCESS)
+    {
+
+        /* Return error code.  */
+        return(status);
+    }
+
+    /* Calculate the byte offset within this sector.  */
+    byte_offset =  byte_offset % media_ptr -> fx_media_bytes_per_sector;
+
+
+    /* Setup a pointer into the buffer.  */
+    read_ptr =  (UCHAR *)media_ptr -> fx_media_memory_buffer + (UINT)byte_offset;
+
+    /* Save the logical sector and byte offset in the returned directory entry.  */
+    destination_ptr -> fx_dir_entry_log_sector =       logical_sector;
+    destination_ptr -> fx_dir_entry_next_log_sector =  next_logical_sector;
+    destination_ptr -> fx_dir_entry_byte_offset =      byte_offset;
+
+    /* Clear the short file name information.  */
+    destination_ptr -> fx_dir_entry_long_name_shorted =  0;
+    destination_ptr -> fx_dir_entry_short_name[0]     =  0;
+
+    /* Check if the directory entry type has InUse bit set, or if it is an end marker.  */
+    if ((*read_ptr & FX_EXFAT_ENTRY_TYPE_IN_USE_MASK) || (*read_ptr == FX_EXFAT_DIR_ENTRY_TYPE_END_MARKER))
+    {
+
+        /* Set the directory entry type.  */
+        destination_ptr -> fx_dir_entry_type = *read_ptr;
+    }
+    else
+    {
+
+        /* This is a free entry.  */
+        destination_ptr -> fx_dir_entry_type = FX_EXFAT_DIR_ENTRY_TYPE_FREE;
+    }
+
+    /* Check if the entry is a file directory entry.  */
+    if (destination_ptr -> fx_dir_entry_type != FX_EXFAT_DIR_ENTRY_TYPE_FILE_DIRECTORY)
+    {
+
+        /* The entry is not directory entry, check if we know the type.  */
+        if ((destination_ptr -> fx_dir_entry_type == FX_EXFAT_DIR_ENTRY_TYPE_ALLOCATION_BITMAP) ||
+            (destination_ptr -> fx_dir_entry_type == FX_EXFAT_DIR_ENTRY_TYPE_UP_CASE_TABLE)     ||
+            (destination_ptr -> fx_dir_entry_type == FX_EXFAT_DIR_ENTRY_TYPE_VOLUME_LABEL)      ||
+            (destination_ptr -> fx_dir_entry_type == FX_EXFAT_DIR_ENTRY_TYPE_FREE)              ||
+            (destination_ptr -> fx_dir_entry_type == FX_EXFAT_DIR_ENTRY_TYPE_END_MARKER))
+        {
+
+            /* Known critical primary or free, just skip it. */
+            return(FX_SUCCESS);
+        }
+
+        /* Check if the entry is unknown critical primary directory entry.  */
+        if ((destination_ptr -> fx_dir_entry_type & (FX_EXFAT_ENTRY_TYPE_IMPORTANCE_MASK | FX_EXFAT_ENTRY_TYPE_CATEGORY_MASK)) == 0)
+        {
+
+            /* Yes, it is an unknown critical primary entry. Return error.  */
+            return(FX_MEDIA_INVALID);
+        }
+
+        /* Just ignore.  */
+        return(FX_SUCCESS);
+    }
+
+    /* Calculate checksum for file entry.  */
+    for (j = 0; j < FX_DIR_ENTRY_SIZE; ++j)
+    {
+
+        /* Skip the checksum field.  */
+        if ((j == 2) || (j == 3))
+        {
+            continue;
+        }
+
+        /* Calculate the checksum using the algorithm described in the specification.  */
+        /* Right rotate the checksum by one bit position and add the data.  */
+        checksum = (USHORT)(((checksum >> 1) | (checksum << 15)) + read_ptr[j]);
+    }
+
+    /* Read secondary count field.  */
+    read_ptr++;
+    secondary_count = *read_ptr;
+
+    /* Validate the secondary count field.  */
+    if (secondary_count < 2)
+    {
+
+        /* Something wrong, file entry should have at least 2 entries: stream and filename.  */
+        return(FX_FILE_CORRUPT);
+    }
+
+    /* Save secondary count.  */
+    destination_ptr -> fx_dir_entry_secondary_count =  secondary_count;
+
+    /* exFAT has no short/long name concept, set long name present for compatibility.  */
+    destination_ptr -> fx_dir_entry_long_name_present =  1;
+
+    /* Advance the pointer to the checksum field.  */
+    read_ptr++;
+
+    /* Read checksum field.  */
+    file_checksum = (USHORT)_fx_utility_16_unsigned_read(read_ptr);
+    read_ptr += 2;
+
+    /* Read FileAttributes field.  */
+    destination_ptr -> fx_dir_entry_attributes = (UCHAR)_fx_utility_16_unsigned_read(read_ptr); /* The same order as FAT32 but more unused bits.  */
+
+    /* Skip Reserved1.  */
+    read_ptr += 4;
+
+    /* Read CreatedTimestamp field.  */
+    date_time = _fx_utility_32_unsigned_read(read_ptr);
+    destination_ptr -> fx_dir_entry_created_time = date_time & 0xffff;
+    destination_ptr -> fx_dir_entry_created_date = date_time >> 16;
+    read_ptr += 4;
+
+    /* Read LastModifiedTimestamp.  */
+    date_time = _fx_utility_32_unsigned_read(read_ptr);
+    destination_ptr -> fx_dir_entry_time = date_time & 0xffff;
+    destination_ptr -> fx_dir_entry_date = date_time >> 16;
+    read_ptr += 4;
+
+    /* Read LastAccessedTimestamp.  */
+    date_time = _fx_utility_32_unsigned_read(read_ptr);
+    destination_ptr -> fx_dir_entry_last_accessed_date = date_time >> 16;
+    read_ptr += 4;
+
+    /* Read Create10msIncrement.  */
+    destination_ptr -> fx_dir_entry_created_time_ms = *read_ptr;
+    read_ptr++;
+
+    /* LastModified10msIncrement field is currently ignored.  */
+    read_ptr++;
+
+    /* CreateUtcOffset field is currently ignored.  */
+    read_ptr++;
+
+    /* LastModifiedUtcOffset field is currently ignored.  */
+    read_ptr++;
+
+    /* LastAccessedUtcOffset field is currently ignored.  */
+
+    /* Process all the secondary directory entries.  */
+    for (i = 0; i < secondary_count; ++i)
+    {
+
+        /* Determine if a new sector needs to be read.  */
+        if (byte_offset + FX_DIR_ENTRY_SIZE >= media_ptr -> fx_media_bytes_per_sector)
+        {
+
+            /* Determine the next sector of the directory entry.  */
+            if (relative_sector < (media_ptr -> fx_media_sectors_per_cluster - 1))
+            {
+
+                /* More sectors in this cluster.  */
+
+                /* Simply increment the logical sector.  */
+                logical_sector++;
+
+                /* Increment the relative sector.  */
+                relative_sector++;
+            }
+            else
+            {
+
+                /* We need to move to the next cluster.  */
+
+                /* Read the next cluster. First check if FAT is used.  */
+                if ((source_dir) && (source_dir -> fx_dir_entry_dont_use_fat & 1))
+                {
+
+                    /* FAT is not used. Check for file size range.  */
+                    if (relative_cluster >= clusters_count)
+                    {
+
+                        /* We are at the last cluster, set next cluster to LAST CLUSTER.  */
+                        next_cluster =  FX_LAST_CLUSTER_exFAT;
+                    }
+                    else
+                    {
+
+                        /* The next cluster is just after the current cluster.  */
+                        next_cluster =  cluster + 1;
+                    }
+                }
+                else
+                {
+
+                    /* FAT is used, call FAT read function to get the next cluster.  */
+                    status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
+
+                    /* Check for I/O error.  */
+                    if (status != FX_SUCCESS)
+                    {
+
+                        /* Return error code.  */
+                        return(status);
+                    }
+                }
+
+                /* Copy next cluster to the current cluster.  */
+                cluster =  next_cluster;
+
+                /* Check the value of the new cluster - it must be a valid cluster number
+                   or something is really wrong!  */
+                if ((cluster < FX_FAT_ENTRY_START) || (cluster > FX_RESERVED_1_exFAT))
+                {
+
+                    /* Send error message back to caller.  */
+                    return(FX_FILE_CORRUPT);
+                }
+
+                /* Now increment the relative cluster.  */
+                relative_cluster++;
+
+                /* Setup the relative sector (this is zero for subsequent cluster.  */
+                relative_sector =  0;
+
+                /* Calculate the next logical sector.  */
+                logical_sector =   ((ULONG)media_ptr -> fx_media_data_sector_start) +
+                    (((ULONG64)cluster - FX_FAT_ENTRY_START) *
+                     ((ULONG)media_ptr -> fx_media_sectors_per_cluster));
+            }
+
+            /* Read the new sector.  */
+            status =  _fx_utility_logical_sector_read(media_ptr, ((ULONG64) logical_sector),
+                                                      media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
+
+            /* Check I/O status.  */
+            if (status != FX_SUCCESS)
+            {
+                return(status);
+            }
+
+            /* Set the byte offset to 0 for new sector.  */
+            byte_offset = 0;
+        }
+        else
+        {
+
+            /* Calculate the new byte offset.  */
+            byte_offset += FX_DIR_ENTRY_SIZE;
+        }
+
+        /* Read sub entry.  */
+        read_ptr = (UCHAR *)media_ptr -> fx_media_memory_buffer + (UINT)byte_offset;
+
+        /* Calculate checksum for sub entry.  */
+        for (j = 0; j < FX_DIR_ENTRY_SIZE; ++j)
+        {
+
+            /* Right rotate the checksum by one bit position and add the data.  */
+            checksum = (USHORT)(((checksum >> 1) | (checksum << 15)) + read_ptr[j]);
+        }
+
+        /* Add the entry number to the next entry.  */
+        (*entry_ptr)++;
+
+        /* Check if we are processing the first secondary directory entry.  */
+        if (i == 0)
+        {
+
+            /* Make sure the directory entry type is stream extension.  */
+            if (*read_ptr != FX_EXFAT_DIR_ENTRY_TYPE_STREAM_EXTENSION)
+            {
+
+                /* Something wrong, stream entry should be next to file entry.  */
+                return(FX_FILE_CORRUPT);
+            }
+
+            /* Read stream entry.  */
+
+            /* Advance the pointer to general secondary flags field.  */
+            read_ptr++;
+
+            /* Read NoFatChain field.  */
+            dont_use_fat = ((*read_ptr) >> 1) & 1; /* 0 bit - current */
+
+            /* Check if we have a parent directory.  */
+            if (source_dir)
+            {
+
+                /* Save the dont_use_fat flag for parent directory.  */
+                dont_use_fat = (UCHAR)(dont_use_fat | ((source_dir -> fx_dir_entry_dont_use_fat & 1) << 1)); /* 1st bit parent */
+            }
+
+            /* Put the dont_use_fat flag to the destination.  */
+            destination_ptr -> fx_dir_entry_dont_use_fat =  (CHAR)dont_use_fat;
+
+            /* Skip the reserved1 field.  */
+            read_ptr += 2;
+
+            /* Read the name length field.  */
+            name_length = *read_ptr;
+
+            /* Check if name_length is invalid.  */
+            if (name_length == 0)
+            {
+
+                /* Name length should be at least 1. Return error.  */
+                return(FX_FILE_CORRUPT);
+            }
+
+            /* Advance the pointer to the name hash field.  */
+            read_ptr++;
+
+            /* Hash search */
+            if (skip || (hash && (hash != _fx_utility_16_unsigned_read(read_ptr))))
+            {
+
+                /* Wrong hash, skip filename.  */
+                destination_ptr -> fx_dir_entry_type =  FX_EXFAT_DIR_ENTRY_TYPE_STREAM_EXTENSION;
+                name_length =  0;
+                (*entry_ptr) +=  (ULONG)(secondary_count - 1);
+
+                /* Return success.  */
+                return(FX_SUCCESS);
+            }
+
+            /* Skip name hash and reserved2.  */
+            read_ptr += 4;
+
+            /* Read Valid Data Len. */
+            destination_ptr -> fx_dir_entry_file_size = _fx_utility_64_unsigned_read(read_ptr);
+
+            /* Skip ValidDataLen and reserved3.  */
+            read_ptr += 12;
+            destination_ptr -> fx_dir_entry_cluster = _fx_utility_32_unsigned_read(read_ptr);
+            read_ptr += 4;
+
+            /* Read Data Len.  */
+            destination_ptr -> fx_dir_entry_available_file_size = _fx_utility_64_unsigned_read(read_ptr);
+
+            /* Checks for corruption */
+            if (((destination_ptr -> fx_dir_entry_available_file_size == 0)   &&
+                 (destination_ptr -> fx_dir_entry_cluster       != 0))  ||
+                ((destination_ptr -> fx_dir_entry_available_file_size != 0)   &&
+                 (destination_ptr -> fx_dir_entry_cluster       == 0)))
+            {
+
+                /* Return file corrupt error.  */
+                return(FX_FILE_CORRUPT);
+            }
+
+            /* File System Specification Ver 3.00 */
+            if (destination_ptr -> fx_dir_entry_cluster == 0)
+            {
+
+                /* Don't use FAT by default.  */
+                destination_ptr -> fx_dir_entry_dont_use_fat |=  1;
+            }
+
+            /* Check for directory restrictions.  */
+            if ((destination_ptr -> fx_dir_entry_attributes & FX_DIRECTORY) &&
+                (destination_ptr -> fx_dir_entry_available_file_size != destination_ptr -> fx_dir_entry_file_size))
+            {
+
+                /* Return file corrupt error.  */
+                return(FX_FILE_CORRUPT);
+            }
+
+            /* Check if the directory size exceed file system limits.  */
+            if ((destination_ptr -> fx_dir_entry_attributes & FX_DIRECTORY) &&
+                (destination_ptr -> fx_dir_entry_available_file_size > FX_EXFAT_MAX_DIRECTORY_SIZE))
+            {
+
+                /* Return the no more space error.  */
+                return(FX_NO_MORE_SPACE);
+            }
+        }
+        else
+        {
+
+            /* Check if the entry type is file name directory entry.  */
+            if (*read_ptr == FX_EXFAT_DIR_ENTRY_TYPE_FILE_NAME)
+            {
+
+                /* Skip the entry type and flags field.  */
+                read_ptr += 2;
+
+                /* There are 15 characters in one file name directory entry.  */
+                if (name_length > 15)
+                {
+
+                    /* Set copy size to the max size of one entry.  */
+                    copy_size = 15;
+                }
+                else
+                {
+
+                    /* Set copy size to the acutal remaining length.  */
+                    copy_size = name_length;
+                }
+
+                /* Check if we are requested to return the unicode name.  */
+                if (unicode_name)
+                {
+
+                    /* Loop to copy the unicode file name. from the file name directory entry.  */
+                    for (j = 0; j < copy_size * 2; ++j)
+                    {
+
+                        /* Copy the unicode file name from the file name directory entry.  */
+                        unicode_name[name_pos * 2 + j] = *read_ptr++;
+                    }
+
+                    /* Revert the read pointer for later use.  */
+                    read_ptr -= copy_size * 2;
+                }
+
+                /* Loop to copy the non-unicode file name.  */
+                for (j = 0; j < copy_size; ++j)
+                {
+
+                    /* Copy and convert the file name from the file name directory entry.  */
+                    destination_ptr -> fx_dir_entry_name[name_pos++] = (CHAR)_fx_utility_16_unsigned_read(read_ptr);
+                    read_ptr += 2;
+                }
+
+                /* Modify the name_length to indicate the remaining length.  */
+                name_length = (UCHAR)(name_length - copy_size);
+            }
+            else if (((*read_ptr & (FX_EXFAT_ENTRY_TYPE_IN_USE_MASK | FX_EXFAT_ENTRY_TYPE_IMPORTANCE_MASK | FX_EXFAT_ENTRY_TYPE_CATEGORY_MASK)) ==
+                      (FX_EXFAT_ENTRY_TYPE_IN_USE_MASK | FX_EXFAT_ENTRY_TYPE_CATEGORY_MASK)))
+            {
+
+                /* Unknown critical secondary, we can't work with this directory.  */
+                return(FX_FILE_CORRUPT);
+            }
+        }
+    }
+
+    /* Terminate the entry name string.  */
+    destination_ptr -> fx_dir_entry_name[name_pos] = 0;
+
+    /* Check if we are requested to return the unicode name.  */
+    if (unicode_name)
+    {
+
+        /* Terminate the unicode name string.  */
+        unicode_name[name_pos * 2] = 0;
+        unicode_name[name_pos * 2 + 1] = 0;
+
+        /* Check if we are requested to return the unicode name length.  */
+        if (unicode_length)
+        {
+
+            /* Return the unicode name length.  */
+            *unicode_length = name_pos;
+        }
+    }
+
+    /* Verify checksum.  */
+    if (checksum != file_checksum)
+    {
+
+        /* Return corrupted file error.  */
+        return(FX_FILE_CORRUPT);
+    }
+
+    /* Check if we have found all the file name directory entries.  */
+    if (name_length != 0)
+    {
+
+        /* Return file corrupted error.  */
+        return(FX_FILE_CORRUPT);
+    }
+
+    /* Return success.  */
+    return(FX_SUCCESS);
+}
+
+#endif
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_exFAT_entry_write.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_exFAT_entry_write.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_exFAT_entry_write.c	(revision 30)
@@ -0,0 +1,102 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+
+#ifdef FX_ENABLE_EXFAT
+#include "fx_directory.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_directory_exFAT_entry_write                     PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function writes the supplied directory entry to the specified  */
+/*    logical sector and offset.                                          */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    entry_ptr                             Pointer to directory entry    */
+/*    update_level                          Update level for entry write  */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_exFAT_unicode_entry_write                             */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    fx_directory_attributes_set                                         */
+/*    fx_directory_create                                                 */
+/*    fx_directory_delete                                                 */
+/*    fx_directory_exFAT_unicode_entry_write                              */
+/*    fx_directory_rename                                                 */
+/*    fx_file_allocate                                                    */
+/*    fx_file_attributes_set                                              */
+/*    fx_file_best_effort_allocate                                        */
+/*    fx_file_close                                                       */
+/*    fx_file_create                                                      */
+/*    fx_file_date_time_set                                               */
+/*    fx_file_delete                                                      */
+/*    fx_file_rename                                                      */
+/*    fx_file_truncate_release                                            */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_directory_exFAT_entry_write(FX_MEDIA *media_ptr, FX_DIR_ENTRY *entry_ptr, UCHAR update_level)
+{
+
+UINT status;
+
+
+    /* Call the unicode director entry write function.  */
+    status =  _fx_directory_exFAT_unicode_entry_write(media_ptr, entry_ptr, update_level, NULL, 0);
+
+    /* Return completion status.  */
+    return(status);
+}
+
+#endif
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_exFAT_free_search.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_exFAT_free_search.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_exFAT_free_search.c	(revision 30)
@@ -0,0 +1,516 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_directory.h"
+#include "fx_utility.h"
+#ifdef FX_ENABLE_EXFAT
+#include "fx_directory_exFAT.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_directory_free_search                           PORTABLE C      */
+/*                                                           6.1.10       */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function searches the media for a free directory entry.        */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    directory_ptr                         Pointer to directory to       */
+/*                                            search in                   */
+/*    entry_ptr                             Pointer to directory entry    */
+/*                                            record                      */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_exFAT_entry_read        Read entries from directory   */
+/*    _fx_utility_FAT_entry_write           Write a FAT entry             */
+/*    _fx_utility_FAT_flush                 Flush written FAT entries     */
+/*    _fx_utility_logical_sector_flush      Flush logical sector cache    */
+/*    _fx_utility_logical_sector_read       Read logical sector           */
+/*    _fx_utility_exFAT_cluster_state_set   Set cluster state in bitmap   */
+/*    _fx_utility_exFAT_bitmap_flush        Flush written exFAT bitmap    */
+/*    _fx_utility_exFAT_allocate_new_cluster                              */
+/*                                          Allocate new cluster          */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    FileX System Functions                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*  01-31-2022     William E. Lamie         Modified comment(s), fixed    */
+/*                                            errors without cache,       */
+/*                                            resulting in version 6.1.10 */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_directory_exFAT_free_search(FX_MEDIA *media_ptr, FX_DIR_ENTRY *directory_ptr, FX_DIR_ENTRY *entry_ptr)
+{
+
+ULONG             i;
+UCHAR            *work_ptr;
+UINT              status, total_entries;
+ULONG64           entry_sector = 0;
+ULONG64           entry_next_sector = 0;
+ULONG             entry_offset = 0;
+ULONG             cluster;
+ULONG             last_cluster;
+ULONG             directory_entries;
+ULONG64           logical_sector;
+FX_DIR_ENTRY     *search_dir_ptr;
+ULONG             free_entry_start;
+UINT              sectors;
+#ifndef FX_DISABLE_CACHE
+FX_CACHED_SECTOR *cache_entry_ptr;
+#endif
+ULONG             bytes_per_cluster;
+
+
+    /* Get name length.  */
+    i = _fx_utility_string_length_get(entry_ptr -> fx_dir_entry_name, FX_MAX_EX_FAT_NAME_LEN);
+
+    /* Check if name is valid.  */
+    if (entry_ptr -> fx_dir_entry_name[i] != 0)
+    {
+
+        /* Invalid name, return error.  */
+        return(FX_INVALID_NAME);
+    }
+    /* Determine the total entries.  */
+    total_entries = 2 + (i + 14) / 15;
+
+    /* Determine if the search is in the root directory or in a
+       sub-directory.  Note: the directory search function clears the
+       first character of the name for the root directory.  */
+    if (directory_ptr -> fx_dir_entry_name[0])
+    {
+
+        /* Search for a free entry in a sub-directory.  */
+        directory_entries =  (ULONG)directory_ptr -> fx_dir_entry_file_size / FX_DIR_ENTRY_SIZE;
+
+        /* Point the search directory pointer to this entry.  */
+        search_dir_ptr =  directory_ptr;
+    }
+    else
+    {
+
+        /* Find a free entry in the root directory.  */
+
+        /* Setup the number of directory entries.  */
+        directory_entries =  (ULONG)media_ptr -> fx_media_root_directory_entries;
+
+        /* Set the search pointer to NULL since we are working off of the
+           root directory.  */
+        search_dir_ptr =  FX_NULL;
+
+        /* Clear dont_use_fat for root directory.  */
+        directory_ptr -> fx_dir_entry_dont_use_fat = 0;
+    }
+
+    /* Loop through entries in the search directory.  Yes, this is a
+       linear search!  */
+    i =  0;
+    free_entry_start =  directory_entries;
+
+    if (directory_entries > 0)
+    {
+        do
+        {
+            /* Read an entry from the directory.  */
+            status =
+                _fx_directory_exFAT_entry_read(media_ptr,
+                                               search_dir_ptr, &i, entry_ptr, 0, FX_TRUE, NULL, NULL);
+
+            /* Check for error status.  */
+            if (status != FX_SUCCESS)
+            {
+                return(status);
+            }
+
+            /* Determine if this is an empty entry.  */
+            if ((entry_ptr -> fx_dir_entry_type == FX_EXFAT_DIR_ENTRY_TYPE_FREE) ||
+                (entry_ptr -> fx_dir_entry_type == FX_EXFAT_DIR_ENTRY_TYPE_END_MARKER))
+            {
+                /* Determine if we are at the first free entry.  */
+                if (free_entry_start == directory_entries)
+                {
+
+                    /* Remember the start of the free entry.  */
+                    free_entry_start =  i;
+                    entry_sector =      entry_ptr -> fx_dir_entry_log_sector;
+                    entry_next_sector = entry_ptr -> fx_dir_entry_next_log_sector;
+                    entry_offset  =     entry_ptr -> fx_dir_entry_byte_offset;
+                }
+
+                /* Determine if there are enough free entries to satisfy the request.  */
+                if ((i - free_entry_start + 1) >= total_entries)
+                {
+                    FX_INT_SAVE_AREA
+
+                    /* Found an empty slot.  All the pertinent information is already
+                       in the entry structure.  */
+                    entry_ptr -> fx_dir_entry_log_sector =      entry_sector;
+                    entry_ptr -> fx_dir_entry_next_log_sector = entry_next_sector;
+                    entry_ptr -> fx_dir_entry_byte_offset =     entry_offset;
+
+                    /* Initialize the additional directory entries.  */
+                    entry_ptr -> fx_dir_entry_created_time_ms =     0;
+
+                    /* Lockout interrupts for time/date access.  */
+                    FX_DISABLE_INTS
+
+                    entry_ptr -> fx_dir_entry_created_time =        _fx_system_time;
+                    entry_ptr -> fx_dir_entry_created_date =        _fx_system_date;
+                    entry_ptr -> fx_dir_entry_last_accessed_date =  _fx_system_date;
+
+                    /* Restore interrupts.  */
+                    FX_RESTORE_INTS
+
+                    /* Return a successful completion.  */
+                    return(FX_SUCCESS);
+                }
+            }
+            else
+            {
+
+                /* Reset the free entry start.  */
+                free_entry_start =  directory_entries;
+            }
+
+            /* Move to the next entry.  */
+            i++;
+        } while (i < directory_entries);
+    }
+
+    /* No empty entries were found.  If the specified directory is a sub-directory,
+       attempt to allocate another cluster to it.  */
+    if (media_ptr -> fx_media_available_clusters)
+    {
+    ULONG64 size;
+        bytes_per_cluster = ((ULONG)media_ptr -> fx_media_bytes_per_sector) *
+            ((ULONG)media_ptr -> fx_media_sectors_per_cluster);
+
+        /* Check if it is a sub directory.  */
+        if (search_dir_ptr)
+        {
+
+            /* Set size to the available file size.  */
+            size = search_dir_ptr -> fx_dir_entry_available_file_size;
+        }
+        else
+        {
+
+            /* Root directory, set size to root directory size.  */
+            size = media_ptr -> fx_media_root_directory_entries * FX_DIR_ENTRY_SIZE;
+        }
+
+        /* Check for directory restriction */
+        if (size + bytes_per_cluster > FX_EXFAT_MAX_DIRECTORY_SIZE)
+        {
+            return(FX_NO_MORE_SPACE);
+        }
+
+        /* Search the FAT for the next available cluster.  */
+        status = _fx_utility_exFAT_allocate_new_cluster(media_ptr, search_dir_ptr, &last_cluster, &cluster);
+
+        if (status != FX_SUCCESS)
+        {
+            return(status);
+        }
+
+        /* Decrease the available clusters in the media.  */
+        media_ptr -> fx_media_available_clusters--;
+
+        /* Defer the update of the FAT entry and the last cluster of the current
+           directory entry until after the new cluster is initialized and written out.  */
+
+        /* Update entry size. */
+        if (search_dir_ptr)
+        {
+            search_dir_ptr -> fx_dir_entry_file_size += bytes_per_cluster;
+            search_dir_ptr -> fx_dir_entry_available_file_size = search_dir_ptr -> fx_dir_entry_file_size;
+        }
+        else
+        {
+
+            /* Change root directory entry count - FAT32 has a variable sized root directory.  */
+            media_ptr -> fx_media_root_directory_entries += bytes_per_cluster / FX_DIR_ENTRY_SIZE;
+        }
+
+        /* Calculate the logical sector of this cluster.  */
+        logical_sector =  ((ULONG)media_ptr -> fx_media_data_sector_start) +
+            ((((ULONG64)cluster) - FX_FAT_ENTRY_START) *
+             ((ULONG)media_ptr -> fx_media_sectors_per_cluster));
+
+        /* Pickup the number of sectors for the next directory cluster.  */
+        sectors =  media_ptr -> fx_media_sectors_per_cluster;
+
+        /* Read the logical sector just for cache reasons.  */
+        status =  _fx_utility_logical_sector_read(media_ptr, logical_sector,
+                                                  media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
+
+        /* Check the return value.  */
+        if (status != FX_SUCCESS)
+        {
+
+            /* Return the error status.  */
+            return(status);
+        }
+
+        /* Clear the entire first sector of the new sub-directory cluster.  */
+        work_ptr =  (UCHAR *)media_ptr -> fx_media_memory_buffer;
+        i =  0;
+        while (i < media_ptr -> fx_media_bytes_per_sector)
+        {
+
+            /* Clear 4 bytes.  */
+            *((ULONG *)work_ptr) =  (ULONG)0;
+
+            /* Increment pointer.  */
+            work_ptr =  work_ptr + sizeof(ULONG);
+
+            /* Increment counter.  */
+            i =  i + sizeof(ULONG);
+        }
+
+#ifndef FX_DISABLE_CACHE
+        /* Invalidate all cached sectors that are contained in the newly allocated first
+           cluster of the directory.  */
+
+        /* Pickup the total number of cache entries.  */
+        i =  (UINT)media_ptr -> fx_media_sector_cache_size;
+
+        /* Setup pointer to first cache entry (not in list order).  */
+        cache_entry_ptr =  media_ptr -> fx_media_sector_cache;
+
+        /* Examine all the logical sector cache entries.  */
+        while (i--)
+        {
+
+            /* Determine if the cached entry is a sector in the first cluster of the
+               new directory.  We don't need to worry about the first sector since it
+               was read using the logical sector read utility earlier.  */
+            if ((cache_entry_ptr -> fx_cached_sector >= (logical_sector + 1)) &&
+                (cache_entry_ptr -> fx_cached_sector <  (logical_sector + sectors)))
+            {
+
+                /* Yes, we have found a logical sector in the cache that is one of the directory
+                   sectors that will be written with zeros.  Because of this, simply make this
+                   cache entry invalid.  */
+                cache_entry_ptr -> fx_cached_sector =                0;
+                cache_entry_ptr -> fx_cached_sector_buffer_dirty =   FX_FALSE;
+            }
+
+            /* Move to next entry in the cached sector list.  */
+            if (cache_entry_ptr -> fx_cached_sector_next_used)
+            {
+                cache_entry_ptr =  cache_entry_ptr -> fx_cached_sector_next_used;
+            }
+        }
+#endif
+
+        /* Clear all sectors of new sub-directory cluster.  */
+        do
+        {
+
+            /* Decrease the number of sectors to clear.  */
+            sectors--;
+
+            /* Build Write request to the driver.  */
+            media_ptr -> fx_media_driver_request =          FX_DRIVER_WRITE;
+            media_ptr -> fx_media_driver_status =           FX_IO_ERROR;
+            media_ptr -> fx_media_driver_buffer =           media_ptr -> fx_media_memory_buffer;
+            media_ptr -> fx_media_driver_logical_sector =   (ULONG)logical_sector + ((ULONG)sectors);
+            media_ptr -> fx_media_driver_sectors =          1;
+
+            /* Set the system write flag since we are writing a directory sector.  */
+            media_ptr -> fx_media_driver_system_write =  FX_TRUE;
+
+            /* Invoke the driver to write the sector.  */
+            (media_ptr -> fx_media_driver_entry)(media_ptr);
+
+            /* Clear the system write flag.  */
+            media_ptr -> fx_media_driver_system_write =  FX_FALSE;
+
+            /* Determine if an error occurred.  */
+            if (media_ptr -> fx_media_driver_status != FX_SUCCESS)
+            {
+
+                /* Return error code.  */
+                return(status);
+            }
+        } while (sectors);
+
+#ifdef FX_FAULT_TOLERANT
+
+        /* Flush the internal logical sector.  */
+        _fx_utility_logical_sector_flush(media_ptr, logical_sector, media_ptr -> fx_media_sectors_per_cluster, FX_FALSE);
+#endif
+
+        if ((!search_dir_ptr) || (!(search_dir_ptr -> fx_dir_entry_dont_use_fat & 1)))
+        {
+
+            /* At this point, link up the last cluster with the new cluster.  */
+
+            /* Setup the last cluster to indicate the end of the chain.  */
+            status =  _fx_utility_FAT_entry_write(media_ptr, cluster, FX_LAST_CLUSTER_exFAT);
+
+            /* Check the return value.  */
+            if (status != FX_SUCCESS)
+            {
+
+                /* Return the error status.  */
+                return(status);
+            }
+
+            /* Link the last cluster of the directory to the new cluster.  */
+            if (last_cluster)
+            {
+
+                status =  _fx_utility_FAT_entry_write(media_ptr, last_cluster, cluster);
+
+                /* Check the return value.  */
+                if (status != FX_SUCCESS)
+                {
+
+                    /* Return the error status.  */
+                    return(status);
+                }
+            }
+        }
+
+        if (!last_cluster && search_dir_ptr)
+        {
+
+            search_dir_ptr -> fx_dir_entry_cluster = cluster;
+        }
+
+        /* Mark the cluster as used. */
+        status = _fx_utility_exFAT_cluster_state_set(media_ptr, cluster, FX_EXFAT_BITMAP_CLUSTER_OCCUPIED);
+
+        /* Check the return value.  */
+        if (status != FX_SUCCESS)
+        {
+
+            /* Return the error status.  */
+            return(status);
+        }
+
+        /* Move cluster search pointer forward. */
+        media_ptr -> fx_media_cluster_search_start = cluster + 1;
+
+        /* Determine if this needs to be wrapped. */
+        if (media_ptr -> fx_media_cluster_search_start >= media_ptr -> fx_media_total_clusters + FX_FAT_ENTRY_START)
+        {
+
+            /* Wrap the search to the beginning FAT entry. */
+            media_ptr -> fx_media_cluster_search_start = FX_FAT_ENTRY_START;
+        }
+
+#ifdef FX_FAULT_TOLERANT
+
+        /* Flush the cached individual FAT entries */
+        _fx_utility_FAT_flush(media_ptr);
+
+        /* Flush the bitmap and its logical sector.  */
+        _fx_utility_exFAT_bitmap_flush(media_ptr);
+        _fx_utility_logical_sector_flush(media_ptr, media_ptr -> fx_media_exfat_bitmap_start_sector +
+                                         (cluster >> media_ptr -> fx_media_exfat_bitmap_clusters_per_sector_shift), ((ULONG64) 1), FX_FALSE);
+#endif
+
+        /* Finally load up the directory entry with information for the
+           beginning of the new cluster.  */
+        {
+            FX_INT_SAVE_AREA
+
+            entry_ptr -> fx_dir_entry_name[0] = 0;
+            if (free_entry_start == directory_entries)
+            {
+
+                /* start from begining of new cluster */
+                entry_ptr -> fx_dir_entry_log_sector = logical_sector;
+
+                /* There are more sectors in this cluster.  */
+                entry_ptr -> fx_dir_entry_next_log_sector = logical_sector + 1;
+
+                /* Clear the byte offset since this is a new entry.  */
+                entry_ptr -> fx_dir_entry_byte_offset = 0;
+            }
+            else
+            {
+
+                /* start from end of last cluster */
+                entry_ptr -> fx_dir_entry_log_sector = entry_sector;
+
+                /* Next sector in new cluster */
+                entry_ptr -> fx_dir_entry_next_log_sector = logical_sector;
+
+                /* Set byte offset */
+                entry_ptr -> fx_dir_entry_byte_offset = entry_offset;
+            }
+
+            /* Lockout interrupts for time/date access.  */
+            FX_DISABLE_INTS
+
+            entry_ptr -> fx_dir_entry_created_time =        _fx_system_time;
+            entry_ptr -> fx_dir_entry_created_date =        _fx_system_date;
+            entry_ptr -> fx_dir_entry_last_accessed_date =  _fx_system_date;
+
+            /* Restore interrupts.  */
+            FX_RESTORE_INTS
+        }
+
+        entry_ptr -> fx_dir_entry_type = FX_EXFAT_DIR_ENTRY_TYPE_END_MARKER;
+
+        /* Return a successful status.  */
+        return(FX_SUCCESS);
+    }
+
+    /* Return "not found" status to the caller.  */
+    return(FX_NOT_FOUND);
+}
+#endif /* FX_ENABLE_EXFAT */
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_exFAT_unicode_entry_write.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_exFAT_unicode_entry_write.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_exFAT_unicode_entry_write.c	(revision 30)
@@ -0,0 +1,946 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+
+
+#ifdef FX_ENABLE_EXFAT
+#include "fx_utility.h"
+#include "fx_directory_exFAT.h"
+#include "fx_directory.h"
+#ifdef FX_ENABLE_FAULT_TOLERANT
+#include "fx_fault_tolerant.h"
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+#include "fx_utility.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_directory_exFAT_unicode_entry_write             PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function writes the supplied directory entry to the specified  */
+/*    logical sector and offset.                                          */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    entry_ptr                             Pointer to directory entry    */
+/*    update_level                          Update level for entry write  */
+/*    unicode_name                          Unicode file name             */
+/*    unicode_length                        Length of unicode file name   */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_exFAT_cluster_free        Release unused clusters       */
+/*    _fx_utility_exFAT_name_hash_get       Get name hash                 */
+/*    _fx_utility_FAT_entry_read            Read a new FAT entry          */
+/*    _fx_utility_logical_sector_flush      Flush the written log sector  */
+/*    _fx_utility_logical_sector_read       Read directory sector         */
+/*    _fx_utility_logical_sector_write      Write directory sector        */
+/*    _fx_utility_string_length_get         Get string's length           */
+/*    _fx_utility_16_unsigned_write         Write a USHORT from memory    */
+/*    _fx_utility_32_unsigned_write         Write a ULONG from memory     */
+/*    _fx_utility_64_unsigned_read          Read a ULONG64 from memory    */
+/*    _fx_fault_tolerant_add_dir_log        Add directory redo log        */
+/*    _fx_fault_tolerant_add_checksum_log   Add checksum redo log         */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    FileX System Functions                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_directory_exFAT_unicode_entry_write(FX_MEDIA *media_ptr, FX_DIR_ENTRY *entry_ptr,
+                                              UCHAR update_level, USHORT *unicode_name, UINT unicode_length)
+{
+
+UCHAR  *work_ptr;
+UCHAR  *sector_base_ptr;
+UINT    status;
+UINT    i, j;
+ULONG64 logical_sector;
+ULONG   relative_sector;
+ULONG   byte_offset;
+ULONG   cluster, next_cluster;
+UINT    total_entries;
+UINT    name_length;
+UINT    name_pos = 0;
+UINT    copy_size;
+USHORT  checksum = 0;
+ULONG   date_time;
+UINT    use_unicode = FX_FALSE;
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+UCHAR  *changed_ptr;    /* Points to the directory entry that needs to be updated. */
+UINT    changed_size;   /* The amount of bytes changed */
+ULONG   changed_offset; /* Offset from the beginning of the sector. */
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+
+
+    /* Check if we have unicode file name available.  */
+    if (unicode_name && unicode_length)
+    {
+
+        /* Set use unicode flag.  */
+        use_unicode = FX_TRUE;
+
+        /* Save the length of the name.  */
+        name_length = unicode_length;
+    }
+    else
+    {
+
+        /* Calculate the length of the name from the name string.  */
+        name_length = _fx_utility_string_length_get(entry_ptr -> fx_dir_entry_name, FX_MAX_EX_FAT_NAME_LEN);
+
+        /* Check if name is valid.  */
+        if (entry_ptr -> fx_dir_entry_name[name_length] != 0)
+        {
+
+            /* Invalid name, return error.  */
+            return(FX_INVALID_NAME);
+        }
+    }
+
+    /* Pickup the byte offset of the entry.  */
+    byte_offset = entry_ptr -> fx_dir_entry_byte_offset;
+
+    /* Pickup the logical sector of the entry.  */
+    logical_sector = entry_ptr -> fx_dir_entry_log_sector;
+
+    /* Calculate the cluster that this logical sector is in.  */
+    cluster =  (ULONG)((logical_sector - media_ptr -> fx_media_data_sector_start) / (media_ptr -> fx_media_sectors_per_cluster)) + FX_FAT_ENTRY_START;
+
+    /* Calculate the relative cluster.  */
+    relative_sector =  (ULONG)(logical_sector -  (((ULONG)media_ptr -> fx_media_data_sector_start) +
+                                                  (((ULONG64)cluster - FX_FAT_ENTRY_START) *
+                                                   ((ULONG)media_ptr -> fx_media_sectors_per_cluster))));
+
+    /* Read the sector.  */
+    status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) logical_sector,
+                                              media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
+
+    /* Determine if an error occurred.  */
+    if (status != FX_SUCCESS)
+    {
+
+        /* Return the error status.  */
+        return(status);
+    }
+
+    /* Setup a pointer into the buffer.  */
+    sector_base_ptr = (UCHAR *)media_ptr -> fx_media_memory_buffer;
+    work_ptr =  sector_base_ptr + (UINT)entry_ptr -> fx_dir_entry_byte_offset;
+
+    /* Build file entry fields.  */
+
+    /* Check if we need to update EntryType field.  */
+    if (update_level == UPDATE_FULL)
+    {
+
+        /* Set EntryType field to file directory.  */
+        *work_ptr = FX_EXFAT_DIR_ENTRY_TYPE_FILE_DIRECTORY;
+    }
+    /* Check if we are request to delete the file.  */
+    else if (update_level == UPDATE_DELETE)
+    {
+
+        /* Clear InUse bit.  */
+        *work_ptr &= 0x7f;
+    }
+
+    /* Advance the pointer to the next field: SecondaryCount.  */
+    work_ptr++;
+
+    /* Update SecondaryCount field.  */
+    if (update_level == UPDATE_FULL)
+    {
+
+        /* Calculate the secondary entry count from file name length.  */
+        total_entries = 1 + (name_length + 14) / 15;
+
+        /* Save SecondaryCount field.  */
+        *work_ptr = (UCHAR)total_entries;
+    }
+    else
+    {
+
+        /* We are not performing a full update, read back the secondary entry count.  */
+        total_entries = *work_ptr;
+    }
+
+    /* Advance the pointer to the next field.  */
+    work_ptr++;
+
+    /* Skip SetChecksum field.  */
+    work_ptr += 2;
+
+    /* Check if we need to update FileAttributes field.  */
+    if (update_level >= UPDATE_FILE)
+    {
+
+        /* Write the file attributes field.  */
+        _fx_utility_16_unsigned_write(work_ptr, entry_ptr -> fx_dir_entry_attributes);
+    }
+
+    /* Advance the pointer to the next field.  */
+    work_ptr += 2;
+
+    /* Check if we need to perform full entry update.  */
+    if (update_level == UPDATE_FULL)
+    {
+
+        /* Clear Reserved1 field.  */
+        _fx_utility_16_unsigned_write(work_ptr, 0);
+    }
+
+    /* Advance the pointer to the next field.  */
+    work_ptr += 2;
+
+    /* Check if we need to update the CreateTimestamp field.  */
+    if (update_level >= UPDATE_FILE)
+    {
+
+        /* Calculate and update CreateTimestamp field.  */
+        date_time = ((ULONG)entry_ptr -> fx_dir_entry_created_date << 16) |
+                     (ULONG)entry_ptr -> fx_dir_entry_created_time;
+        _fx_utility_32_unsigned_write(work_ptr, date_time);
+    }
+
+    /* Advance the pointer to the next field.  */
+    work_ptr += 4;
+
+    /* Check if we need to update LastModifiedTimestamp field.  */
+    if (update_level >= UPDATE_FILE)
+    {
+
+        /* Calculate and update LastModifiedTimestamp field.  */
+        date_time = ((ULONG)entry_ptr -> fx_dir_entry_date << 16) |
+                     (ULONG)entry_ptr -> fx_dir_entry_time;
+        _fx_utility_32_unsigned_write(work_ptr, date_time);
+    }
+
+    /* Advance the pointer to the next field.  */
+    work_ptr += 4;
+
+    /* Check if we need to update LastAccessedTimestamp field.  */
+    if (update_level >= UPDATE_FILE)
+    {
+
+        /* Calculate and update LastAccessedTimestamp field.  */
+        date_time = ((ULONG)entry_ptr -> fx_dir_entry_date << 16) |
+                     (ULONG)entry_ptr -> fx_dir_entry_time; /* use modified as accessed */
+        _fx_utility_32_unsigned_write(work_ptr, date_time);
+    }
+
+    /* Advance the pointer to the next field.  */
+    work_ptr += 4;
+
+    /* Check if we need to update Create10msIncrement field.  */
+    if (update_level >= UPDATE_FILE)
+    {
+
+        /* Update Create10msIncrement field.  */
+        *work_ptr = entry_ptr -> fx_dir_entry_created_time_ms;
+    }
+
+    /* Advance the pointer to the next field.  */
+    work_ptr++;
+
+    /* Check if we need to perform full entry update.  */
+    if (update_level >= UPDATE_FILE)
+    {
+
+        /* 10ms increment field is not supported, clear this field.  */
+        *work_ptr = 0;
+    }
+
+    /* Advance the pointer to the next field.  */
+    work_ptr++;
+
+    /* Check if we need to perform full entry update.  */
+    if (update_level == UPDATE_FULL)
+    {
+
+        /*CreateUtcOffset field is not supported, clear this field.  */
+        *work_ptr = 0;
+    }
+
+    /* Advance the pointer to the next field.  */
+    work_ptr++;
+
+    /* Check if we need to perform full entry update.  */
+    if (update_level >= UPDATE_FILE)
+    {
+
+        /* LastModifiedUtcOffset field is not supported, clear this field.  */
+        *work_ptr = 0;
+    }
+
+    /* Advance the pointer to the next field.  */
+    work_ptr++;
+
+    /* Check if we need to perform full entry update.  */
+    if (update_level == UPDATE_FULL)
+    {
+
+        /* LastModifiedUtcOffset field is not supported, clear this field.  */
+        *work_ptr = 0; /* Not supported.  */
+    }
+
+    /* Advance the pointer to the next field.  */
+    work_ptr++;
+
+    /* Clear Reserved2 field.  */
+    if (update_level == UPDATE_FULL)
+    {
+
+        /* Loop to clear the reserved field.  */
+        for (i = 0; i < 7; ++i)
+        {
+
+            /* Clear the reserved field.  */
+            *work_ptr = 0;
+            work_ptr++;
+        }
+    }
+    else
+    {
+
+        /* Skip the reserved field.  */
+        work_ptr += 7;
+    }
+
+    /* Calculate checksum.  */
+    work_ptr -= FX_DIR_ENTRY_SIZE;
+
+    /* Loop to calculate the entry checksum.  */
+    for (j = 0; j < FX_DIR_ENTRY_SIZE; ++j)
+    {
+
+        /* Skip the checksum field.  */
+        if ((j == 2) || (j == 3))
+        {
+
+            continue;
+        }
+
+        /* Calculate the checksum using the algorithm described in the specification.  */
+        /* Right rotate the checksum by one bit position and add the data.  */
+        checksum = (USHORT)(((checksum >> 1) | (checksum << 15)) + work_ptr[j]);
+    }
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    /* Initialize variables for fault tolerant. */
+    changed_ptr = work_ptr;
+    changed_offset = entry_ptr -> fx_dir_entry_byte_offset;
+    changed_size = 0;
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Update second entries.  */
+    for (i = 0; i < total_entries; ++i)
+    {
+
+        /* Advance the pointer and offset to next directory entry.  */
+        work_ptr += FX_DIR_ENTRY_SIZE;
+        byte_offset += FX_DIR_ENTRY_SIZE;
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        /* Update changed_size. */
+        changed_size += FX_DIR_ENTRY_SIZE;
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Determine if the entry overlaps into the next sector.  */
+        if (byte_offset >= media_ptr -> fx_media_bytes_per_sector)
+        {
+#ifdef FX_ENABLE_FAULT_TOLERANT
+            if (media_ptr -> fx_media_fault_tolerant_enabled &&
+                (media_ptr -> fx_media_fault_tolerant_state & FX_FAULT_TOLERANT_STATE_STARTED))
+            {
+
+                /* Redirect this request to log file. */
+                status = _fx_fault_tolerant_add_dir_log(media_ptr, logical_sector, changed_offset, changed_ptr, changed_size);
+            }
+            else
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+            {
+
+                /* Write current logical sector out.  */
+                status =  _fx_utility_logical_sector_write(media_ptr, logical_sector,
+                                                           sector_base_ptr, ((ULONG) 1), FX_DIRECTORY_SECTOR);
+            }
+
+            /* Determine if an error occurred.  */
+            if (status != FX_SUCCESS)
+            {
+
+                /* Return the error status.  */
+                return(status);
+            }
+
+            /* Determine the next sector of the directory entry.  */
+            if (relative_sector < (media_ptr -> fx_media_sectors_per_cluster - 1))
+            {
+
+                /* More sectors in this cluster.  */
+
+                /* Simply increment the logical sector.  */
+                logical_sector++;
+
+                /* Increment the relative sector.  */
+                relative_sector++;
+            }
+            else
+            {
+
+                /* We need to move to the next cluster.  */
+                if ((entry_ptr -> fx_dir_entry_dont_use_fat >> 1) & 1) /* Check parent dont_use_fat flag.  */
+                {
+
+                    /* FAT is not used, next cluster is after the current cluster.  */
+                    next_cluster = cluster + 1;
+                }
+                else
+                {
+
+                    /* FAT is used, read FAT to get the next cluster.  */
+                    status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
+
+                    /* Check for I/O error.  */
+                    if (status != FX_SUCCESS)
+                    {
+
+                        /* Return error code.  */
+                        return(status);
+                    }
+                }
+
+                /* Copy next cluster to the current cluster.  */
+                cluster =  next_cluster;
+
+                /* Check the value of the new cluster - it must be a valid cluster number
+                   or something is really wrong!  */
+                if ((cluster < FX_FAT_ENTRY_START) || (cluster > FX_RESERVED_1_exFAT))
+                {
+
+                    /* Send error message back to caller.  */
+                    return(FX_FILE_CORRUPT);
+                }
+
+                /* Setup the relative sector (this is zero for subsequent cluster.  */
+                relative_sector =  0;
+
+                /* Calculate the next logical sector.  */
+                logical_sector =   ((ULONG)media_ptr -> fx_media_data_sector_start) +
+                    (((ULONG64)cluster - FX_FAT_ENTRY_START) *
+                     ((ULONG)media_ptr -> fx_media_sectors_per_cluster));
+            }
+
+            /* Read the sector.  */
+            status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) logical_sector,
+                                                      media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
+
+            /* Determine if an error occurred.  */
+            if (status != FX_SUCCESS)
+            {
+
+                /* Return the error status.  */
+                return(status);
+            }
+
+            /* Setup logical sector.  */
+            sector_base_ptr = media_ptr -> fx_media_memory_buffer;
+
+            /* Setup a fresh byte offset.  */
+            byte_offset = 0;
+
+            /* Setup a new pointer into the buffer.  */
+            work_ptr = sector_base_ptr;
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+            /* Initialize data for fault tolerant. */
+            changed_ptr = work_ptr;
+            changed_size = 0;
+            changed_offset = 0;
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+        }
+
+        /* Check if we are processing the first secondary entry.  */
+        if (i == 0)
+        {
+
+            /* First sub entry is stream entry.  */
+
+            /* Check if we need to perform full entry update.  */
+            if (update_level == UPDATE_FULL)
+            {
+
+                /* Set the EntryType field to stream extension type.  */
+                *work_ptr = FX_EXFAT_DIR_ENTRY_TYPE_STREAM_EXTENSION;
+            }
+            else if (update_level == UPDATE_DELETE)
+            {
+
+                /* Clear InUse bit.  */
+                *work_ptr &= 0x7f;
+            }
+
+            /* Advance the pointer to the next field.  */
+            work_ptr++;
+
+            /* Update GeneralSecondaryFlags field.  */
+            if (update_level >= UPDATE_STREAM)
+            {
+
+                /* Check if FAT is used and the entry has associated cluster.  */
+                if ((entry_ptr -> fx_dir_entry_dont_use_fat & 1) && (entry_ptr -> fx_dir_entry_cluster != 0))
+                {
+
+                    /* Set the flags to don't use FAT.  */
+                    *work_ptr = 3;
+                }
+                else
+                {
+
+                    /* FAT is used.  */
+                    *work_ptr = 1;
+                }
+            }
+
+            /* Advance the pointer to the next field.  */
+            work_ptr++;
+
+            /* Check if we need to perform full entry update.  */
+            if (update_level == UPDATE_FULL)
+            {
+
+                /* Clear Reserved1 field.  */
+                *work_ptr = 0;
+            }
+
+            /* Advance the pointer to the next field.  */
+            work_ptr++;
+
+            /* Check if we need to update NameLength field.  */
+            if (update_level >= UPDATE_NAME)
+            {
+
+                /* Update NameLength field.  */
+                *work_ptr = (UCHAR)name_length;
+            }
+
+            /* Advance the pointer to the next field.  */
+            work_ptr++;
+
+            /* Check if we need to update NameHash field.  */
+            if (update_level >= UPDATE_NAME)
+            {
+                /* Check if the supplied file name is in unicode format.  */
+                if (use_unicode)
+                {
+
+                    /* Update NameHash field.  */
+                    _fx_utility_16_unsigned_write(work_ptr, _fx_utility_exFAT_unicode_name_hash_get((CHAR *)unicode_name, name_length));
+                }
+                else
+                {
+
+                    /* Update NameHash field.  */
+                    _fx_utility_16_unsigned_write(work_ptr, _fx_utility_exFAT_name_hash_get(entry_ptr -> fx_dir_entry_name));
+                }
+            }
+
+            /* Advance the pointer to the next field.  */
+            work_ptr += 2;
+
+            /* Check if we need to perform full entry update.  */
+            if (update_level == UPDATE_FULL)
+            {
+
+                /* Clear Reserved2 field.  */
+                _fx_utility_16_unsigned_write(work_ptr, 0);
+            }
+
+            /* Advance the pointer to the next field.  */
+            work_ptr += 2;
+
+            /* Check if we need to update ValidDataLength field.  */
+            if (update_level >= UPDATE_STREAM)
+            {
+
+                /* Update ValidDataLength field.  */
+                _fx_utility_64_unsigned_write(work_ptr, entry_ptr -> fx_dir_entry_file_size);
+            }
+
+            /* Advance the pointer to the next field.  */
+            work_ptr += 8;
+
+            /* Check if we need to perform full entry update.  */
+            if (update_level == UPDATE_FULL)
+            {
+
+                /* Clear Reserved3 field.  */
+                _fx_utility_32_unsigned_write(work_ptr, 0);
+            }
+
+            /* Advance the pointer to the next field.  */
+            work_ptr += 4;
+
+            /* Check if we need to update FirstCluster field.  */
+            if (update_level >= UPDATE_STREAM)
+            {
+
+                /* Update FirstCluster field.  */
+                _fx_utility_32_unsigned_write(work_ptr, entry_ptr -> fx_dir_entry_cluster);
+            }
+
+            /* Advance the pointer to the next field.  */
+            work_ptr += 4;
+
+            /* Update DataLength fields.  */
+            if (update_level >= UPDATE_STREAM)
+            {
+
+                /* Update DataLength fields.  */
+                _fx_utility_64_unsigned_write(work_ptr, entry_ptr -> fx_dir_entry_available_file_size);
+                _fx_utility_64_unsigned_write(work_ptr, entry_ptr -> fx_dir_entry_file_size);
+            }
+
+            /* Advance the pointer to the next field.  */
+            work_ptr += 8;
+        }
+        else
+        {
+
+            /* Check if we are requested to delete the entries.  */
+            if (update_level == UPDATE_DELETE)
+            {
+
+                /* Check the directory entry type.  */
+                if ((*work_ptr != FX_EXFAT_DIR_ENTRY_TYPE_FILE_NAME) && (*work_ptr != FX_EXFAT_DIR_ENTRY_TYPE_STREAM_EXTENSION))
+                {
+
+                    /* Unknown secondary, we should free used clusters if any.  */
+                    status = _fx_utility_exFAT_cluster_free(media_ptr, work_ptr);
+                    if (status != FX_SUCCESS)
+                    {
+
+                        /* Return completion status.  */
+                        return(status);
+                    }
+                }
+
+                /* Clear InUse bit.  */
+                *work_ptr &= 0x7f;
+                work_ptr += FX_DIR_ENTRY_SIZE;
+            }
+            /* Check if we need to update the file name.  */
+            else if ((update_level == UPDATE_FULL) ||
+                     ((update_level == UPDATE_NAME) && (*work_ptr == FX_EXFAT_DIR_ENTRY_TYPE_FILE_NAME)))
+            {
+
+                /* Build Name entry.  */
+
+                /* Update EntryType field.  */
+                *work_ptr = FX_EXFAT_DIR_ENTRY_TYPE_FILE_NAME;
+                work_ptr++;
+
+                /* Update GeneralSecondaryFlags field.  */
+                *work_ptr = 0;
+                work_ptr++;
+
+                /* Update FileName field.  */
+
+                /* One name entry can hold up to 15 characters. Set how many characters to copy.  */
+                if (name_length > 15)
+                {
+                    copy_size = 15;
+                }
+                else
+                {
+                    copy_size = name_length;
+                }
+
+                /* Check if the supplied file name is in unicode format.  */
+                if (use_unicode)
+                {
+
+                    /* Loop to copy the unicode file name.  */
+                    for (j = 0; j < copy_size; ++j)
+                    {
+
+                        /* Copy unicode file name to the file name entry.  */
+                        _fx_utility_16_unsigned_write(work_ptr, (UINT)unicode_name[name_pos++]);
+                        work_ptr += 2;
+                    }
+                }
+                else
+                {
+
+                    /* Loop to copy non-unicode file name.  */
+                    for (j = 0; j < copy_size; ++j)
+                    {
+
+                        /* Copy and convert non-unicode file name.  */
+                        _fx_utility_16_unsigned_write(work_ptr, (UINT)entry_ptr -> fx_dir_entry_name[name_pos++]);
+                        work_ptr += 2;
+                    }
+                }
+
+                /* Loop to clear remaining bytes.  */
+                for (j = copy_size; j < 15; ++j)
+                {
+
+                    /* Clear the remaining bytes.  */
+                    _fx_utility_16_unsigned_write(work_ptr, 0);
+                    work_ptr += 2;
+                }
+
+                /* Modify the name_length to indicate the remaining length.  */
+                name_length -= copy_size;
+            }
+            else
+            {
+
+                /* The entry does need to be updated, move to next entry.  */
+                work_ptr += FX_DIR_ENTRY_SIZE;
+            }
+        }
+
+        /* Set pointer back for checksum calculation.  */
+        work_ptr -= FX_DIR_ENTRY_SIZE;
+
+        /* Loop to calculate the checksum.  */
+        for (j = 0; j < FX_DIR_ENTRY_SIZE; ++j)
+        {
+
+            /* Calculate the checksum.  */
+            /* Right rotate the checksum by one bit position and add the data.  */
+            checksum = (USHORT)(((checksum >> 1) | (checksum << 15)) + work_ptr[j]);
+        }
+    }
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    /* Update changed_size. */
+    changed_size += FX_DIR_ENTRY_SIZE;
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Go back to file entry.  */
+    if (byte_offset < total_entries * FX_DIR_ENTRY_SIZE)
+    {
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        if (media_ptr -> fx_media_fault_tolerant_enabled &&
+            (media_ptr -> fx_media_fault_tolerant_state & FX_FAULT_TOLERANT_STATE_STARTED))
+        {
+
+            /* Redirect this request to log file. */
+            status = _fx_fault_tolerant_add_dir_log(media_ptr, logical_sector, changed_offset, changed_ptr, changed_size);
+        }
+        else
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+        {
+
+            /* Write current logical sector out.  */
+            status =  _fx_utility_logical_sector_write(media_ptr, logical_sector,
+                                                       sector_base_ptr, ((ULONG) 1), FX_DIRECTORY_SECTOR);
+        }
+        /* Determine if an error occurred.  */
+        if (status != FX_SUCCESS)
+        {
+
+            /* Return the error status.  */
+            return(status);
+        }
+
+        /* Pickup the byte offset of the entry.  */
+        byte_offset = entry_ptr -> fx_dir_entry_byte_offset;
+
+        /* Pickup the logical sector of the entry.  */
+        logical_sector = entry_ptr -> fx_dir_entry_log_sector;
+
+        /* Calculate the cluster that this logical sector is in.  */
+        cluster =  (ULONG)((logical_sector - media_ptr -> fx_media_data_sector_start) / (media_ptr -> fx_media_sectors_per_cluster)) + FX_FAT_ENTRY_START;
+
+        /* Calculate the relative cluster.  */
+        relative_sector =  (ULONG)(logical_sector -  (((ULONG)media_ptr -> fx_media_data_sector_start) +
+                                                      (((ULONG64)cluster - FX_FAT_ENTRY_START) *
+                                                       ((ULONG)media_ptr -> fx_media_sectors_per_cluster))));
+
+        /* Read the sector.  */
+        status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) logical_sector,
+                                                  media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
+
+        /* Determine if an error occurred.  */
+        if (status != FX_SUCCESS)
+        {
+
+            /* Return the error status.  */
+            return(status);
+        }
+
+        /* Setup logical sector.  */
+        sector_base_ptr = media_ptr -> fx_media_memory_buffer;
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        /* Initialize data for fault tolerant. */
+        /* A log for checksum. */
+        changed_ptr = sector_base_ptr + byte_offset + 2;
+        changed_size = 2;
+        changed_offset = byte_offset + 2;
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+    }
+    else
+    {
+
+        /* The directory entries are not crossing sector boundary, just adjust the pointer to go back to the first entry.  */
+        byte_offset -= total_entries * FX_DIR_ENTRY_SIZE;
+    }
+
+    /* Setup work pointer to the directory entry.  */
+    work_ptr = sector_base_ptr + byte_offset;
+
+    /* Store SetChecksum field.  */
+    work_ptr += 2;
+    _fx_utility_16_unsigned_write(work_ptr, checksum);
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    if (media_ptr -> fx_media_fault_tolerant_enabled &&
+        (media_ptr -> fx_media_fault_tolerant_state & FX_FAULT_TOLERANT_STATE_STARTED))
+    {
+
+        if (changed_size == 2)
+        {
+
+            /* Only checksum. */
+            /* Redirect this request to log file. */
+            status = _fx_fault_tolerant_add_checksum_log(media_ptr, logical_sector, changed_offset, checksum);
+        }
+        else
+        {
+
+            /* Redirect this request to log file. */
+            status = _fx_fault_tolerant_add_dir_log(media_ptr, logical_sector, changed_offset, changed_ptr, changed_size);
+        }
+    }
+    else
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+    {
+
+        /* Write current logical sector out.  */
+        status =  _fx_utility_logical_sector_write(media_ptr, logical_sector,
+                                                   sector_base_ptr, ((ULONG) 1), FX_DIRECTORY_SECTOR);
+    }
+
+    /* Determine if an error occurred.  */
+    if (status != FX_SUCCESS)
+    {
+
+        /* Return the error status.  */
+        return(status);
+    }
+
+    /* Check if there is a default path.  */
+    if (media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_name[0])
+    {
+
+        /* Check default path directory was updated.  */
+        if ((media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_log_sector ==
+             entry_ptr -> fx_dir_entry_log_sector) &&
+            (media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_byte_offset ==
+             entry_ptr -> fx_dir_entry_byte_offset))
+        {
+
+            /* Update default path.  */
+            media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_file_size =
+                entry_ptr -> fx_dir_entry_file_size;
+            media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_available_file_size =
+                entry_ptr -> fx_dir_entry_available_file_size;
+            media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_dont_use_fat =
+                entry_ptr -> fx_dir_entry_dont_use_fat;
+            media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_cluster =
+                entry_ptr -> fx_dir_entry_cluster;
+        }
+    }
+
+#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
+
+    /* Determine if there is a previously found directory entry in the directory
+       search cache.  */
+    if (media_ptr -> fx_media_last_found_name[0])
+    {
+
+        /* Determine if the cached search directory entry matches the directory entry being
+           written.  */
+        if ((entry_ptr -> fx_dir_entry_log_sector == media_ptr -> fx_media_last_found_entry.fx_dir_entry_log_sector) &&
+            (entry_ptr -> fx_dir_entry_byte_offset == media_ptr -> fx_media_last_found_entry.fx_dir_entry_byte_offset))
+        {
+
+            /* Yes, this entry is the same as the one currently in the directory search cache.
+               Update various fields in the directory search cache with the information being
+               written now.  */
+            media_ptr -> fx_media_last_found_entry.fx_dir_entry_cluster =         entry_ptr -> fx_dir_entry_cluster;
+            media_ptr -> fx_media_last_found_entry.fx_dir_entry_file_size =       entry_ptr -> fx_dir_entry_file_size;
+            media_ptr -> fx_media_last_found_entry.fx_dir_entry_attributes =      entry_ptr -> fx_dir_entry_attributes;
+            media_ptr -> fx_media_last_found_entry.fx_dir_entry_time =            entry_ptr -> fx_dir_entry_time;
+            media_ptr -> fx_media_last_found_entry.fx_dir_entry_date =            entry_ptr -> fx_dir_entry_date;
+            media_ptr -> fx_media_last_found_entry.fx_dir_entry_reserved =        entry_ptr -> fx_dir_entry_reserved;
+            media_ptr -> fx_media_last_found_entry.fx_dir_entry_created_time_ms = entry_ptr -> fx_dir_entry_created_time_ms;
+            media_ptr -> fx_media_last_found_entry.fx_dir_entry_created_time =    entry_ptr -> fx_dir_entry_created_time;
+            media_ptr -> fx_media_last_found_entry.fx_dir_entry_created_date =    entry_ptr -> fx_dir_entry_created_date;
+
+            media_ptr -> fx_media_last_found_entry.fx_dir_entry_dont_use_fat =    entry_ptr -> fx_dir_entry_dont_use_fat;
+            media_ptr -> fx_media_last_found_entry.fx_dir_entry_type =            entry_ptr -> fx_dir_entry_type;
+            media_ptr -> fx_media_last_found_entry.fx_dir_entry_available_file_size = entry_ptr -> fx_dir_entry_available_file_size;
+        }
+    }
+#endif
+
+    /* Return success to the caller.  */
+    return(status);
+}
+
+#endif
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_first_entry_find.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_first_entry_find.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_first_entry_find.c	(revision 30)
@@ -0,0 +1,136 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_directory.h"
+#include "fx_utility.h"
+
+#ifndef FX_NO_LOCAL_PATH
+FX_LOCAL_PATH_SETUP
+#endif
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_directory_first_entry_find                      PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function returns the first directory entry of the current      */
+/*    working directory.                                                  */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    directory_name                        Destination for directory     */
+/*                                            name                        */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_next_entry_find         Find next directory entry     */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    FileX System Functions                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_directory_first_entry_find(FX_MEDIA *media_ptr, CHAR *directory_name)
+{
+
+UINT status;
+
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of times this service has been called.  */
+    media_ptr -> fx_media_directory_first_entry_finds++;
+#endif
+
+    /* Check the media to make sure it is open.  */
+    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
+    {
+
+        /* Return the media not opened error.  */
+        return(FX_MEDIA_NOT_OPEN);
+    }
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_DIRECTORY_FIRST_ENTRY_FIND, media_ptr, directory_name, 0, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+    /* Determine if a local path is in effect at this point.  */
+#ifndef FX_NO_LOCAL_PATH
+    if (_tx_thread_current_ptr -> tx_thread_filex_ptr)
+    {
+
+        /* Yes, there is a local path.  Set the current entry to zero.  */
+        ((FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr) -> fx_path_current_entry =  0;
+    }
+    else
+    {
+
+        /* Use global default directory.  Set the current entry to 0 in
+           order to pickup the first entry.  */
+        media_ptr -> fx_media_default_path.fx_path_current_entry =  0;
+    }
+#else
+
+    /* Set the current entry to 0 in order to pickup the first entry.  */
+    media_ptr -> fx_media_default_path.fx_path_current_entry =  0;
+#endif
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* Call the next directory entry to pickup the first entry.  */
+    status =  _fx_directory_next_entry_find(media_ptr, directory_name);
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_first_full_entry_find.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_first_full_entry_find.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_first_full_entry_find.c	(revision 30)
@@ -0,0 +1,146 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_directory.h"
+#include "fx_utility.h"
+
+#ifndef FX_NO_LOCAL_PATH
+FX_LOCAL_PATH_SETUP
+#endif
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_directory_first_full_entry_find                 PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function returns the first directory entry of the current      */
+/*    working directory and selected information about the entry.         */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    directory_name                        Destination for directory     */
+/*                                            name                        */
+/*    attributes                            Destination for attributes    */
+/*    size                                  Destination for size          */
+/*    year                                  Destination for year          */
+/*    month                                 Destination for month         */
+/*    day                                   Destination for day           */
+/*    hour                                  Destination for hour          */
+/*    minute                                Destination for minute        */
+/*    second                                Destination for second        */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_next_full_entry_find    Find next full directory entry*/
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    FileX System Functions                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_directory_first_full_entry_find(FX_MEDIA *media_ptr,
+                                          CHAR *directory_name, UINT *attributes, ULONG *size,
+                                          UINT *year, UINT *month, UINT *day, UINT *hour, UINT *minute, UINT *second)
+{
+
+UINT status;
+
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of times this service has been called.  */
+    media_ptr -> fx_media_directory_first_full_entry_finds++;
+#endif
+
+    /* Check the media to make sure it is open.  */
+    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
+    {
+
+        /* Return the media not opened error.  */
+        return(FX_MEDIA_NOT_OPEN);
+    }
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_DIRECTORY_FIRST_FULL_ENTRY_FIND, media_ptr, directory_name, 0, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+    /* Determine if a local path is in effect at this point.  */
+#ifndef FX_NO_LOCAL_PATH
+    if (_tx_thread_current_ptr -> tx_thread_filex_ptr)
+    {
+
+        /* Yes, there is a local path.  Set the current entry to zero.  */
+        ((FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr) -> fx_path_current_entry =  0;
+    }
+    else
+    {
+
+        /* Use global default directory.  Set the current entry to 0 in
+           order to pickup the first entry.  */
+        media_ptr -> fx_media_default_path.fx_path_current_entry =  0;
+    }
+#else
+
+    /* Set the current entry to 0 in order to pickup the first entry.  */
+    media_ptr -> fx_media_default_path.fx_path_current_entry =  0;
+#endif
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* Call the next directory full entry service to pickup the first entry.  */
+    status =  _fx_directory_next_full_entry_find(media_ptr, directory_name, attributes,
+                                                 size, year, month, day, hour, minute, second);
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_free_search.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_free_search.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_free_search.c	(revision 30)
@@ -0,0 +1,782 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_directory.h"
+#include "fx_utility.h"
+#ifdef FX_ENABLE_EXFAT
+#include "fx_directory_exFAT.h"
+#endif /* FX_ENABLE_EXFAT */
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_directory_free_search                           PORTABLE C      */
+/*                                                           6.1.12       */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function searches the media for a free directory entry.        */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    directory_ptr                         Pointer to directory to       */
+/*                                            search in                   */
+/*    entry_ptr                             Pointer to directory entry    */
+/*                                            record                      */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_entry_read              Read entries from directory   */
+/*    _fx_directory_entry_write             Write entries to directory    */
+/*    _fx_utility_FAT_entry_read            Read a FAT entry              */
+/*    _fx_utility_FAT_entry_write           Write a FAT entry             */
+/*    _fx_utility_FAT_flush                 Flush written FAT entries     */
+/*    _fx_utility_logical_sector_flush      Flush logical sector cache    */
+/*    _fx_utility_logical_sector_read       Read logical sector           */
+/*    _fx_utility_logical_sector_write      Write logical sector          */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    FileX System Functions                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*  07-29-2022     Bhupendra Naphade        Modified comment(s),          */
+/*                                            updated available cluster   */
+/*                                            check for sub directory,    */
+/*                                            resulting in version 6.1.12 */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_directory_free_search(FX_MEDIA *media_ptr, FX_DIR_ENTRY *directory_ptr, FX_DIR_ENTRY *entry_ptr)
+{
+
+ULONG         i, j;
+UCHAR        *work_ptr;
+UINT          status, total_entries;
+ULONG         entry_sector, entry_offset;
+ULONG         FAT_index, FAT_value;
+ULONG         cluster, total_clusters, clusters_needed;
+ULONG         first_new_cluster, last_cluster, clusters;
+ULONG         directory_index;
+ULONG         directory_entries;
+ULONG         logical_sector;
+FX_DIR_ENTRY *search_dir_ptr;
+ULONG         free_entry_start;
+UINT          sectors;
+
+FX_INT_SAVE_AREA
+
+
+#ifdef FX_ENABLE_EXFAT
+    /* Check if media format is exFAT.  */
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+
+        /* Call exFAT specific function.  */
+        return(_fx_directory_exFAT_free_search(media_ptr, directory_ptr, entry_ptr));
+    }
+#endif /* FX_ENABLE_EXFAT */
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of directory free entry search requests.  */
+    media_ptr -> fx_media_directory_free_searches++;
+#endif
+
+    /* Initialize the entry sector values.  */
+    entry_sector = entry_offset = 0;
+
+    /* Set the long file name flag to false.  */
+    entry_ptr -> fx_dir_entry_long_name_present =  0;
+
+    /* Are there leading dots?  */
+    if (entry_ptr -> fx_dir_entry_name[0] == '.')
+    {
+
+        /* Is there more than 1 dot?  */
+        if (entry_ptr -> fx_dir_entry_name[1] == '.')
+        {
+            /* Yes, consider the name invalid.  */
+            return(FX_INVALID_NAME);
+        }
+    }
+
+    /* Determine if a long file name is present.  */
+    for (i = 0, j = 0; entry_ptr -> fx_dir_entry_name[i]; i++)
+    {
+
+        /* Check for upper-case characters.  */
+        if ((entry_ptr -> fx_dir_entry_name[i] >= 'A') && (entry_ptr -> fx_dir_entry_name[i] <= 'Z'))
+        {
+            continue;
+        }
+        /* Check for numeric characters.  */
+        else if ((entry_ptr -> fx_dir_entry_name[i] >= '0') && (entry_ptr -> fx_dir_entry_name[i] <= '9'))
+        {
+            continue;
+        }
+        /* Check for any lower-case characters.  */
+        else if ((entry_ptr -> fx_dir_entry_name[i] >= 'a') && (entry_ptr -> fx_dir_entry_name[i] <= 'z'))
+        {
+            entry_ptr -> fx_dir_entry_long_name_present =  1;
+        }
+        /* Check for a space in the middle of the name.  */
+        else if (entry_ptr -> fx_dir_entry_name[i] == ' ')
+        {
+            entry_ptr -> fx_dir_entry_long_name_present = 1;
+        }
+        /* Check for a dot in the name.  */
+        else if (entry_ptr -> fx_dir_entry_name[i] == '.')
+        {
+            /* Determine if this is the first dot detected.  */
+            if (j == 0)
+            {
+                /* First dot, remember where it was.  */
+                j = i;
+
+                /* Determine if this is a leading dot.  */
+                if (i == 0)
+                {
+
+                    /* Leading dot detected, treat as a long filename.  */
+                    entry_ptr -> fx_dir_entry_long_name_present =  1;
+                }
+            }
+            else
+            {
+                /* Second dot detected, must have a long file name.  */
+                entry_ptr -> fx_dir_entry_long_name_present = 1;
+            }
+        }
+        /* Check for a special 0xE5 character.  */
+        else if ((UCHAR)entry_ptr -> fx_dir_entry_name[i] == (UCHAR)0xE5)
+        {
+            entry_ptr -> fx_dir_entry_long_name_present = 1;
+        }
+        /* Check for code point value greater than 127.  */
+        else if ((UCHAR)entry_ptr -> fx_dir_entry_name[i] > (UCHAR)127)
+        {
+            continue;
+        }
+        /* Check for any special characters.  */
+        else if ((entry_ptr -> fx_dir_entry_name[i] == '~') ||
+                 (entry_ptr -> fx_dir_entry_name[i] == '-') ||
+                 (entry_ptr -> fx_dir_entry_name[i] == '_') ||
+                 (entry_ptr -> fx_dir_entry_name[i] == '}') ||
+                 (entry_ptr -> fx_dir_entry_name[i] == '{') ||
+                 (entry_ptr -> fx_dir_entry_name[i] == '(') ||
+                 (entry_ptr -> fx_dir_entry_name[i] == ')') ||
+                 (entry_ptr -> fx_dir_entry_name[i] == '`') ||
+                 (entry_ptr -> fx_dir_entry_name[i] == '\'') ||
+                 (entry_ptr -> fx_dir_entry_name[i] == '!') ||
+                 (entry_ptr -> fx_dir_entry_name[i] == '#') ||
+                 (entry_ptr -> fx_dir_entry_name[i] == '$') ||
+                 (entry_ptr -> fx_dir_entry_name[i] == '&') ||
+                 (entry_ptr -> fx_dir_entry_name[i] == '@') ||
+                 (entry_ptr -> fx_dir_entry_name[i] == '^') ||
+                 (entry_ptr -> fx_dir_entry_name[i] == '%'))
+        {
+            continue;
+        }
+        /* Check for long filename special characters.  */
+        else if ((entry_ptr -> fx_dir_entry_name[i] == '+') ||
+                 (entry_ptr -> fx_dir_entry_name[i] == ',') ||
+                 (entry_ptr -> fx_dir_entry_name[i] == ';') ||
+                 (entry_ptr -> fx_dir_entry_name[i] == '=') ||
+                 (entry_ptr -> fx_dir_entry_name[i] == '[') ||
+                 (entry_ptr -> fx_dir_entry_name[i] == ']'))
+        {
+            entry_ptr -> fx_dir_entry_long_name_present = 1;
+        }
+        /* Something is wrong with the supplied name.  */
+        else
+        {
+            return(FX_INVALID_NAME);
+        }
+    }
+
+    /* Determine if a dot was found.  */
+    if (j != 0)
+    {
+
+        /* Yes, Determine if the extension exceeds a 3 character extension.  */
+        if ((i - j) > 4)
+        {
+
+            /* Yes, long file name is present.  */
+            entry_ptr -> fx_dir_entry_long_name_present = 1;
+        }
+    }
+
+    /* Calculate the total entries needed.  */
+    if ((i <= 12) && (entry_ptr -> fx_dir_entry_long_name_present == 0))
+    {
+
+        /* Initialize the total entries to 1.  */
+        total_entries = 1;
+
+        /* Check for special instance of long file name.  */
+        if ((j >= 9) || ((i - j) >= 9))
+        {
+
+            /* The dot is after 8 character or there is no dot and the name
+               is greater than 8 character. */
+            entry_ptr -> fx_dir_entry_long_name_present = 1;
+            total_entries = 2;
+        }
+    }
+    else
+    {
+
+        /* Long file name is present, calculate how many entries are needed
+           to represent it.  */
+        if (i % 13 == 0)
+        {
+            /* Exact fit, just add one for the 8.3 short name.  */
+            total_entries = i / 13 + 1;
+        }
+        else
+        {
+            /* Non-exact fit, add two for 8.3 short name and overlap.  */
+            total_entries = i / 13 + 2;
+        }
+    }
+
+    /* Determine if the search is in the root directory or in a
+       sub-directory.  Note: the directory search function clears the
+       first character of the name for the root directory.  */
+    if (directory_ptr -> fx_dir_entry_name[0])
+    {
+
+        /* Search for a free entry in a sub-directory.  */
+
+        /* Pickup the number of entries in this directory.  This was placed
+           into the unused file size field.  */
+        directory_entries =  (ULONG)directory_ptr -> fx_dir_entry_file_size;
+
+        /* Point the search directory pointer to this entry.  */
+        search_dir_ptr =  directory_ptr;
+
+        /* Ensure that the search directory's last search cluster is cleared.  */
+        search_dir_ptr -> fx_dir_entry_last_search_cluster =  0;
+
+        /* Set the initial index to 2, since the first two directory entries are
+           always allocated.  */
+        directory_index =  2;
+    }
+    else
+    {
+
+        /* Find a free entry in the root directory.  */
+
+        /* Setup the number of directory entries.  */
+        directory_entries =  (ULONG)media_ptr -> fx_media_root_directory_entries;
+
+        /* Set the search pointer to NULL since we are working off of the
+           root directory.  */
+        search_dir_ptr =  FX_NULL;
+
+        /* Set the initial index to 0, since the first entry of the root directory is valid.  */
+        directory_index =  0;
+    }
+
+    /* Loop through entries in the search directory.  Yes, this is a
+       linear search!  */
+    free_entry_start = directory_entries;
+    do
+    {
+
+        /* Read an entry from the directory.  */
+        status =  _fx_directory_entry_read(media_ptr, search_dir_ptr, &directory_index, entry_ptr);
+
+        /* Check for error status.  */
+        if (status != FX_SUCCESS)
+        {
+            return(status);
+        }
+
+        /* Determine if this is an empty entry.  */
+        if ((((UCHAR)entry_ptr -> fx_dir_entry_name[0] == (UCHAR)FX_DIR_ENTRY_FREE) && (entry_ptr -> fx_dir_entry_short_name[0] == 0)) ||
+            ((UCHAR)entry_ptr -> fx_dir_entry_name[0] == (UCHAR)FX_DIR_ENTRY_DONE))
+        {
+
+            /* Determine how many entries are needed.  */
+            if (total_entries > 1)
+            {
+
+                /* Multiple entries are needed for long file names.  Mark this
+                   entry as free. */
+                if (entry_ptr -> fx_dir_entry_name[0] == FX_DIR_ENTRY_DONE)
+                {
+
+                    entry_ptr -> fx_dir_entry_long_name_present =  0;
+                    entry_ptr -> fx_dir_entry_name[0] =      (CHAR)FX_DIR_ENTRY_FREE;
+                    entry_ptr -> fx_dir_entry_name[1] =      (CHAR)0;
+
+                    /* Write out the directory entry.  */
+                    status = _fx_directory_entry_write(media_ptr, entry_ptr);
+                    if(status != FX_SUCCESS)
+                    {  
+                        return(status);
+                    }
+  
+                    /* Note that for long names we need to avoid holes in the middle,
+                       i.e. entries must be logically contiguous.  */
+                }
+            }
+
+            /* Determine if we are at the first free entry.  */
+            if (free_entry_start == directory_entries)
+            {
+
+                /* Remember the start of the free entry.  */
+                free_entry_start =  directory_index;
+                entry_sector =      (ULONG)entry_ptr -> fx_dir_entry_log_sector;
+                entry_offset  =     entry_ptr -> fx_dir_entry_byte_offset;
+            }
+
+            /* Determine if there are enough free entries to satisfy the request.  */
+            if ((directory_index - free_entry_start + 1) >= total_entries)
+            {
+
+                /* Found an empty slot.  Most pertinent information is already
+                   in the entry structure.  */
+
+                /* Setup the the sector and the offset.  */
+                entry_ptr -> fx_dir_entry_log_sector =      entry_sector;
+                entry_ptr -> fx_dir_entry_byte_offset =     entry_offset;
+
+                /* Initialize the additional directory entries.  */
+                entry_ptr -> fx_dir_entry_reserved =            0;
+                entry_ptr -> fx_dir_entry_created_time_ms =     0;
+
+                /* Lockout interrupts for time/date access.  */
+                FX_DISABLE_INTS
+
+                entry_ptr -> fx_dir_entry_created_time =        _fx_system_time;
+                entry_ptr -> fx_dir_entry_created_date =        _fx_system_date;
+                entry_ptr -> fx_dir_entry_last_accessed_date =  _fx_system_date;
+
+                /* Restore interrupts.  */
+                FX_RESTORE_INTS
+
+                /* Determine if a long file name is present.  */
+                if (total_entries == 1)
+                {
+                    entry_ptr -> fx_dir_entry_long_name_present =  0;
+                }
+                else
+                {
+                    entry_ptr -> fx_dir_entry_long_name_present =  1;
+                }
+
+                /* Return a successful completion.  */
+                return(FX_SUCCESS);
+            }
+        }
+        else
+        {
+
+            /* Reset the free entry start.  */
+            free_entry_start =  directory_entries;
+        }
+
+        /* Move to the next entry.  */
+        directory_index++;
+
+        /* Determine if we have exceeded the number of entries in the current directory.  */
+        if (directory_index >= directory_entries)
+        {
+
+            /* Calculate how many sectors we need for the new directory entry.  */
+            sectors =  ((total_entries * FX_DIR_ENTRY_SIZE) + (media_ptr -> fx_media_bytes_per_sector - 1))/
+                                                                            media_ptr -> fx_media_bytes_per_sector;
+
+            /* Now calculate how many clusters we need for the new directory entry.  */
+            clusters_needed = (sectors + (media_ptr -> fx_media_sectors_per_cluster - 1)) / media_ptr -> fx_media_sectors_per_cluster;
+
+            /* Not enough empty entries were found.  If the specified directory is a sub-directory,
+               attempt to allocate another cluster to it.  */
+            if (((search_dir_ptr) || (media_ptr -> fx_media_32_bit_FAT)) && (media_ptr -> fx_media_available_clusters >= clusters_needed))
+            {
+
+                /* Search for the additional clusters we need.  */
+                first_new_cluster =  0;
+                total_clusters =     media_ptr -> fx_media_total_clusters;
+                last_cluster =       0;
+                FAT_index    =       media_ptr -> fx_media_cluster_search_start;
+                clusters =           clusters_needed;
+
+                /* Loop to find the needed clusters.  */
+                while (clusters)
+                {
+
+                    /* Decrease the cluster count.  */
+                    clusters--;
+
+                    /* Loop to find the first available cluster.  */
+                    do
+                    {
+
+                        /* Make sure we stop looking after one pass through the FAT table.  */
+                        if (!total_clusters)
+                        {
+
+                            /* Something is wrong with the media - the desired clusters were
+                               not found in the FAT table.  */
+                            return(FX_NO_MORE_SPACE);
+                        }
+
+                        /* Read FAT entry.  */
+                        status =  _fx_utility_FAT_entry_read(media_ptr, FAT_index, &FAT_value);
+
+                        /* Check for a bad status.  */
+                        if (status != FX_SUCCESS)
+                        {
+
+                            /* Return the bad status.  */
+                            return(status);
+                        }
+
+                        /* Decrement the total cluster count.  */
+                        total_clusters--;
+
+                        /* Determine if the FAT entry is free.  */
+                        if (FAT_value == FX_FREE_CLUSTER)
+                        {
+
+                            /* Move cluster search pointer forward.  */
+                            media_ptr -> fx_media_cluster_search_start =  FAT_index + 1;
+
+                            /* Determine if this needs to be wrapped.  */
+                            if (media_ptr -> fx_media_cluster_search_start >= (media_ptr -> fx_media_total_clusters + FX_FAT_ENTRY_START))
+                            {
+
+                                /* Wrap the search to the beginning FAT entry.  */
+                                media_ptr -> fx_media_cluster_search_start =  FX_FAT_ENTRY_START;
+                            }
+
+                            /* Break this loop.  */
+                            break;
+                        }
+                        else
+                        {
+
+                            /* FAT entry is not free... Advance the FAT index.  */
+                            FAT_index++;
+
+                            /* Determine if we need to wrap the FAT index around.  */
+                            if (FAT_index >= (media_ptr -> fx_media_total_clusters + FX_FAT_ENTRY_START))
+                            {
+
+                                /* Wrap the search to the beginning FAT entry.  */
+                                FAT_index =  FX_FAT_ENTRY_START;
+                            }
+                        }
+                    } while (FX_TRUE);
+
+                    /* We found an available cluster.  We now need to clear all of entries in
+                       each of the cluster's sectors.  */
+
+                    /* Calculate the logical sector of this cluster.  */
+                    logical_sector =  ((ULONG) media_ptr -> fx_media_data_sector_start) +
+                                       ((((ULONG) FAT_index) - FX_FAT_ENTRY_START) *
+                                       ((ULONG) media_ptr -> fx_media_sectors_per_cluster));
+
+                    /* Pickup the number of sectors for the next directory cluster.  */
+                    sectors =  media_ptr -> fx_media_sectors_per_cluster;
+
+                    /* Read the logical sector just for cache reasons.  */
+                    status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) logical_sector,
+                                                              media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
+
+                    /* Check the return value.  */
+                    if (status != FX_SUCCESS)
+                    {
+
+                        /* Return the error status.  */
+                        return(status);
+                    }
+
+                    /* Clear the entire first sector of the new sub-directory cluster.  */
+                    work_ptr =  (UCHAR *)media_ptr -> fx_media_memory_buffer;
+                    i =  0;
+                    while (i < media_ptr -> fx_media_bytes_per_sector)
+                    {
+
+                        /* Clear 4 bytes.  */
+                        *((ULONG *)work_ptr) =  (ULONG)0;
+
+                        /* Increment pointer.  */
+                        work_ptr =  work_ptr + sizeof(ULONG);
+
+                        /* Increment counter.  */
+                        i =  i + (ULONG)sizeof(ULONG);
+                    }
+
+                    /* Write the logical sector to ensure the zeros are written.  */
+                    status =  _fx_utility_logical_sector_write(media_ptr, (ULONG64) logical_sector,
+                                                               media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
+
+                    /* Determine if the write was successful.  */
+                    if (status != FX_SUCCESS)
+                    {
+
+                        /* Return the error code.  */
+                        return(status);
+                    }
+
+                    /* Determine if there are more sectors to clear in the first cluster of the new
+                       sub-directory.  */
+                    if (sectors > 1)
+                    {
+
+                        /* Yes, invalidate all cached sectors that are contained in the newly allocated first
+                           cluster of the directory.  */
+
+                        /* Flush the internal logical sector cache.  */
+                        status =  _fx_utility_logical_sector_flush(media_ptr, (ULONG64) (logical_sector + 1), (ULONG64) (sectors - 1), FX_TRUE);
+
+                        /* Determine if the flush was successful.  */
+                        if (status != FX_SUCCESS)
+                        {
+
+                            /* Return the error code.  */
+                            return(status);
+                        }
+
+                        /* Clear all additional sectors of new sub-directory.  */
+                        sectors--;
+                        while (sectors)
+                        {
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+                            /* Increment the number of driver write sector(s) requests.  */
+                            media_ptr -> fx_media_driver_write_requests++;
+#endif
+
+                            /* Build Write request to the driver.  */
+                            media_ptr -> fx_media_driver_request =          FX_DRIVER_WRITE;
+                            media_ptr -> fx_media_driver_status =           FX_IO_ERROR;
+                            media_ptr -> fx_media_driver_buffer =           media_ptr -> fx_media_memory_buffer;
+                            media_ptr -> fx_media_driver_logical_sector =   (ULONG)logical_sector + ((ULONG)sectors);
+                            media_ptr -> fx_media_driver_sectors =          1;
+                            media_ptr -> fx_media_driver_sector_type =      FX_DIRECTORY_SECTOR;
+
+                            /* Set the system write flag since we are writing a directory sector.  */
+                            media_ptr -> fx_media_driver_system_write =  FX_TRUE;
+
+                            /* If trace is enabled, insert this event into the trace buffer.  */
+                            FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_WRITE, media_ptr, ((ULONG)logical_sector) + ((ULONG)sectors), 1, media_ptr -> fx_media_memory_buffer, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+                            /* Invoke the driver to write the sector.  */
+                            (media_ptr -> fx_media_driver_entry) (media_ptr);
+
+                            /* Clear the system write flag.  */
+                            media_ptr -> fx_media_driver_system_write =  FX_FALSE;
+
+                            /* Determine if an error occurred.  */
+                            if (media_ptr -> fx_media_driver_status != FX_SUCCESS)
+                            {
+
+                                /* Return error code.  */
+                                return(media_ptr -> fx_media_driver_status);
+                            }
+
+                            /* Decrease the number of sectors to clear.  */
+                            sectors--;
+                        }
+                    }
+
+                    /* Determine if we have found the first new cluster yet.  */
+                    if (first_new_cluster == 0)
+                    {
+
+                        /* Remember the first new cluster. */
+                        first_new_cluster =  FAT_index;
+                    }
+
+                    /* Check for a valid last cluster to link.  */
+                    if (last_cluster)
+                    {
+
+                        /* Normal condition - link the last cluster with the new
+                           found cluster.  */
+                        status = _fx_utility_FAT_entry_write(media_ptr, last_cluster, FAT_index);
+
+                        /* Check for a bad FAT write status.  */
+                        if (status !=  FX_SUCCESS)
+                        {
+
+                            /* Return the bad status.  */
+                            return(status);
+                        }
+                    }
+
+                    /* Otherwise, remember the new FAT index as the last.  */
+                    last_cluster =  FAT_index;
+
+                    /* Move to the next FAT entry.  */
+                    FAT_index =  media_ptr -> fx_media_cluster_search_start;
+                }
+
+                /* Place an end-of-file marker on the last cluster.  */
+                status = _fx_utility_FAT_entry_write(media_ptr, last_cluster, media_ptr -> fx_media_fat_last);
+
+                /* Check for a bad FAT write status.  */
+                if (status !=  FX_SUCCESS)
+                {
+
+                    /* Return the bad status.  */
+                    return(status);
+                }
+
+#ifdef FX_FAULT_TOLERANT
+
+                /* Ensure the new FAT chain is properly written to the media.  */
+
+                /* Flush the cached individual FAT entries */
+                _fx_utility_FAT_flush(media_ptr);
+#endif
+
+                /* Now the new cluster needs to be linked to the sub-directory.  */
+                if (search_dir_ptr)
+                {
+                    cluster = search_dir_ptr -> fx_dir_entry_cluster;
+                }
+                else
+                {
+                    cluster = media_ptr -> fx_media_root_cluster_32;
+                }
+
+                /* Initialize loop variables.  */
+                last_cluster =  0;
+                i =  0;
+
+                /* Follow the link of FAT entries.  */
+                while (cluster < media_ptr -> fx_media_fat_reserved)
+                {
+
+                    /* Read the current cluster entry from the FAT.  */
+                    status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &FAT_value);
+                    i++;
+
+                    /* Check the return value.  */
+                    if (status != FX_SUCCESS)
+                    {
+
+                        /* Return the error status.  */
+                        return(status);
+                    }
+
+                    /* Determine if the FAT read was invalid.  */
+                    if ((cluster < FX_FAT_ENTRY_START) || (cluster == FAT_value) || (i > media_ptr -> fx_media_total_clusters))
+                    {
+
+                        /* Return the bad status.  */
+                        return(FX_FAT_READ_ERROR);
+                    }
+
+                    /* Save the last valid cluster.  */
+                    last_cluster =  cluster;
+
+                    /* Setup for the next cluster.  */
+                    cluster =  FAT_value;
+                }
+
+                /* Decrease the available clusters in the media.  */
+                media_ptr -> fx_media_available_clusters =  media_ptr -> fx_media_available_clusters - clusters_needed;
+
+                /* Increase the number of directory entries.  */
+                directory_entries =  directory_entries + ((clusters_needed * media_ptr -> fx_media_sectors_per_cluster) * media_ptr -> fx_media_bytes_per_sector) / FX_DIR_ENTRY_SIZE;
+
+                /* Determine if we need to reset the free entry start since we changed the
+                   number of directory entries.  If the last entry was not free, then we
+                   should definitely reset the free entry start.  */
+                if (!(((UCHAR)entry_ptr -> fx_dir_entry_name[0] == (UCHAR) FX_DIR_ENTRY_FREE) && (entry_ptr -> fx_dir_entry_short_name[0] == 0)))
+                {
+
+                    /* Reset the free entry start to indicate we haven't found a starting free entry yet.  */
+                    free_entry_start =  directory_entries;
+                }
+
+                /* Update the directory size field.  */
+                directory_ptr -> fx_dir_entry_file_size =  directory_entries;
+
+                /* Defer the update of the FAT entry and the last cluster of the current
+                   directory entry until after the new cluster is initialized and written out.  */
+
+                /* Determine if a FAT32 is present.  */
+                if ((media_ptr -> fx_media_32_bit_FAT) && (search_dir_ptr == FX_NULL))
+                {
+
+                    /* Change root directory entry count - FAT32 has a variable sized root directory.  */
+                    media_ptr -> fx_media_root_directory_entries =  directory_entries;
+                }
+
+                /* At this point, link up the last cluster with the new cluster.  */
+                status =  _fx_utility_FAT_entry_write(media_ptr, last_cluster, first_new_cluster);
+
+                /* Check the return value.  */
+                if (status != FX_SUCCESS)
+                {
+
+                    /* Return the error status.  */
+                    return(status);
+                }
+
+#ifdef FX_FAULT_TOLERANT
+
+                /* Flush the cached individual FAT entries */
+                _fx_utility_FAT_flush(media_ptr);
+#endif
+            }
+        }
+    } while (directory_index < directory_entries);
+
+    /* Return FX_NO_MORE_SPACE status to the caller.  */
+    return(FX_NO_MORE_SPACE);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_information_get.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_information_get.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_information_get.c	(revision 30)
@@ -0,0 +1,235 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_directory.h"
+#include "fx_file.h"
+#include "fx_utility.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_directory_information_get                       PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function first attempts to find the specified directory name.  */
+/*    If found, the complete file parameters are placed in all non-NULL   */
+/*    return parameters.  If the file name is not found, the appropriate  */
+/*    error code is returned to the caller.                               */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    directory_name                        Directory name pointer        */
+/*    attributes                            Pointer to attributes         */
+/*    size                                  Pointer to size               */
+/*    year                                  Pointer to year               */
+/*    month                                 Pointer to month              */
+/*    day                                   Pointer to day                */
+/*    hour                                  Pointer to hour               */
+/*    minute                                Pointer to minute             */
+/*    second                                Pointer to second             */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_search                  Search for the file name in   */
+/*                                          the directory structure       */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s), verified */
+/*                                            memcpy usage,               */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_directory_information_get(FX_MEDIA *media_ptr, CHAR *directory_name,
+                                    UINT *attributes, ULONG *size,
+                                    UINT *year, UINT *month, UINT *day,
+                                    UINT *hour, UINT *minute, UINT *second)
+{
+
+UINT         status;
+FX_DIR_ENTRY dir_entry;
+ULONG        open_count;
+FX_FILE     *search_ptr;
+
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of times this service has been called.  */
+    media_ptr -> fx_media_directory_information_gets++;
+#endif
+
+    /* Setup pointer to media name buffer.  */
+    dir_entry.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
+
+    /* Clear the short name string.  */
+    dir_entry.fx_dir_entry_short_name[0] =  0;
+
+    /* Check the media to make sure it is open.  */
+    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
+    {
+
+        /* Return the media not opened error.  */
+        return(FX_MEDIA_NOT_OPEN);
+    }
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_DIRECTORY_INFORMATION_GET, media_ptr, directory_name, 0, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+    /* Search the system for the supplied directory name.  */
+    status =  _fx_directory_search(media_ptr, directory_name, &dir_entry, FX_NULL, FX_NULL);
+
+    /* Determine if the search was successful.  */
+    if (status != FX_SUCCESS)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the error code.  */
+        return(status);
+    }
+
+    /* Check the list of open files for others open for writing.  */
+    open_count =  media_ptr -> fx_media_opened_file_count;
+    search_ptr =  media_ptr -> fx_media_opened_file_list;
+    while (open_count)
+    {
+
+        /* Look at each opened file to see if the same file is opened
+           for writing.  */
+        if ((search_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector == dir_entry.fx_dir_entry_log_sector) &&
+            (search_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset == dir_entry.fx_dir_entry_byte_offset) &&
+            (search_ptr -> fx_file_open_mode))
+        {
+
+            /* The file has been opened for writing by a previous call. Use the information used by
+               the writer instead of what is currently on the media.  */
+            _fx_utility_memory_copy((UCHAR *)&search_ptr -> fx_file_dir_entry, (UCHAR *)&dir_entry, sizeof(FX_DIR_ENTRY)); /* Use case of memcpy is verified. */
+            break;
+        }
+
+        /* Adjust the pointer and decrement the search count.  */
+        search_ptr =  search_ptr -> fx_file_opened_next;
+        open_count--;
+    }
+
+    /* Check to see if attributes are required.  */
+    if (attributes)
+    {
+
+        /* Pickup the attributes.  */
+        *attributes =  dir_entry.fx_dir_entry_attributes;
+    }
+
+    /* Check to see if the size is required.  */
+    if (size)
+    {
+
+        /* Pickup the size.  */
+        *size =  (ULONG)dir_entry.fx_dir_entry_file_size;
+    }
+
+    /* Check to see if the year is required.  */
+    if (year)
+    {
+
+        /* Pickup the year.  */
+        *year =  ((dir_entry.fx_dir_entry_date >> FX_YEAR_SHIFT) & FX_YEAR_MASK) +
+                                                                        FX_BASE_YEAR;
+    }
+
+    /* Check to see if the month is required.  */
+    if (month)
+    {
+
+        /* Pickup the month.  */
+        *month =  (dir_entry.fx_dir_entry_date >> FX_MONTH_SHIFT) & FX_MONTH_MASK;
+    }
+
+    /* Check to see if the day is required.  */
+    if (day)
+    {
+
+        /* Pickup the day.  */
+        *day =  dir_entry.fx_dir_entry_date & FX_DAY_MASK;
+    }
+
+    /* Check to see if the hour is required.  */
+    if (hour)
+    {
+
+        /* Pickup the hour.  */
+        *hour =  (dir_entry.fx_dir_entry_time >> FX_HOUR_SHIFT) & FX_HOUR_MASK;
+    }
+
+    /* Check to see if the minute is required.  */
+    if (minute)
+    {
+
+        /* Pickup the minute.  */
+        *minute =  (dir_entry.fx_dir_entry_time >> FX_MINUTE_SHIFT) & FX_MINUTE_MASK;
+    }
+
+    /* Check to see if the second is required.  */
+    if (second)
+    {
+
+        /* Pickup the second.  */
+        *second =  (dir_entry.fx_dir_entry_time & FX_SECOND_MASK) * 2;
+    }
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* Directory information get is complete, return successful status.  */
+    return(FX_SUCCESS);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_local_path_clear.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_local_path_clear.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_local_path_clear.c	(revision 30)
@@ -0,0 +1,114 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_file.h"
+#include "fx_utility.h"
+#include "fx_directory.h"
+
+#ifndef FX_NO_LOCAL_PATH
+FX_LOCAL_PATH_SETUP
+#endif
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_directory_local_path_clear                      PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function clears the local default directory of the media so    */
+/*    any path relative operations will start using the media's global    */
+/*    default path again.                                                 */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_directory_local_path_clear(FX_MEDIA *media_ptr)
+{
+
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of times this service has been called.  */
+    media_ptr -> fx_media_directory_local_path_clears++;
+#endif
+
+    /* Check the media to make sure it is open.  */
+    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
+    {
+
+        /* Return the media not opened error.  */
+        return(FX_MEDIA_NOT_OPEN);
+    }
+
+#ifdef FX_NO_LOCAL_PATH
+
+    /* Error, return to caller.  */
+    return(FX_NOT_IMPLEMENTED);
+#else
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_DIRECTORY_LOCAL_PATH_CLEAR, media_ptr, 0, 0, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
+
+    /* Clear this thread's local path pointer.  */
+    _tx_thread_current_ptr -> tx_thread_filex_ptr =  FX_NULL;
+
+    /* Local default directory clear is complete, return status.  */
+    return(FX_SUCCESS);
+#endif
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_local_path_get.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_local_path_get.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_local_path_get.c	(revision 30)
@@ -0,0 +1,129 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_file.h"
+#include "fx_utility.h"
+#include "fx_directory.h"
+
+#ifndef FX_NO_LOCAL_PATH
+FX_LOCAL_PATH_SETUP
+#endif
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_directory_local_path_get                        PORTABLE C      */
+/*                                                           6.1.5        */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function returns a pointer to the local default directory      */
+/*    for this thread.                                                    */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    return_path_name                      Return local path name        */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*  03-02-2021     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1.5  */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_directory_local_path_get(FX_MEDIA *media_ptr, CHAR **return_path_name)
+{
+
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of times this service has been called.  */
+    media_ptr -> fx_media_directory_local_path_gets++;
+#endif
+
+    /* Check the media to make sure it is open.  */
+    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
+    {
+
+        /* Return the media not opened error.  */
+        return(FX_MEDIA_NOT_OPEN);
+    }
+
+#ifdef FX_NO_LOCAL_PATH
+
+    FX_PARAMETER_NOT_USED(return_path_name);
+
+    /* Error, return to caller.  */
+    return(FX_NOT_IMPLEMENTED);
+#else
+
+    /* Determine if there is a local path.  */
+    if (_tx_thread_current_ptr -> tx_thread_filex_ptr)
+    {
+
+        /* Return a pointer to the current local directory path string.  */
+        *return_path_name =  ((FX_LOCAL_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr) -> fx_path_string;
+    }
+    else
+    {
+
+        /* Just set the return value to FX_NULL to indicate there is no
+           local path setup.  */
+        *return_path_name =  FX_NULL;
+    }
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_DIRECTORY_LOCAL_PATH_GET, media_ptr, return_path_name, 0, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
+
+    /* Local default directory has been returned, return status.  */
+    return(FX_SUCCESS);
+#endif
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_local_path_get_copy.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_local_path_get_copy.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_local_path_get_copy.c	(revision 30)
@@ -0,0 +1,123 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_file.h"
+#include "fx_utility.h"
+#include "fx_directory.h"
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_directory_local_path_get_copy                   PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function copies the local default directory for this thread    */
+/*    into the specified buffer.                                          */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    return_path_name_buffer               Destination buffer for name   */
+/*    return_path_name_buffer_size          Size of buffer pointed to by  */
+/*                                            return_path_name_buffer     */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s), verified */
+/*                                            memcpy usage,               */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_directory_local_path_get_copy(FX_MEDIA *media_ptr, CHAR *return_path_name_buffer, UINT return_path_name_buffer_size)
+{
+
+UINT    status;
+CHAR    *return_path_name;
+UINT    path_name_length_with_null_terminator;
+
+
+    /* Get the pointer to the path.  */
+    status =  _fx_directory_local_path_get(media_ptr, &return_path_name);
+    if (status == FX_SUCCESS)
+    {
+
+        /* Was a path set?  */
+        if (return_path_name != FX_NULL)
+        {
+
+            /* Get the length of the path.  */
+            path_name_length_with_null_terminator =  _fx_utility_string_length_get(return_path_name, FX_MAXIMUM_PATH) + 1;
+
+            /* Can it fit in the user's buffer? */
+            if (path_name_length_with_null_terminator <= return_path_name_buffer_size)
+            {
+
+                /* Copy the path name into the user's buffer.  */
+                _fx_utility_memory_copy((UCHAR *) return_path_name, (UCHAR *) return_path_name_buffer, path_name_length_with_null_terminator); /* Use case of memcpy is verified. */
+            }
+            else
+            {
+
+                /* Buffer is too small. Return error.  */
+                return(FX_BUFFER_ERROR);
+            }
+        }
+        else
+        {
+
+            /* Set zero-length string.  */
+            return_path_name_buffer[0] = '\0';
+        }
+    }
+
+    /* Return status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_local_path_restore.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_local_path_restore.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_local_path_restore.c	(revision 30)
@@ -0,0 +1,117 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_file.h"
+#include "fx_utility.h"
+#include "fx_directory.h"
+
+#ifndef FX_NO_LOCAL_PATH
+FX_LOCAL_PATH_SETUP
+#endif
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_directory_local_path_restore                    PORTABLE C      */
+/*                                                           6.1.5        */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function restores the local default directory of the media to  */
+/*    the previous path specified by the caller.                          */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    local_path_ptr                        Local path control block ptr  */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*  03-02-2021     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1.5  */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_directory_local_path_restore(FX_MEDIA *media_ptr, FX_LOCAL_PATH *local_path_ptr)
+{
+
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of times this service has been called.  */
+    media_ptr -> fx_media_directory_local_path_restores++;
+#endif
+
+    /* Check the media to make sure it is open.  */
+    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
+    {
+
+        /* Return the media not opened error.  */
+        return(FX_MEDIA_NOT_OPEN);
+    }
+
+#ifdef FX_NO_LOCAL_PATH
+
+    FX_PARAMETER_NOT_USED(local_path_ptr);
+
+    /* Error, return to caller.  */
+    return(FX_NOT_IMPLEMENTED);
+#else
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_DIRECTORY_LOCAL_PATH_RESTORE, media_ptr, local_path_ptr, 0, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
+
+    /* Setup thread control block to use this local path pointer.  */
+    _tx_thread_current_ptr -> tx_thread_filex_ptr =  (VOID *)local_path_ptr;
+
+    /* Default directory restore is complete, return status.  */
+    return(FX_SUCCESS);
+#endif
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_local_path_set.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_local_path_set.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_local_path_set.c	(revision 30)
@@ -0,0 +1,451 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_file.h"
+#include "fx_utility.h"
+#include "fx_directory.h"
+
+#ifndef FX_NO_LOCAL_PATH
+FX_LOCAL_PATH_SETUP
+#endif
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_directory_local_path_set                        PORTABLE C      */
+/*                                                           6.1.5        */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function sets the local default directory of the media to the  */
+/*    path specified by the caller.  If this path is not found, an error  */
+/*    code is returned.                                                   */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    local_path                            Local path control block ptr  */
+/*    new_path_name                         New path to set current local */
+/*                                            working directory to        */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_search                  Search for the directory name */
+/*                                          in the directory structure    */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*  03-02-2021     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1.5  */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_directory_local_path_set(FX_MEDIA *media_ptr, FX_LOCAL_PATH *local_path_ptr, CHAR *new_path_name)
+{
+
+#ifndef FX_NO_LOCAL_PATH
+UINT         status;
+CHAR        *path_string_ptr;
+UINT         path_string_capacity;
+FX_PATH     *path_ptr;
+UINT         i, j;
+#endif
+FX_DIR_ENTRY dir_entry;
+
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of times this service has been called.  */
+    media_ptr -> fx_media_directory_local_path_sets++;
+#endif
+
+    /* Setup pointer to a name buffer.  */
+    dir_entry.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
+
+    /* Setup the local path name buffer pointer.  */
+    local_path_ptr -> fx_path_directory.fx_dir_entry_name =  local_path_ptr -> fx_path_name_buffer;
+
+    /* Clear the short name string.  */
+    dir_entry.fx_dir_entry_short_name[0] =  (CHAR)0;
+
+    /* Clear the long name string.  */
+    dir_entry.fx_dir_entry_name[0] =  (CHAR)0;
+
+    /* Check the media to make sure it is open.  */
+    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
+    {
+
+        /* Return the media not opened error.  */
+        return(FX_MEDIA_NOT_OPEN);
+    }
+
+#ifdef FX_NO_LOCAL_PATH
+
+    FX_PARAMETER_NOT_USED(new_path_name);
+
+    /* Error, return to caller.  */
+    return(FX_NOT_IMPLEMENTED);
+#else
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_DIRECTORY_LOCAL_PATH_SET, media_ptr, local_path_ptr, new_path_name, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+    /* Look for a root directory selection.  */
+    if ((!new_path_name) || (((new_path_name[0] == '\\') || (new_path_name[0] == '/')) && (new_path_name[1] == (CHAR)0)))
+    {
+
+        /* Set the default local directory to the root.  */
+        local_path_ptr -> fx_path_directory.fx_dir_entry_name[0] =  (CHAR)0;
+        local_path_ptr -> fx_path_string[0] =                       (CHAR)0;
+        local_path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] =       (CHAR)0;
+
+        /* Setup thread control block to use this local path pointer.  */
+        _tx_thread_current_ptr -> tx_thread_filex_ptr =  (VOID *)local_path_ptr;
+    }
+    else
+    {
+
+        /* Search the system for the supplied path and directory name.  */
+        status =  _fx_directory_search(media_ptr, new_path_name, &dir_entry, FX_NULL, FX_NULL);
+
+        /* Determine if the search failed or if the entry found is not a
+           directory.  */
+        if ((status != FX_SUCCESS) || (!(dir_entry.fx_dir_entry_attributes & FX_DIRECTORY)))
+        {
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* Invalid Path - Return the error code.  */
+            return(FX_INVALID_PATH);
+        }
+
+        /* Now update the current path string.  */
+
+        /* Setup the path string pointer to the start of the current path.  */
+        path_string_ptr =  &(local_path_ptr -> fx_path_string[0]);
+
+        /* Setup the path string's capacity.  */
+        path_string_capacity =  FX_MAXIMUM_PATH - 1;
+
+        /* Determine if the new path is relative from the current path.  */
+        if ((new_path_name[0] != '\\') && (new_path_name[0] != '/'))
+        {
+
+            /* Yes, a relative path was found.  */
+
+            /* Setup the default path pointer to the local path.  */
+            path_ptr =  local_path_ptr;
+
+            /* Determine if the local path is different than the current local path.  */
+            if (local_path_ptr !=  (FX_LOCAL_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr)
+            {
+
+                /* Yes, there is a difference.  */
+
+                /* Should we copy from the default media path or from the previous default
+                   path.  */
+                if (_tx_thread_current_ptr -> tx_thread_filex_ptr)
+                {
+
+                    /* There is a local path so copy the relative path info from it.  */
+                    i =  0;
+                    do
+                    {
+
+                        /* Copy from previous local to new local path.  */
+                        local_path_ptr -> fx_path_string[i] =
+                            ((FX_LOCAL_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr) -> fx_path_string[i];
+                            
+                        /* Determine if we are done.  */
+                        if (local_path_ptr -> fx_path_string[i] == 0)
+                        {
+                        
+                            /* Are we not at the end of the string?  */
+                            if (i < (FX_MAXIMUM_PATH - 1))
+                            {
+                            
+                                /* Yes, break the loop.  */
+                                break;
+                            }
+                        }
+                        
+                        /* Move to the next character.  */
+                        i++;
+                        
+                    } while (i < FX_MAXIMUM_PATH);
+                }
+                else
+                {
+
+                    /* No local path, so copy the relative path information from the media
+                       default.  */
+                    i =  0;
+                    do
+                    {
+
+                        /* Copy from the media default to new local path.  */
+                        local_path_ptr -> fx_path_string[i] =
+                            media_ptr -> fx_media_default_path.fx_path_string[i];
+                            
+                        /* Determine if we are done.  */
+                        if (local_path_ptr -> fx_path_string[i] == 0)
+                        {
+                        
+                            /* Are we not at the end of the string?  */
+                            if (i < (FX_MAXIMUM_PATH - 1))
+                            {
+                            
+                                /* Yes, break the loop.  */
+                                break;
+                            }
+                        }
+
+                        /* Move to the next character.  */
+                        i++;
+
+                    } while (i < FX_MAXIMUM_PATH);
+                }
+            }
+
+            /* First, check the current path for string overflow.  If this is set,
+               don't attempt to update the current path with relative information.
+               The path won't be valid again until a complete path is given.  */
+            if (path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] == '*')
+            {
+
+                /* Yes, don't update the string, just finish the path set processing.  */
+
+                /* Determine if we are at the root directory.  */
+                if (!dir_entry.fx_dir_entry_cluster)
+                {
+                    /* Set the current directory back to the root directory.  */
+                    dir_entry.fx_dir_entry_name[0] =  (CHAR)0;
+
+                    /* Clear the current path string.  */
+                    path_ptr -> fx_path_string[0] =  (CHAR)0;
+
+                    /* Clear the overflow flag in the current path string... just in
+                       case! */
+                    path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] =  (CHAR)0;
+                }
+
+                /* Copy the new directory entry into the media control block.  */
+                path_ptr -> fx_path_directory =  dir_entry;
+
+                /* Reset the local path name buffer pointer, since it was clobbered earlier.  */
+                local_path_ptr -> fx_path_directory.fx_dir_entry_name =  local_path_ptr -> fx_path_name_buffer;
+
+                /* Copy the directory name entry to the local path name area.  */
+                for (j = 0; j < FX_MAX_LONG_NAME_LEN; j++)
+                {
+
+                    /* Copy the name buffer.  */
+                    local_path_ptr -> fx_path_directory.fx_dir_entry_name[j] =  dir_entry.fx_dir_entry_name[j];
+                }
+
+                /* Setup thread control block to use this local path pointer.  */
+                _tx_thread_current_ptr -> tx_thread_filex_ptr =  (VOID *)local_path_ptr;
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* Default directory set is complete, return status.  */
+                return(FX_SUCCESS);
+            }
+
+            /* Move the current path starting pointer to the end of the current
+               path string.  */
+            while ((path_string_capacity) && (*path_string_ptr != FX_NULL))
+            {
+                path_string_ptr++;
+                path_string_capacity--;
+            }
+
+            /* If room, place the \ character in the path string.  */
+            if (path_string_capacity)
+            {
+
+                /* There is room, place the directory marker in the string.  */
+                *path_string_ptr++ =  '\\';
+                path_string_capacity--;
+            }
+        }
+        else
+        {
+
+            /* Setup the default path pointer.  */
+
+            /* Setup the default path pointer to the local path.  */
+            path_ptr =  local_path_ptr;
+
+            /* Complete path name given.  Check to see if we need to clear an
+               overflow character from a previous current path string update.  */
+            if (path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] == '*')
+            {
+                path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] = (CHAR)0;
+            }
+        }
+
+        /* Copy what we can into the current path.  */
+        while (*new_path_name)
+        {
+
+            /* Determine if there is a ".." character sequence that specifies the
+               previous path.  */
+            if ((*new_path_name == '.') && (*(new_path_name + 1) == '.'))
+            {
+
+                /* Yes, a backward path is found.  The current path pointer
+                   must be moved back to just after the previous \ character.  */
+
+                /* Skip the current \0 that is at the end of the current path.  */
+                path_string_capacity =  path_string_capacity + 2;
+                path_string_ptr =       path_string_ptr - 2;
+
+                while (path_string_capacity <= (FX_MAXIMUM_PATH - 1))
+                {
+
+                    /* Move the current path pointer backwards until
+                       a \ character is found.  */
+
+                    if ((*path_string_ptr == '\\') || (*path_string_ptr == '/'))
+                    {
+
+                        /* Yes, we have successfully backed up one directory.  */
+                        break;
+                    }
+
+                    /* Backup another character.  */
+                    path_string_capacity++;
+                    path_string_ptr--;
+                }
+
+                /* Adjust the new directory pointer past the .. characters  */
+                new_path_name =  new_path_name + 2;
+            }
+            else
+            {
+
+                /* Normal characters that need to be copied into the current path.  */
+
+                if (path_string_capacity)
+                {
+
+                    /* Copy character from the new path into the current path string.  */
+                    *path_string_ptr++ =  *new_path_name++;
+
+                    path_string_capacity--;
+                }
+                else
+                {
+
+                    /* No more room in the current path string!  */
+                    break;
+                }
+            }
+        }
+
+        /* Determine if there is still room in the current path string.  */
+        if (path_string_capacity)
+        {
+
+            /* Yes, there is still room, place a NULL character at the
+               end of the path.  */
+            *path_string_ptr =  (CHAR)FX_NULL;
+        }
+        else
+        {
+
+            /* No more room.  Determine if the entire path was successfully
+               copied into the current path.  */
+            if (*new_path_name)
+            {
+
+                /* No, we couldn't fit the entire path.  Place a "*" character
+                   at the end to indicate that we had overflow.  Note that
+                   the path is kept just the the directory default get call, so
+                   the new default path is valid.  */
+                path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] =  '*';
+            }
+        }
+
+        /* Determine if we are at the root directory.  */
+        if (!dir_entry.fx_dir_entry_cluster)
+        {
+            /* Set the current directory back to the root directory.  */
+            dir_entry.fx_dir_entry_name[0] =            (CHAR)0;
+            local_path_ptr -> fx_path_name_buffer[0] =  (CHAR)0;
+        }
+
+        /* Copy the new directory entry into the media control block.  */
+        path_ptr -> fx_path_directory =  dir_entry;
+
+        /* Reset the local path name buffer pointer, since it was clobbered earlier.  */
+        local_path_ptr -> fx_path_directory.fx_dir_entry_name =  local_path_ptr -> fx_path_name_buffer;
+
+        /* Copy the directory name entry to the local path name area.  */
+        for (j = 0; j < FX_MAX_LONG_NAME_LEN; j++)
+        {
+
+            /* Copy the name buffer.  */
+            local_path_ptr -> fx_path_directory.fx_dir_entry_name[j] =  dir_entry.fx_dir_entry_name[j];
+        }
+
+        /* Setup thread control block to use this local path pointer.  */
+        _tx_thread_current_ptr -> tx_thread_filex_ptr =  (VOID *)local_path_ptr;
+    }
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* Default directory set is complete, return status.  */
+    return(FX_SUCCESS);
+#endif
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_long_name_get.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_long_name_get.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_long_name_get.c	(revision 30)
@@ -0,0 +1,85 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_directory.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_directory_long_name_get                         PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function gets the long file name via the supplied short file   */
+/*    name. If there is no long file name, the short file name will be    */
+/*    returned.                                                           */
+/*                                                                        */
+/*    Note, this API is deprecated as fx_directory_long_name_get_extended */
+/*    should be used. The maximum written size to long_file_name could be */
+/*    FX_MAX_LONG_NAME_LEN.                                               */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    short_file_name                       Pointer to short (8.3) name   */
+/*    long_file_name                        Pointer to long (max 255) name*/
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_long_name_get_extended  Actual long name get service  */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_directory_long_name_get(FX_MEDIA *media_ptr, CHAR *short_file_name, CHAR *long_file_name)
+{
+
+    /* Call the extended version with maximum long name length.  */
+    return(_fx_directory_long_name_get_extended(media_ptr, short_file_name, long_file_name, FX_MAX_LONG_NAME_LEN));
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_long_name_get_extended.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_long_name_get_extended.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_long_name_get_extended.c	(revision 30)
@@ -0,0 +1,139 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_directory.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_directory_long_name_get_extended                PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function gets the long file name via the supplied short file   */
+/*    name. If there is no long file name, the short file name will be    */
+/*    returned.                                                           */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    short_file_name                       Pointer to short (8.3) name   */
+/*    long_file_name                        Pointer to long (max 255) name*/
+/*    long_file_name_buffer_length          Buffer length for long name   */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_search                  Search for the file name in   */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_directory_long_name_get_extended(FX_MEDIA *media_ptr, CHAR *short_file_name, CHAR *long_file_name, UINT long_file_name_buffer_length)
+{
+
+UINT         status;
+UINT         i;
+FX_DIR_ENTRY dir_entry;
+
+
+    /* Setup pointer to media name buffer.  */
+    dir_entry.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
+
+    /* Clear the short name string.  */
+    dir_entry.fx_dir_entry_short_name[0] =  0;
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_DIRECTORY_LONG_NAME_GET, media_ptr, short_file_name, long_file_name, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+    /* Search the system for the supplied short directory name.  */
+    status =  _fx_directory_search(media_ptr, short_file_name, &dir_entry, FX_NULL, FX_NULL);
+
+    /* Determine if the search was successful.  */
+    if (status != FX_SUCCESS)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the error code.  */
+        return(status);
+    }
+
+    /* Copy the long name portion into the destination string.  */
+    i =  0;
+    while ((i < (FX_MAX_LONG_NAME_LEN - 1)) && (dir_entry.fx_dir_entry_name[i]) && (i < (long_file_name_buffer_length - 1)))
+    {
+
+        /* Copy a character of the long name into the destination name.  */
+        long_file_name[i] =  dir_entry.fx_dir_entry_name[i];
+
+        /* Move to next character.  */
+        i++;
+    }
+
+    /* Ensure the long file name is NULL terminated.  */
+    long_file_name[i] =  FX_NULL;
+
+    /* Check if the buffer is too short for the name.  */
+    if ((i == (long_file_name_buffer_length - 1)) && (dir_entry.fx_dir_entry_name[i]))
+    {
+
+        /* Buffer too short, return error.  */
+        status = FX_BUFFER_ERROR;
+    }
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* Return the completion status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_name_extract.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_name_extract.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_name_extract.c	(revision 30)
@@ -0,0 +1,161 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_directory.h"
+#include "fx_utility.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_directory_name_extract                          PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function extracts the file name from the supplied input        */
+/*    string.  If there is nothing left after the extracted name, a NULL  */
+/*    is returned to the caller.  Otherwise, if something is left, a      */
+/*    pointer to it is returned.                                          */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    source_ptr                           Source string pointer          */
+/*    dest_ptr                             Destination string pointer     */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    Pointer to Next Name                 (if multiple directories)      */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    FileX System Functions                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+CHAR  *_fx_directory_name_extract(CHAR *source_ptr, CHAR *dest_ptr)
+{
+
+UINT i;
+
+
+    /* Set the destination string to NULL.  */
+    dest_ptr[0] = 0;
+
+    /* Is a backslash present?  */
+    if ((*source_ptr == '\\') || (*source_ptr == '/'))
+    {
+
+        /* Advance the string pointer.  */
+        source_ptr++;
+    }
+
+    /* Loop to remove any leading spaces.  */
+    while (*source_ptr == ' ')
+    {
+
+        /* Position past leading space.  */
+        source_ptr++;
+    }
+
+    /* Loop to extract the name.  */
+    i = 0;
+    while (*source_ptr)
+    {
+
+        /* If another backslash is present, break the loop.  */
+        if ((*source_ptr == '\\') || (*source_ptr == '/'))
+        {
+            break;
+        }
+
+        /* Long name can be at most 255 characters, but are further limited by the
+           FX_MAX_LONG_NAME_LEN define.  */
+        if (i == FX_MAX_LONG_NAME_LEN - 1)
+        {
+            break;
+        }
+
+        /* Store the character.  */
+        dest_ptr[i] =  *source_ptr++;
+
+        /* Increment the character counter.  */
+        i++;
+    }
+
+    /* NULL-terminate the string.  */
+    dest_ptr[i] =  0;
+
+    /* Determine if we can backup to the previous character.  */
+    if (i)
+    {
+
+        /* Yes, we can move backwards.  */
+        i--;
+    }
+
+    /* Get rid of trailing blanks in the destination string.  */
+    while (dest_ptr[i] == ' ')
+    {
+
+        /* Set this entry to NULL.  */
+        dest_ptr[i] =  0;
+
+        /* Backup to the next character. Since leading spaces have been removed,
+           we know that the index is always greater than 1.  */
+        i--;
+    }
+
+    /* Determine if the source string is now at the end.  */
+    if (*source_ptr == 0)
+    {
+
+        /* Yes, return a NULL pointer.  */
+        source_ptr = FX_NULL;
+    }
+
+    /* Return the last pointer position in the source.  */
+    return(source_ptr);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_name_test.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_name_test.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_name_test.c	(revision 30)
@@ -0,0 +1,143 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_directory.h"
+#include "fx_file.h"
+#include "fx_utility.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_directory_name_test                             PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function first attempts to find the specified directory name.  */
+/*    If found, the attributes are checked to see if the entry is a       */
+/*    directory.  If not, the appropriate error code is returned to the   */
+/*    caller.                                                             */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    directory_name                        Directory name pointer        */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_search                  Search for the file name in   */
+/*                                          the directory structure       */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_directory_name_test(FX_MEDIA *media_ptr, CHAR *directory_name)
+{
+
+UINT         status;
+FX_DIR_ENTRY dir_entry;
+
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of times this service has been called.  */
+    media_ptr -> fx_media_directory_name_tests++;
+#endif
+
+    /* Setup pointer to media name buffer.  */
+    dir_entry.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
+
+    /* Clear the short name string.  */
+    dir_entry.fx_dir_entry_short_name[0] =  0;
+
+    /* Check the media to make sure it is open.  */
+    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
+    {
+
+        /* Return the media not opened error.  */
+        return(FX_MEDIA_NOT_OPEN);
+    }
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_DIRECTORY_NAME_TEST, media_ptr, directory_name, 0, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+    /* Search the system for the supplied directory name.  */
+    status =  _fx_directory_search(media_ptr, directory_name, &dir_entry, FX_NULL, FX_NULL);
+
+    /* Determine if the search was successful.  */
+    if (status != FX_SUCCESS)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the error code.  */
+        return(status);
+    }
+
+    /* Check to see if the entry is a directory.  */
+    if (!(dir_entry.fx_dir_entry_attributes & (UCHAR)FX_DIRECTORY))
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the not a directory error code.  */
+        return(FX_NOT_DIRECTORY);
+    }
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* Directory name test is complete, return successful status.  */
+    return(FX_SUCCESS);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_next_entry_find.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_next_entry_find.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_next_entry_find.c	(revision 30)
@@ -0,0 +1,471 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_directory.h"
+#include "fx_utility.h"
+#ifdef FX_ENABLE_EXFAT
+#include "fx_directory_exFAT.h"
+#endif /* FX_ENABLE_EXFAT */
+
+#ifndef FX_NO_LOCAL_PATH
+FX_LOCAL_PATH_SETUP
+#endif
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_directory_next_entry_find                       PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function returns the name of the next entry in the current     */
+/*    working directory.  The function that returns the first name in the */
+/*    current directory must be called prior to this function.            */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    directory_name                        Destination for directory     */
+/*                                            name                        */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_entry_read              Read entries from root dir    */
+/*    _fx_utility_FAT_entry_read            Read FAT entries to calculate */
+/*                                            the sub-directory size      */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code and                                                */
+/*    FileX System Functions                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_directory_next_entry_find(FX_MEDIA *media_ptr, CHAR *directory_name)
+{
+
+ULONG         i;
+UINT          status;
+UINT          temp_status;
+ULONG         cluster, next_cluster = 0;
+ULONG64       directory_size;
+FX_DIR_ENTRY  entry;
+FX_DIR_ENTRY *search_dir_ptr;
+FX_PATH      *path_ptr;
+#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
+UINT          index;
+CHAR         *path_string_ptr =  FX_NULL;
+#endif
+
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of times this service has been called.  */
+    media_ptr -> fx_media_directory_next_entry_finds++;
+#endif
+
+    /* Setup pointer to media name buffer.  */
+    entry.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
+
+    /* Clear the short name string.  */
+    entry.fx_dir_entry_short_name[0] =  0;
+
+    /* Check the media to make sure it is open.  */
+    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
+    {
+
+        /* Return the media not opened error.  */
+        return(FX_MEDIA_NOT_OPEN);
+    }
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_DIRECTORY_NEXT_ENTRY_FIND, media_ptr, directory_name, 0, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+    /* First check for a local path pointer stored in the thread control block.  This
+       is only available in ThreadX Version 4 and above.  */
+
+#ifndef FX_NO_LOCAL_PATH
+
+    if (_tx_thread_current_ptr -> tx_thread_filex_ptr)
+    {
+
+        /* Setup the default path pointer.  */
+        path_ptr =  (FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr;
+
+        /* Determine if we are at the root directory.  */
+        if (path_ptr -> fx_path_directory.fx_dir_entry_name[0])
+        {
+
+            /* No, we are not at the root directory.  */
+
+#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
+
+            /* Setup pointer to the path.  */
+            path_string_ptr =  ((FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr) -> fx_path_string;
+#endif
+
+            /* Set the internal pointer to the search directory as well.  */
+            search_dir_ptr =  &(path_ptr -> fx_path_directory);
+        }
+        else
+        {
+
+            /* The current default directory is the root so just set the
+               search directory pointer to NULL.  */
+            search_dir_ptr =  FX_NULL;
+        }
+    }
+    else
+#endif
+
+    /* Set the initial search directory to the current working
+       directory - if there is one.  */
+    if (media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_name[0])
+    {
+
+        /* Setup the path pointer to the global media path.  */
+        path_ptr =  &media_ptr -> fx_media_default_path;
+
+#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
+
+        /* Setup pointer to the path.  */
+        path_string_ptr =  media_ptr -> fx_media_default_path.fx_path_string;
+#endif
+
+        /* Set the internal pointer to the search directory as well.  */
+        search_dir_ptr =  &(path_ptr -> fx_path_directory);
+    }
+    else
+    {
+
+        /* Setup the path pointer to the global media path.  */
+        path_ptr =  &media_ptr -> fx_media_default_path;
+
+        /* The current default directory is the root so just set the
+           search directory pointer to NULL.  */
+        search_dir_ptr =  FX_NULL;
+    }
+
+    /* Calculate the directory size.  */
+    if (search_dir_ptr)
+    {
+#ifdef FX_ENABLE_EXFAT
+        if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+        {
+            directory_size = search_dir_ptr -> fx_dir_entry_file_size / FX_DIR_ENTRY_SIZE;
+        }
+        else
+        {
+#endif /* FX_ENABLE_EXFAT */
+            /* Determine the directory size.  */
+            if (path_ptr -> fx_path_current_entry != 0)
+            {
+
+                /* Pickup the previously saved directory size.  */
+                directory_size =  search_dir_ptr -> fx_dir_entry_file_size;
+            }
+            else
+            {
+
+                /* This should only be done on the first time into next directory find.  */
+
+                /* Ensure that the search directory's last search cluster is cleared.  */
+                search_dir_ptr -> fx_dir_entry_last_search_cluster =  0;
+
+                /* Calculate the directory size by counting the allocated
+                   clusters for it. */
+                i =        0;
+                cluster =  search_dir_ptr -> fx_dir_entry_cluster;
+                while (cluster < media_ptr -> fx_media_fat_reserved)
+                {
+
+                    /* Increment the cluster count.  */
+                    i++;
+
+                    /* Read the next FAT entry.  */
+                    status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
+
+                    /* Check the return status.  */
+                    if (status != FX_SUCCESS)
+                    {
+
+                        /* Release media protection.  */
+                        FX_UNPROTECT
+
+                        /* Return the bad status.  */
+                        return(status);
+                    }
+
+                    if ((cluster < FX_FAT_ENTRY_START) || (cluster == next_cluster) || (i > media_ptr -> fx_media_total_clusters))
+                    {
+
+                        /* Release media protection.  */
+                        FX_UNPROTECT
+
+                        /* Return the bad status.  */
+                        return(FX_FAT_READ_ERROR);
+                    }
+
+                    cluster = next_cluster;
+                }
+
+                /* Now we can calculate the directory size.  */
+                directory_size =  (((ULONG64)media_ptr -> fx_media_bytes_per_sector) *
+                                   ((ULONG64)media_ptr -> fx_media_sectors_per_cluster) * i) /
+                    (ULONG64)FX_DIR_ENTRY_SIZE;
+
+                /* Save how many entries there are in the directory.  */
+                search_dir_ptr -> fx_dir_entry_file_size =  directory_size;
+            }
+#ifdef FX_ENABLE_EXFAT
+        }
+#endif /* FX_ENABLE_EXFAT */
+    }
+    else
+    {
+
+        /* Directory size is the number of entries in the root directory.  */
+        directory_size =  (ULONG)media_ptr -> fx_media_root_directory_entries;
+    }
+
+    /* Preset status with an error return.  */
+    status =  FX_NO_MORE_ENTRIES;
+
+    /* Determine if the current entry is inside of the directory's range.  */
+    while (path_ptr -> fx_path_current_entry < directory_size)
+    {
+
+        /* Read an entry from the directory.  */
+        temp_status =  _fx_directory_entry_read(media_ptr, search_dir_ptr,
+                                                &(path_ptr -> fx_path_current_entry), &entry);
+
+        /* Check for error status.  */
+        if (temp_status != FX_SUCCESS)
+        {
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* Return error status.  */
+            return(temp_status);
+        }
+#ifdef FX_ENABLE_EXFAT
+        if (entry.fx_dir_entry_type == FX_EXFAT_DIR_ENTRY_TYPE_END_MARKER)
+        {
+            /* Set the error code.  */
+            status =  FX_NO_MORE_ENTRIES;
+
+            /* Get out of the loop.  */
+            break;
+        }
+#endif /* FX_ENABLE_EXFAT */
+
+        /* Check to see if the entry has something in it.  */
+#ifdef FX_ENABLE_EXFAT
+        else if (entry.fx_dir_entry_type != FX_EXFAT_DIR_ENTRY_TYPE_FILE_DIRECTORY)
+#else
+        if (((UCHAR)entry.fx_dir_entry_name[0] == (UCHAR)FX_DIR_ENTRY_FREE) && (entry.fx_dir_entry_short_name[0] == 0))
+#endif /* FX_ENABLE_EXFAT */
+        {
+
+            /* Current entry is free, skip to next entry and continue the loop.  */
+            path_ptr -> fx_path_current_entry++;
+            continue;
+        }
+#ifdef FX_ENABLE_EXFAT
+        else /* FX_EXFAT_DIR_ENTRY_TYPE_FILE_DIRECTORY */
+#else
+        else if ((UCHAR)entry.fx_dir_entry_name[0] != (UCHAR)FX_DIR_ENTRY_DONE)
+#endif /* FX_ENABLE_EXFAT */
+        {
+
+            /* A valid directory entry is present.  */
+
+            /* Copy the name into the destination.  */
+            for (i = 0; entry.fx_dir_entry_name[i]; i++)
+            {
+
+                *directory_name = entry.fx_dir_entry_name[i];
+                directory_name++;
+            }
+
+            /* Place a NULL at the end of the directory name.  */
+            *directory_name =  (CHAR)0;
+
+            /* Increment the current entry for the media.  */
+            path_ptr -> fx_path_current_entry++;
+
+#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
+            {
+            UINT v, j;
+
+
+                /* If a subsequent search for the same name is done, it will find it immediately.  */
+
+                /* Set the index of the saved name string.  */
+                v =  0;
+
+                /* First, build the full path and name.  */
+                if (path_string_ptr)
+                {
+
+                    /* Copy the path into the destination.  */
+                    while ((v < (FX_MAX_LAST_NAME_LEN - 1)) && (path_string_ptr[v]))
+                    {
+
+                        /* Copy one character.   */
+                        media_ptr -> fx_media_last_found_name[v] =  path_string_ptr[v];
+
+                        /* Move to next character.  */
+                        v++;
+                    }
+                }
+
+                /* We know there is room at this point, place a directory separator character.  */
+                media_ptr -> fx_media_last_found_name[v++] =  '/';
+
+                /* Now append the name to the path.  */
+                j =  0;
+                while ((v < FX_MAX_LAST_NAME_LEN) && (entry.fx_dir_entry_name[j]))
+                {
+
+                    /* Copy one character.   */
+                    media_ptr -> fx_media_last_found_name[v] =  entry.fx_dir_entry_name[j];
+
+                    /* Move to next character.  */
+                    v++;
+                    j++;
+                }
+
+                /* Null terminate the last name string.   */
+                if (v < FX_MAX_LAST_NAME_LEN)
+                {
+
+                    /* Null terminate.  */
+                    media_ptr -> fx_media_last_found_name[v] =  FX_NULL;
+                }
+                else
+                {
+
+                    /* The string is too big, NULL the string so it won't be used in searching.  */
+                    media_ptr -> fx_media_last_found_name[0] =  FX_NULL;
+                }
+
+                /* Determine if there is a search pointer.  */
+                if (search_dir_ptr)
+                {
+
+                    /* Yes, there is a search directory pointer so save it!   */
+                    media_ptr -> fx_media_last_found_directory =  *search_dir_ptr;
+
+                    /* Indicate the search directory is valid.  */
+                    media_ptr -> fx_media_last_found_directory_valid =  FX_TRUE;
+                }
+                else
+                {
+
+                    /* Indicate the search directory is not valid.  */
+                    media_ptr -> fx_media_last_found_directory_valid =  FX_FALSE;
+                }
+
+                /* Copy the directory entry.  */
+                media_ptr -> fx_media_last_found_entry =  entry;
+
+                /* Setup the last found directory entry to point at the last found internal file name.  */
+                media_ptr -> fx_media_last_found_entry.fx_dir_entry_name =  media_ptr -> fx_media_last_found_file_name;
+
+                /* Copy the actual directory name into the cached directory name.  */
+                for (index = 0; index < FX_MAX_LONG_NAME_LEN; index++)
+                {
+
+                    /* Copy character into the cached directory name.  */
+                    media_ptr -> fx_media_last_found_file_name[index] =  entry.fx_dir_entry_name[index];
+
+                    /* See if we have copied the NULL termination character.  */
+                    if (entry.fx_dir_entry_name[index] == (CHAR)FX_NULL)
+                    {
+                    
+                        /* Check to see if we use the break to get out of the loop.  */
+                        if (v < (FX_MAX_LONG_NAME_LEN - 1))
+                        {
+                        
+                            /* Yes, not at the end of the string, break.  */
+                            break;
+                        }
+                    }
+                }
+            }
+#endif
+
+            /* Set return status to success.  */
+            status =  FX_SUCCESS;
+
+            /* Get out of the loop.  */
+            break;
+        }
+#ifndef FX_ENABLE_EXFAT
+        else
+        {
+
+            /* Set the error code.  */
+            status =  FX_NO_MORE_ENTRIES;
+
+            /* Get out of the loop.  */
+            break;
+        }
+#endif /* FX_ENABLE_EXFAT */
+    }
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_next_full_entry_find.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_next_full_entry_find.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_next_full_entry_find.c	(revision 30)
@@ -0,0 +1,573 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_directory.h"
+#include "fx_utility.h"
+#ifdef FX_ENABLE_EXFAT
+#include "fx_directory_exFAT.h"
+#endif /* FX_ENABLE_EXFAT */
+
+#ifndef FX_NO_LOCAL_PATH
+FX_LOCAL_PATH_SETUP
+#endif
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_directory_next_full_entry_find                  PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function returns the name of the next entry in the current     */
+/*    working directory and various information about the name.  The      */
+/*    function that returns the first name in the current directory must  */
+/*    be called prior to this function.                                   */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    directory_name                        Destination for directory     */
+/*                                            name                        */
+/*    attributes                            Destination for attributes    */
+/*    size                                  Destination for size          */
+/*    year                                  Destination for year          */
+/*    month                                 Destination for month         */
+/*    day                                   Destination for day           */
+/*    hour                                  Destination for hour          */
+/*    minute                                Destination for minute        */
+/*    second                                Destination for second        */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_entry_read              Read entries from root dir    */
+/*    _fx_utility_FAT_entry_read            Read FAT entries              */
+/*    _fx_directory_exFAT_entry_read        Read exFAT entries            */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code and                                                */
+/*    FileX System Functions                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_directory_next_full_entry_find(FX_MEDIA *media_ptr,
+                                         CHAR *directory_name, UINT *attributes, ULONG *size,
+                                         UINT *year, UINT *month, UINT *day, UINT *hour, UINT *minute, UINT *second)
+{
+
+ULONG         i;
+UINT          status;
+UINT          temp_status;
+ULONG         cluster, next_cluster = 0;
+ULONG64       directory_size;
+FX_DIR_ENTRY  entry;
+FX_DIR_ENTRY *search_dir_ptr;
+FX_PATH      *path_ptr;
+#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
+UINT          index;
+CHAR         *path_string_ptr =  FX_NULL;
+#endif
+#ifdef FX_ENABLE_EXFAT
+/* TODO: maybe will be better to use dynamic memory, just because unicode_name is not needed in case of not exFAT.  */
+UCHAR         unicode_name[FX_MAX_LONG_NAME_LEN * 2];
+UINT          unicode_len = 0;
+#endif /* FX_ENABLE_EXFAT */
+
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of times this service has been called.  */
+    media_ptr -> fx_media_directory_next_full_entry_finds++;
+#endif
+
+    /* Setup pointer to media name buffer.  */
+    entry.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
+
+    /* Clear the short name string.  */
+    entry.fx_dir_entry_short_name[0] =  0;
+
+#ifdef FX_ENABLE_EXFAT
+    /* Will be set by exFAT.  */
+    entry.fx_dir_entry_secondary_count = 0;
+#endif /* FX_ENABLE_EXFAT */
+
+    /* Check the media to make sure it is open.  */
+    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
+    {
+
+        /* Return the media not opened error.  */
+        return(FX_MEDIA_NOT_OPEN);
+    }
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_DIRECTORY_NEXT_FULL_ENTRY_FIND, media_ptr, directory_name, 0, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+    /* First check for a local path pointer stored in the thread control block.  This
+       is only available in ThreadX Version 4 and above.  */
+#ifndef FX_NO_LOCAL_PATH
+    if (_tx_thread_current_ptr -> tx_thread_filex_ptr)
+    {
+
+        /* Setup the default path pointer.  */
+        path_ptr =  (FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr;
+
+        /* Determine if we are at the root directory.  */
+        if (path_ptr -> fx_path_directory.fx_dir_entry_name[0])
+        {
+
+            /* No, we are not at the root directory.  */
+
+#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
+
+            /* Setup pointer to the path.  */
+            path_string_ptr =  ((FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr) -> fx_path_string;
+#endif
+
+            /* Set the internal pointer to the search directory as well.  */
+            search_dir_ptr =  &path_ptr -> fx_path_directory;
+        }
+        else
+        {
+
+            /* The current default directory is the root so just set the
+               search directory pointer to NULL.  */
+            search_dir_ptr =  FX_NULL;
+        }
+    }
+    else
+#endif
+
+    /* Set the initial search directory to the current working
+       directory - if there is one.  */
+    if (media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_name[0])
+    {
+
+        /* Setup the path pointer to the global media path.  */
+        path_ptr =  &media_ptr -> fx_media_default_path;
+
+#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
+
+        /* Setup pointer to the path.  */
+        path_string_ptr =  media_ptr -> fx_media_default_path.fx_path_string;
+#endif
+
+        /* Set the internal pointer to the search directory as well.  */
+        search_dir_ptr =  &path_ptr -> fx_path_directory;
+    }
+    else
+    {
+
+        /* Setup the path pointer to the global media path.  */
+        path_ptr =  &media_ptr -> fx_media_default_path;
+
+        /* The current default directory is the root so just set the
+           search directory pointer to NULL.  */
+        search_dir_ptr =  FX_NULL;
+    }
+
+    /* Calculate the directory size.  */
+    if (search_dir_ptr)
+    {
+
+#ifdef FX_ENABLE_EXFAT
+
+        if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+        {
+            directory_size = search_dir_ptr -> fx_dir_entry_file_size / FX_DIR_ENTRY_SIZE;
+        }
+        else
+        {
+#endif /* FX_ENABLE_EXFAT */
+
+            /* Determine the directory size.  */
+            if (path_ptr -> fx_path_current_entry !=  0)
+            {
+
+                /* Pickup the previously saved directory size.  */
+                directory_size =  search_dir_ptr -> fx_dir_entry_file_size;
+            }
+            else
+            {
+
+                /* This should only be done on the first time into next directory find.  */
+
+                /* Ensure that the search directory's last search cluster is cleared.  */
+                search_dir_ptr -> fx_dir_entry_last_search_cluster =  0;
+
+                /* Calculate the directory size by counting the allocated
+                clusters for it.  */
+                i =        0;
+                cluster =  search_dir_ptr -> fx_dir_entry_cluster;
+                while (cluster < media_ptr -> fx_media_fat_reserved)
+                {
+
+                    /* Increment the cluster count.  */
+                    i++;
+
+                    /* Read the next FAT entry.  */
+                    status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
+
+
+                    /* Check the return status.  */
+                    if (status != FX_SUCCESS)
+                    {
+
+                        /* Release media protection.  */
+                        FX_UNPROTECT
+
+                        /* Return the bad status.  */
+                        return(status);
+                    }
+
+                    if ((cluster < FX_FAT_ENTRY_START) || (cluster == next_cluster) || (i > media_ptr -> fx_media_total_clusters))
+                    {
+
+                        /* Release media protection.  */
+                        FX_UNPROTECT
+
+                        /* Return the bad status.  */
+                        return(FX_FAT_READ_ERROR);
+                    }
+
+                    cluster = next_cluster;
+                }
+
+                /* Now we can calculate the directory size.  */
+                directory_size =  (((ULONG64) media_ptr -> fx_media_bytes_per_sector) *
+                                   ((ULONG64) media_ptr -> fx_media_sectors_per_cluster) * i)
+                                    / (ULONG64) FX_DIR_ENTRY_SIZE;
+
+                /* Save how many entries there are in the directory.  */
+                search_dir_ptr -> fx_dir_entry_file_size =  directory_size;
+            }
+#ifdef FX_ENABLE_EXFAT
+        }
+#endif /* FX_ENABLE_EXFAT */
+    }
+    else
+    {
+
+        /* Directory size is the number of entries in the root directory.  */
+        directory_size =  (ULONG)media_ptr -> fx_media_root_directory_entries;
+    }
+
+    /* Preset status with an error return.  */
+    status =  FX_NO_MORE_ENTRIES;
+
+    /* Determine if the current entry is inside of the directory's range.  */
+    while (path_ptr -> fx_path_current_entry < directory_size)
+    {
+
+        /* Read an entry from the directory.  */
+#ifdef FX_ENABLE_EXFAT
+        if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+        {
+            temp_status = _fx_directory_exFAT_entry_read(media_ptr, search_dir_ptr,
+                                                         &(path_ptr -> fx_path_current_entry), &entry,
+                                                         0, FX_FALSE, unicode_name, &unicode_len);
+        }
+        else
+        {
+#endif /* FX_ENABLE_EXFAT */
+            temp_status = _fx_directory_entry_read(media_ptr, search_dir_ptr,
+                                                   &(path_ptr -> fx_path_current_entry), &entry);
+#ifdef FX_ENABLE_EXFAT
+        }
+#endif /* FX_ENABLE_EXFAT */
+
+        /* Check for error status.  */
+        if (temp_status != FX_SUCCESS)
+        {
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* Return error status.  */
+            return(temp_status);
+        }
+
+#ifdef FX_ENABLE_EXFAT
+        if (entry.fx_dir_entry_type == FX_EXFAT_DIR_ENTRY_TYPE_END_MARKER)
+        {
+            /* Set the error code.  */
+            status =  FX_NO_MORE_ENTRIES;
+
+            /* Get out of the loop.  */
+            break;
+        }
+#endif /* FX_ENABLE_EXFAT */
+
+        /* Check to see if the entry has something in it.  */
+#ifdef FX_ENABLE_EXFAT
+        else if (entry.fx_dir_entry_type != FX_EXFAT_DIR_ENTRY_TYPE_FILE_DIRECTORY)
+#else
+        if (((UCHAR)entry.fx_dir_entry_name[0] == (UCHAR)FX_DIR_ENTRY_FREE) && (entry.fx_dir_entry_short_name[0] == 0))
+#endif /* FX_ENABLE_EXFAT */
+        {
+
+            /* Current entry is free, skip to next entry and continue the loop.  */
+            path_ptr -> fx_path_current_entry++;
+            continue;
+        }
+
+        /* Determine if a valid directory entry is present.  */
+#ifdef FX_ENABLE_EXFAT
+        else /* FX_EXFAT_DIR_ENTRY_TYPE_FILE_DIRECTORY */
+#else
+        else if ((UCHAR)entry.fx_dir_entry_name[0] != (UCHAR)FX_DIR_ENTRY_DONE)
+#endif /* FX_ENABLE_EXFAT */
+        {
+
+            /* A valid directory entry is present.  */
+
+            /* Copy the name into the destination.  */
+            for (i = 0; entry.fx_dir_entry_name[i]; i++)
+            {
+
+                *directory_name =  entry.fx_dir_entry_name[i];
+                directory_name++;
+            }
+
+            /* Place a NULL at the end of the directory name.  */
+            *directory_name =  (CHAR)0;
+
+            /* Determine if the entry's attributes are required.  */
+            if (attributes)
+            {
+
+                /* Pickup the entry's attributes.  */
+                *attributes =  entry.fx_dir_entry_attributes;
+            }
+
+            /* Determine if the entry's size is required.  */
+            if (size)
+            {
+
+                /* Pickup the entry's size.  */
+                *size =  (ULONG)entry.fx_dir_entry_file_size;
+            }
+
+            /* Determine if the entry's year is required.  */
+            if (year)
+            {
+
+                /* Pickup the entry's year.  */
+                *year =  ((entry.fx_dir_entry_date >> FX_YEAR_SHIFT) & FX_YEAR_MASK) + FX_BASE_YEAR;
+            }
+
+            /* Determine if the entry's month is required.  */
+            if (month)
+            {
+
+                /* Pickup the entry's month.  */
+                *month =  (entry.fx_dir_entry_date >> FX_MONTH_SHIFT) & FX_MONTH_MASK;
+            }
+
+            /* Determine if the entry's day is required.  */
+            if (day)
+            {
+
+                /* Pickup the entry's day.  */
+                *day =  entry.fx_dir_entry_date & FX_DAY_MASK;
+            }
+
+            /* Determine if the entry's hour is required.  */
+            if (hour)
+            {
+
+                /* Pickup the entry's hour.  */
+                *hour =  (entry.fx_dir_entry_time >> FX_HOUR_SHIFT) & FX_HOUR_MASK;
+            }
+
+            /* Determine if the entry's minute is required.  */
+            if (minute)
+            {
+
+                /* Pickup the entry's minute.  */
+                *minute =  (entry.fx_dir_entry_time >> FX_MINUTE_SHIFT) & FX_MINUTE_MASK;
+            }
+
+            /* Determine if the entry's second is required.  */
+            if (second)
+            {
+
+                /* Pickup the entry's second.  */
+                *second =  (entry.fx_dir_entry_time & FX_SECOND_MASK) * 2;
+            }
+
+            /* Increment the current entry for the media.  */
+            path_ptr -> fx_path_current_entry++;
+
+#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
+            {
+            UINT v, j;
+
+
+                /* If a subsequent search for the same name is done, it will find it immediately.  */
+
+                /* Set the index of the saved name string.  */
+                v =  0;
+
+                /* First, build the full path and name.  */
+                if (path_string_ptr)
+                {
+
+                    /* Copy the path into the destination.  */
+                    while ((v < (FX_MAX_LAST_NAME_LEN - 1)) && (path_string_ptr[v]))
+                    {
+
+                        /* Copy one character.   */
+                        media_ptr -> fx_media_last_found_name[v] =  path_string_ptr[v];
+
+                        /* Move to next character.  */
+                        v++;
+                    }
+                }
+
+                /* We know there is room at this point, place a directory separator character.  */
+                media_ptr -> fx_media_last_found_name[v++] =  '/';
+
+                /* Now append the name to the path.  */
+                j =  0;
+                while ((v < FX_MAX_LAST_NAME_LEN) && (entry.fx_dir_entry_name[j]))
+                {
+
+                    /* Copy one character.   */
+                    media_ptr -> fx_media_last_found_name[v] =  entry.fx_dir_entry_name[j];
+
+                    /* Move to next character.  */
+                    v++;
+                    j++;
+                }
+
+                /* Null terminate the last name string.   */
+                if (v < FX_MAX_LAST_NAME_LEN)
+                {
+
+                    /* Null terminate.  */
+                    media_ptr -> fx_media_last_found_name[v] =  FX_NULL;
+                }
+                else
+                {
+
+                    /* The string is too big, NULL the string so it won't be used in searching.  */
+                    media_ptr -> fx_media_last_found_name[0] =  FX_NULL;
+                }
+
+                /* Determine if there is a search pointer.  */
+                if (search_dir_ptr)
+                {
+
+                    /* Yes, there is a search directory pointer so save it!   */
+                    media_ptr -> fx_media_last_found_directory =  *search_dir_ptr;
+
+                    /* Indicate the search directory is valid.  */
+                    media_ptr -> fx_media_last_found_directory_valid =  FX_TRUE;
+                }
+                else
+                {
+
+                    /* Indicate the search directory is not valid.  */
+                    media_ptr -> fx_media_last_found_directory_valid =  FX_FALSE;
+                }
+
+                /* Copy the directory entry.  */
+                media_ptr -> fx_media_last_found_entry =  entry;
+
+                /* Setup the last found directory entry to point at the last found internal file name.  */
+                media_ptr -> fx_media_last_found_entry.fx_dir_entry_name =  media_ptr -> fx_media_last_found_file_name;
+
+                /* Copy the actual directory name into the cached directory name.  */
+                for (index = 0; index < FX_MAX_LONG_NAME_LEN; index++)
+                {
+
+                    /* Copy character into the cached directory name.  */
+                    media_ptr -> fx_media_last_found_file_name[index] =  entry.fx_dir_entry_name[index];
+
+                    /* See if we have copied the NULL termination character.  */
+                    if (entry.fx_dir_entry_name[index] == (CHAR)FX_NULL)
+                    {
+                    
+                        /* Check to see if we use the break to get out of the loop.  */
+                        if (v < (FX_MAX_LONG_NAME_LEN - 1))
+                        {
+                        
+                            /* Yes, not at the end of the string, break.  */
+                            break;
+                        }
+                    }
+                }
+            }
+#endif
+
+            /* Set return status to success.  */
+            status =  FX_SUCCESS;
+
+            /* Get out of the loop.  */
+            break;
+        }
+#ifndef FX_ENABLE_EXFAT
+        else
+        {
+            /* Set the error code.  */
+            status =  FX_NO_MORE_ENTRIES;
+
+            /* Get out of the loop.  */
+            break;
+        }
+#endif /* FX_ENABLE_EXFAT */
+    }
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_rename.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_rename.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_rename.c	(revision 30)
@@ -0,0 +1,523 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_directory.h"
+#include "fx_file.h"
+#include "fx_utility.h"
+#ifdef FX_ENABLE_EXFAT
+#include "fx_directory_exFAT.h"
+#endif /* FX_ENABLE_EXFAT */
+#ifdef FX_ENABLE_FAULT_TOLERANT
+#include "fx_fault_tolerant.h"
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_directory_rename                                PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function first attempts to find the specified directory.       */
+/*    If found, the rename request is valid and the directory will be     */
+/*    changed to the new name.  Otherwise, if the directory is not found, */
+/*    the appropriate error code is returned to the caller.               */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    old_directory_name                    Old file directory pointer    */
+/*    new_directory_name                    New file directory pointer    */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_entry_write             Write the new directory entry */
+/*    _fx_directory_free_search             Search for a free directory   */
+/*                                            entry                       */
+/*    _fx_directory_name_extract            Extract directory name        */
+/*    _fx_directory_search                  Search for the file name in   */
+/*                                          the directory structure       */
+/*    _fx_fault_tolerant_transaction_start  Start fault tolerant          */
+/*                                            transaction                 */
+/*    _fx_fault_tolerant_transaction_end    End fault tolerant transaction*/
+/*    _fx_fault_tolerant_recover            Recover FAT chain             */
+/*    _fx_fault_tolerant_reset_log_file     Reset the log file            */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_directory_rename(FX_MEDIA *media_ptr, CHAR *old_directory_name, CHAR *new_directory_name)
+{
+
+UINT         status;
+FX_DIR_ENTRY old_dir_entry;
+FX_DIR_ENTRY new_dir_entry;
+FX_DIR_ENTRY search_directory;
+CHAR        *new_name_ptr;
+ULONG        i;
+CHAR        *work_ptr;
+CHAR         alpha, beta;
+#ifdef FX_RENAME_PATH_INHERIT
+UINT         j;
+#endif
+
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of times this service has been called.  */
+    media_ptr -> fx_media_directory_renames++;
+#endif
+
+    /* Setup pointers to media name buffers.  */
+    old_dir_entry.fx_dir_entry_name =     media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
+    new_dir_entry.fx_dir_entry_name =     media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN * 2;
+    search_directory.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN * 3;
+
+    /* Clear the short name strings.  */
+    old_dir_entry.fx_dir_entry_short_name[0] =     0;
+    new_dir_entry.fx_dir_entry_short_name[0] =     0;
+    search_directory.fx_dir_entry_short_name[0] =  0;
+
+    /* Determine if the supplied name is less than the maximum supported name size. The
+       maximum name (FX_MAX_LONG_NAME_LEN) is defined in fx_api.h.  */
+    i =  0;
+    work_ptr =  (CHAR *)new_directory_name;
+    while (*work_ptr && (i < FX_MAX_LONG_NAME_LEN))
+    {
+
+        /* Determine if the character designates a new path.  */
+        if ((*work_ptr == '\\') || (*work_ptr == '/'))
+        {
+            /* Yes, reset the name size.  */
+            i =  0;
+        }
+        /* Check for leading spaces.  */
+        else if ((*work_ptr != ' ') || (i != 0))
+        {
+
+            /* No leading spaces, increment the name size.  */
+            i++;
+        }
+
+        /* Move to the next character.  */
+        work_ptr++;
+    }
+
+    /* Determine if the supplied name is valid.  */
+    if ((i == 0) || (i >= FX_MAX_LONG_NAME_LEN))
+    {
+
+        /* Return an invalid name value.  */
+        return(FX_INVALID_NAME);
+    }
+
+    /* Check the media to make sure it is open.  */
+    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
+    {
+
+        /* Return the media not opened error.  */
+        return(FX_MEDIA_NOT_OPEN);
+    }
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_DIRECTORY_RENAME, media_ptr, old_directory_name, new_directory_name, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    /* Start transaction. */
+    _fx_fault_tolerant_transaction_start(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Check for write protect at the media level (set by driver).  */
+    if (media_ptr -> fx_media_driver_write_protect)
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return write protect error.  */
+        return(FX_WRITE_PROTECT);
+    }
+
+    /* Search the system for the supplied directory name.  */
+    status =  _fx_directory_search(media_ptr, old_directory_name, &old_dir_entry, &search_directory, FX_NULL);
+
+    /* Determine if the search was successful.  */
+    if (status != FX_SUCCESS)
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the error code.  */
+        return(status);
+    }
+
+    /* Check to make sure the found entry is a directory.  */
+    if (!(old_dir_entry.fx_dir_entry_attributes & (UCHAR)(FX_DIRECTORY)))
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the not a directory error code.  */
+        return(FX_NOT_DIRECTORY);
+    }
+
+#ifdef FX_RENAME_PATH_INHERIT
+
+    /* Determine if the source directory name has a path and the target directory name does not.  */
+    if (((old_directory_name[0] == '/') || (old_directory_name[0] == '\\')) && (new_directory_name[0] != '/') && (new_directory_name[0] != '\\'))
+    {
+
+        /* In this case, we need to prepend the path of the old directory name to that of the new directory name.  */
+
+        /* Setup pointer to the rename buffer.  */
+        work_ptr =  (CHAR *)media_ptr -> fx_media_rename_buffer;
+
+        /* First, copy the path of the old directory name.  */
+        i =  0;
+        j =  0;
+        while ((old_directory_name[i]) && (i < FX_MAXIMUM_PATH))
+        {
+
+            /* Copy a character into the rename buffer.  */
+            *work_ptr++ =  old_directory_name[i];
+
+            /* Determine if this character is directory separator.  */
+            if ((old_directory_name[i] == '/') || (old_directory_name[i] == '\\'))
+            {
+
+                /* Yes, directory separator has been found - remember the index.  */
+                j =  i;
+            }
+
+            /* Move to next position in the old directory name.  */
+            i++;
+        }
+
+        /* At this point, we have the path stored in the rename buffer.  */
+
+        /* Position past the last slash or backslash.  */
+        j++;
+
+        /* Reset the working pointer to the position after the last directory separator.  */
+        work_ptr =  (CHAR *)&(media_ptr -> fx_media_rename_buffer[j]);
+
+        /* Now copy the new directory name into the rename buffer.  */
+        i =  0;
+        while ((new_directory_name[i]) && (j < FX_MAXIMUM_PATH))
+        {
+
+            /* Copy a character into the rename buffer.  */
+            *work_ptr++ =  new_directory_name[i];
+
+            /* Move to next character.  */
+            i++;
+            j++;
+        }
+
+        /* Determine if the path was successfully prepended.  */
+        if (new_directory_name[i])
+        {
+
+            /* No, there was not enough room in the destination buffer.  */
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+            FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* Return the invalid path error code.  */
+            return(FX_INVALID_PATH);
+        }
+
+        /* Place a NULL at the end of the string.  */
+        *work_ptr =  (CHAR)FX_NULL;
+
+        /* At this point, we have successfully prepended the path in the new directory name, override
+           the new directory name so it is used from now on.  */
+        new_directory_name =  (CHAR *)media_ptr -> fx_media_rename_buffer;
+    }
+#endif
+
+    /* Search the media for the new directory name - including any supplied path.  */
+    status = _fx_directory_search(media_ptr, new_directory_name, &new_dir_entry, &search_directory, &new_name_ptr);
+
+    /* Determine if the search found anything.  */
+    if (status == FX_SUCCESS)
+    {
+
+        /* Determine if the new name simply has an ASCII case change. If so, simply let the processing
+           continue.  */
+        i =  0;
+        do
+        {
+
+            /* Pickup an old name and new name character and convert to upper case if necessary.  */
+            alpha =  old_directory_name[i];
+            if ((alpha >= 'a') && (alpha <= 'z'))
+            {
+
+                /* Lower case, convert to upper case!  */
+                alpha =  (CHAR)((INT)alpha - 0x20);
+            }
+            beta =   new_directory_name[i];
+            if ((beta >= 'a') && (beta <= 'z'))
+            {
+
+                /* Lower case, convert to upper case!  */
+                beta =  (CHAR)((INT)beta - 0x20);
+            }
+
+            /* Now compare the characters.  */
+            if ((alpha != beta) || (alpha == 0))
+            {
+
+                /* Get out of this loop!  */
+                break;
+            }
+
+            /* Move to next character.  */
+            i++;
+        } while (i < (FX_MAXIMUM_PATH-1));
+
+        /* Now determine if the names match.  */
+        if (alpha != beta)
+        {
+
+            /* Yes, the directory name already exists in the target location.  */
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+            FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* Return the error code.  */
+            return(FX_ALREADY_CREATED);
+        }
+    }
+
+    /* Make sure the name is valid.  */
+    if (_fx_directory_name_extract(new_name_ptr, &new_dir_entry.fx_dir_entry_name[0]))
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection */
+        FX_UNPROTECT
+
+        /* Return the error code */
+        return(FX_INVALID_NAME);
+    }
+
+    /* Look for a free slot in the target directory.  */
+    status =  _fx_directory_free_search(media_ptr, &search_directory, &new_dir_entry);
+
+    /* Was a free slot found?  */
+    if (status != FX_SUCCESS)
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* No, release protection.  */
+        FX_UNPROTECT
+
+        /* Return the error code.  */
+        return(status);
+    }
+
+    /* Extract the new directory name.  */
+    _fx_directory_name_extract(new_name_ptr, &new_dir_entry.fx_dir_entry_name[0]);
+
+    /* Determine if the name was a long directory name.   */
+    if (new_dir_entry.fx_dir_entry_long_name_present)
+    {
+
+        /* Yes, clear the short directory name to force a new one.  */
+        new_dir_entry.fx_dir_entry_short_name[0] =  0;
+    }
+
+    /* Setup new attributes for the new directory entry.  */
+    new_dir_entry.fx_dir_entry_attributes = old_dir_entry.fx_dir_entry_attributes;
+    new_dir_entry.fx_dir_entry_cluster    = old_dir_entry.fx_dir_entry_cluster;
+    new_dir_entry.fx_dir_entry_file_size  = old_dir_entry.fx_dir_entry_file_size;
+
+    /* Save the reserved field.  */
+    new_dir_entry.fx_dir_entry_reserved =            old_dir_entry.fx_dir_entry_reserved;
+
+    /* Set time and date stamps.  */
+    new_dir_entry.fx_dir_entry_created_time_ms =     old_dir_entry.fx_dir_entry_created_time_ms;
+    new_dir_entry.fx_dir_entry_created_time =        old_dir_entry.fx_dir_entry_created_time;
+    new_dir_entry.fx_dir_entry_created_date =        old_dir_entry.fx_dir_entry_created_date;
+    new_dir_entry.fx_dir_entry_last_accessed_date =  old_dir_entry.fx_dir_entry_last_accessed_date;
+    new_dir_entry.fx_dir_entry_time =                old_dir_entry.fx_dir_entry_time;
+    new_dir_entry.fx_dir_entry_date =                old_dir_entry.fx_dir_entry_date;
+
+#ifdef FX_ENABLE_EXFAT
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+
+        new_dir_entry.fx_dir_entry_dont_use_fat =           old_dir_entry.fx_dir_entry_dont_use_fat;
+        new_dir_entry.fx_dir_entry_type =                   old_dir_entry.fx_dir_entry_type;
+        new_dir_entry.fx_dir_entry_available_file_size =    old_dir_entry.fx_dir_entry_available_file_size;
+        new_dir_entry.fx_dir_entry_secondary_count =        old_dir_entry.fx_dir_entry_secondary_count;
+    }
+#endif /* FX_ENABLE_EXFAT */
+
+    /* Is there a leading dot?  */
+    if (new_dir_entry.fx_dir_entry_name[0] == '.')
+    {
+
+        /* Yes, toggle the hidden attribute bit.  */
+        new_dir_entry.fx_dir_entry_attributes |=  FX_HIDDEN;
+    }
+
+#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
+
+    /* Invalidate the directory cache.  */
+    media_ptr -> fx_media_last_found_name[0] =  FX_NULL;
+#endif
+
+    /* Now write out the directory entry.  */
+#ifdef FX_ENABLE_EXFAT
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+
+        status = _fx_directory_exFAT_entry_write(media_ptr, &new_dir_entry, UPDATE_FULL);
+    }
+    else
+    {
+#endif /* FX_ENABLE_EXFAT */
+        status =  _fx_directory_entry_write(media_ptr, &new_dir_entry);
+#ifdef FX_ENABLE_EXFAT
+    }
+#endif /* FX_ENABLE_EXFAT */
+
+    /* Determine if the write was successful.  */
+    if (status != FX_SUCCESS)
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the error code.  */
+        return(status);
+    }
+
+    /* Set the old directory entry to free.  */
+    old_dir_entry.fx_dir_entry_name[0] =        (CHAR)FX_DIR_ENTRY_FREE;
+    old_dir_entry.fx_dir_entry_short_name[0] =  (CHAR)FX_DIR_ENTRY_FREE;
+
+    /* Now wipe out the old directory entry.  */
+#ifdef FX_ENABLE_EXFAT
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+
+        status = _fx_directory_exFAT_entry_write(media_ptr, &old_dir_entry, UPDATE_DELETE);
+    }
+    else
+    {
+#endif /* FX_ENABLE_EXFAT */
+        status =  _fx_directory_entry_write(media_ptr, &old_dir_entry);
+#ifdef FX_ENABLE_EXFAT
+    }
+#endif /* FX_ENABLE_EXFAT */
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    /* Check for a bad status.  */
+    if (status != FX_SUCCESS)
+    {
+
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the bad status.  */
+        return(status);
+    }
+
+    /* End transaction. */
+    status = _fx_fault_tolerant_transaction_end(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* Directory rename is complete, return status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_search.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_search.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_search.c	(revision 30)
@@ -0,0 +1,984 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_directory.h"
+#include "fx_utility.h"
+#ifdef FX_ENABLE_EXFAT
+#include "fx_directory_exFAT.h"
+#endif /* FX_ENABLE_EXFAT */
+
+#ifndef FX_NO_LOCAL_PATH
+FX_LOCAL_PATH_SETUP
+#endif
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_directory_search                                PORTABLE C      */
+/*                                                           6.1.10       */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function searches the media for the supplied name.  The search */
+/*    routine will find files as well as directory names.                 */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    name_ptr                              Name pointer                  */
+/*    entry_ptr                             Pointer to directory entry    */
+/*                                            record                      */
+/*    last_dir_ptr                          Pointer to destination for    */
+/*                                            the last directory entry    */
+/*    last_name_ptr                         Pointer to the last name      */
+/*                                            token that was searched for */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_name_extract            Extract directory name from   */
+/*                                            input string                */
+/*    _fx_directory_entry_read              Read entries from root dir    */
+/*    _fx_utility_exFAT_name_hash_get       Get name hash                 */
+/*    _fx_utility_FAT_entry_read            Read FAT entries to calculate */
+/*                                            the sub-directory size      */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    FileX System Functions                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s), and      */
+/*                                            added conditional to        */
+/*                                            disable media search cache, */
+/*                                            resulting in version 6.1    */
+/*  06-02-2021     Bhupendra Naphade        Modified comment(s), and      */
+/*                                            added check for             */
+/*                                            volume label,               */
+/*                                            resulting in version 6.1.7  */
+/*  01-31-2022     William E. Lamie         Modified comment(s), and      */
+/*                                            fixed path compare,         */
+/*                                            resulting in version 6.1.10 */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_directory_search(FX_MEDIA *media_ptr, CHAR *name_ptr, FX_DIR_ENTRY *entry_ptr,
+                           FX_DIR_ENTRY *last_dir_ptr, CHAR **last_name_ptr)
+{
+
+ULONG         i, n;
+UINT          found;
+UINT          status;
+#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
+UINT          v, j;
+#endif /* FX_MEDIA_DISABLE_SEARCH_CACHE */
+ULONG         cluster, next_cluster = 0;
+ULONG64       directory_size;
+CHAR         *dir_name_ptr;
+CHAR         *work_ptr;
+CHAR         *source_name_ptr;
+CHAR         *destination_name_ptr;
+FX_DIR_ENTRY  search_dir;
+FX_DIR_ENTRY *search_dir_ptr;
+CHAR         *name, alpha, name_alpha;
+#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
+UINT          index;
+CHAR         *path_ptr =  FX_NULL;
+CHAR         *original_name =  name_ptr;
+#endif
+#ifdef FX_ENABLE_EXFAT
+USHORT        hash = 0;
+#endif /* FX_ENABLE_EXFAT */
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of directory search requests.  */
+    media_ptr -> fx_media_directory_searches++;
+#endif
+
+    /* Setup pointer to media name buffer.  */
+    name =  media_ptr -> fx_media_name_buffer;
+
+    /* Setup the last directory, if required.  */
+    if (last_dir_ptr)
+    {
+
+        /* Set the first character of the directory entry to NULL to
+           indicate root or no directory.  */
+        last_dir_ptr -> fx_dir_entry_name[0] =  0;
+    }
+
+    /* Determine if the file name has a full directory path.  */
+    if ((*name_ptr == '\\') || (*name_ptr == '/'))
+    {
+
+        /* Directory name has full path, set the search pointer to NULL.  */
+        search_dir_ptr =  FX_NULL;
+    }
+    else
+    {
+
+        /* Set the initial search directory to the current working
+           directory - if there is one.  */
+
+        /* First check for a local path pointer stored in the thread control block.  This
+           is only available in ThreadX Version 4 and above.  */
+#ifndef FX_NO_LOCAL_PATH
+        if (_tx_thread_current_ptr -> tx_thread_filex_ptr)
+        {
+
+            /* Determine if the local directory is not the root directory.  */
+            if (((FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr) -> fx_path_directory.fx_dir_entry_name[0])
+            {
+
+                /* Start at the current working directory of the media.  */
+                search_dir =   ((FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr) -> fx_path_directory;
+
+#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
+
+                /* Setup pointer to the path.  */
+                path_ptr =  ((FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr) -> fx_path_string;
+#endif
+
+                /* Set the internal pointer to the search directory as well.  */
+                search_dir_ptr =  &search_dir;
+            }
+            else
+            {
+
+                /* We are searching in the root directory.  */
+                search_dir_ptr =  FX_NULL;
+            }
+        }
+        else
+#endif
+        if (media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_name[0])
+        {
+
+            /* Start at the current working directory of the media.  */
+            search_dir =  media_ptr -> fx_media_default_path.fx_path_directory;
+
+#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
+
+            /* Setup pointer to the path.  */
+            path_ptr =  media_ptr -> fx_media_default_path.fx_path_string;
+#endif
+
+            /* Set the internal pointer to the search directory as well.  */
+            search_dir_ptr =  &search_dir;
+        }
+        else
+        {
+
+            /* The current default directory is the root so just set the
+               search directory pointer to NULL.  */
+            search_dir_ptr =  FX_NULL;
+        }
+    }
+
+#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
+
+    /* Determine if there is a previously found directory entry.  */
+    if (media_ptr -> fx_media_last_found_name[0])
+    {
+
+    UINT  match;
+    CHAR *temp_ptr, beta;
+
+        /* Yes, there is a previously found directory in our cache.  */
+
+        /* Initialize the index.  */
+        v =  0;
+
+        /* Determine if there is a full path.  */
+        if ((*name_ptr == '\\') || (*name_ptr == '/'))
+        {
+
+            /* Yes, the full path is in the name buffer. Simply compare with what is in
+               the last search buffer.  */
+            while ((v < (FX_MAX_LAST_NAME_LEN - 1)) && (name_ptr[v]))
+            {
+
+                /* Pickup the respective name characters.  */
+                alpha =  name_ptr[v];
+                beta =   media_ptr -> fx_media_last_found_name[v];
+
+                /* Ensure directory markers are the same.  */
+                if (alpha == '\\')
+                {
+                    alpha =  '/';
+                }
+                if (beta == '\\')
+                {
+                    beta =  '/';
+                }
+
+                /* Is the name the same?  */
+                if (alpha != beta)
+                {
+
+                    /* Break out of loop!  */
+                    break;
+                }
+
+                /* Move to next character.  */
+                v++;
+            }
+
+            /* Determine if we have a match.  */
+            if (name_ptr[v] != media_ptr -> fx_media_last_found_name[v])
+            {
+                match =  FX_FALSE;
+            }
+            else
+            {
+                match =  FX_TRUE;
+            }
+        }
+        else
+        {
+
+            /* Default to found.  */
+            match =  FX_TRUE;
+
+            /* Determine if there is a default path to compare with.  */
+            if (path_ptr)
+            {
+
+                /* Yes, compare the current path with what is contained in the last
+                   found buffer. Note that the last found name must have at least one
+                   path separator as well as room for at least one character for a name. */
+                while ((v < (FX_MAX_LAST_NAME_LEN - 1)) && (path_ptr[v]))
+                {
+
+                    /* Pickup the respective name characters.  */
+                    alpha =  media_ptr -> fx_media_last_found_name[v];
+                    beta =   path_ptr[v];
+
+                    /* Ensure directory markers are the same.  */
+                    if (alpha == '\\')
+                    {
+                        alpha =  '/';
+                    }
+                    if (beta == '\\')
+                    {
+                        beta =  '/';
+                    }
+
+                    /* Is the name the same?  */
+                    if (alpha != beta)
+                    {
+
+                        /* Break out of loop!  */
+                        break;
+                    }
+
+                    /* Move to next character.  */
+                    v++;
+                }
+
+                /* Determine if we don't have a match...  The relative path must be exhausted. */
+                if (path_ptr[v])
+                {
+                    match =  FX_FALSE;
+                }
+            }
+
+            /* Determine if we still have a match.  */
+            if (match)
+            {
+
+                /* Now examine the rest of the last name and the newly supplied
+                   input name.  */
+
+                /* Determine if a valid directory separator is present.  */
+                if ((media_ptr -> fx_media_last_found_name[v] != '\\') &&
+                    (media_ptr -> fx_media_last_found_name[v] != '/'))
+                {
+
+                    /* Set match to false - invalid directory path separator.  */
+                    match =  FX_FALSE;
+                }
+                else
+                {
+                    /* Position past the next directory separator in the
+                       last name string.  */
+                    v++;
+                }
+
+                /* Yes, the full path is in the name buffer. Simply compare with what is in
+                   the last search buffer.  */
+                j =  0;
+                while ((v < (FX_MAX_LAST_NAME_LEN - 1)) && (name_ptr[j]) && (match))
+                {
+
+                    /* Pickup the respective name characters.  */
+                    alpha =  name_ptr[j];
+                    beta =   media_ptr -> fx_media_last_found_name[v];
+
+                    /* Ensure directory markers are the same.  */
+                    if (alpha == '\\')
+                    {
+                        alpha =  '/';
+                    }
+                    if (beta == '\\')
+                    {
+                        beta =  '/';
+                    }
+
+                    /* Is the name the same?  */
+                    if (alpha != beta)
+                    {
+
+                        /* Break out of loop!  */
+                        break;
+                    }
+
+                    /* Move to next character.  */
+                    v++;
+                    j++;
+                }
+
+                /* Avoid accessing fx_media_last_found_name out of bounds. */
+                if (v >= 256)
+                {
+                    match = FX_FALSE;
+                }
+                else if ((match) && (name_ptr[j] != media_ptr -> fx_media_last_found_name[v]))
+                {
+
+                    /* We don't have a match.  */
+                    match =  FX_FALSE;
+                }
+            }
+        }
+
+        /* Now determine if we actually found a match.  */
+        if (match)
+        {
+
+            /* Save the directory entry name pointer.  */
+            temp_ptr =  entry_ptr -> fx_dir_entry_name;
+
+            /* Copy the saved directory entry.  */
+            *entry_ptr =  media_ptr -> fx_media_last_found_entry;
+
+            /* Restore the directory entry name pointer.  */
+            entry_ptr -> fx_dir_entry_name =  temp_ptr;
+
+            /* Copy the directory name into the destination directory name.  */
+            for (index = 0; index < FX_MAX_LONG_NAME_LEN; index++)
+            {
+
+                /* Copy character into the destination.  */
+                temp_ptr[index] =  media_ptr -> fx_media_last_found_file_name[index];
+
+                /* See if we have copied the NULL termination character.  */
+                if (temp_ptr[index] == (CHAR)FX_NULL)
+                {
+                
+                    /* Determine if we should break here or at the top of the loop.  */
+                    if (index < (FX_MAX_LONG_NAME_LEN - 1))
+                    {
+                    
+                        /* Yes, break out of the loop early.  */
+                        break;
+                    }
+                }
+            }
+
+            /* Determine if there is a search directory to copy.  */
+            if ((last_dir_ptr) && (media_ptr -> fx_media_last_found_directory_valid))
+            {
+
+                /* Yes, there was a search directory... and one is requested in this request as well.
+                   Simply copy it into the destination.  */
+
+                /* First, save the name pointer from the list directory pointer.  */
+                destination_name_ptr =  last_dir_ptr -> fx_dir_entry_name;
+
+                /* Copy the entire directory entry structure.  */
+                *last_dir_ptr =  media_ptr -> fx_media_last_found_directory;
+
+                /* Restore the original name buffer pointer.  */
+                last_dir_ptr -> fx_dir_entry_name =  destination_name_ptr;
+
+                /* Pickup pointer to name to copy.  */
+                source_name_ptr =  media_ptr -> fx_media_last_found_directory.fx_dir_entry_name;
+
+                /* Loop to copy the name into the last directory name buffer.  */
+                for (n = 0; n < FX_MAX_LONG_NAME_LEN; n++)
+                {
+                
+                    /* Copy a character.  */
+                    destination_name_ptr[n] =  source_name_ptr[n];
+                
+                    /* See if we have copied the NULL termination character.  */
+                    if (source_name_ptr[n] == (CHAR)FX_NULL)
+                    {
+                
+                        /* Determine if we should break here or at the top of the loop.  */
+                        if (n < (FX_MAX_LONG_NAME_LEN - 1))
+                        {
+                    
+                            /* Yes, break out of the loop early.  */
+                            break;
+                        }
+                    }
+                }
+            }
+
+            /* Return the last name pointer, if required.  */
+            if (last_name_ptr)
+            {
+
+                /* Just set the last name to initial name string.  */
+                *last_name_ptr =  temp_ptr;
+            }
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+            /* Increment the number of directory search cache hits.  */
+            media_ptr -> fx_media_directory_search_cache_hits++;
+#endif
+
+            /* Return success.  */
+            return(FX_SUCCESS);
+        }
+    }
+
+    /* Not a sequential search, invalidate the saved information.  */
+    media_ptr -> fx_media_last_found_name[0] =  FX_NULL;
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_DIR_CACHE_MISS, media_ptr, media_ptr -> fx_media_directory_searches - media_ptr -> fx_media_directory_search_cache_hits, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+#else
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_DIR_CACHE_MISS, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+#endif
+#endif
+
+    /* Loop to traverse the directory paths to find the specified file.  */
+    do
+    {
+
+        /* Remember the last name pointer, if required.  */
+        if (last_name_ptr)
+        {
+
+            /* Just set the last name to initial name string.  */
+            *last_name_ptr =  name_ptr;
+        }
+
+        /* Extract file name.  */
+        name_ptr =  _fx_directory_name_extract(name_ptr, name);
+
+        /* Calculate the directory size.  */
+        if (search_dir_ptr)
+        {
+#ifdef FX_ENABLE_EXFAT
+            if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+            {
+                directory_size = search_dir_ptr -> fx_dir_entry_file_size / FX_DIR_ENTRY_SIZE;
+            }
+            else
+            {
+#endif /* FX_ENABLE_EXFAT */
+
+                /* Ensure that the search directory's last search cluster is cleared.  */
+                search_dir_ptr -> fx_dir_entry_last_search_cluster =  0;
+
+                /* Calculate the directory size by counting the allocated
+                clusters for it.  */
+                i =        0;
+                cluster =  search_dir_ptr -> fx_dir_entry_cluster;
+                while (cluster < media_ptr -> fx_media_fat_reserved)
+                {
+
+                    /* Increment the cluster count.  */
+                    i++;
+
+                    /* Read the next FAT entry.  */
+                    status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
+
+                    /* Check the return status.  */
+                    if (status != FX_SUCCESS)
+                    {
+
+                        /* Return the bad status.  */
+                        return(status);
+                    }
+
+                    /* Check for error situation.  */
+                    if ((cluster < FX_FAT_ENTRY_START) || (cluster == next_cluster) || (i > media_ptr -> fx_media_total_clusters))
+                    {
+
+                        /* Return the bad status.  */
+                        return(FX_FAT_READ_ERROR);
+                    }
+
+                    cluster = next_cluster;
+                }
+
+                /* Now we can calculate the directory size.  */
+                directory_size =  (((ULONG64) media_ptr -> fx_media_bytes_per_sector) *
+                                   ((ULONG64) media_ptr -> fx_media_sectors_per_cluster) * i)
+                                    / (ULONG64) FX_DIR_ENTRY_SIZE;
+
+                /* Also save this in the directory entry so we don't have to
+                   calculate it later.  */
+                search_dir_ptr -> fx_dir_entry_file_size =  directory_size;
+#ifdef FX_ENABLE_EXFAT
+            }
+#endif /* FX_ENABLE_EXFAT */
+
+            /* If required, copy the last search directory entry into the
+               destination.  */
+            if (last_dir_ptr)
+            {
+
+                /* Copy the last search directory into the destination.  */
+
+                /* First, save the name pointer from the list directory pointer.  */
+                destination_name_ptr =  last_dir_ptr -> fx_dir_entry_name;
+
+                /* Copy the entire directory entry structure.  */
+                *last_dir_ptr =  *search_dir_ptr;
+
+                /* Restore the original name buffer pointer.  */
+                last_dir_ptr -> fx_dir_entry_name =  destination_name_ptr;
+
+                /* Pickup pointer to name to copy.  */
+                source_name_ptr =  search_dir_ptr -> fx_dir_entry_name;
+
+                /* Loop to copy the name into the last directory name buffer.  */
+                for (n = 0; n < FX_MAX_LONG_NAME_LEN; n++)
+                {
+
+                    /* Copy a character.  */
+                    destination_name_ptr[n] =  source_name_ptr[n];
+
+                    /* See if we have copied the NULL termination character.  */
+                    if (source_name_ptr[n] == (CHAR) FX_NULL)
+                    {
+                
+                        /* Determine if we should break here or at the top of the loop.  */
+                        if (n < (FX_MAX_LONG_NAME_LEN - 1))
+                        {
+                    
+                            /* Yes, break out of the loop early.  */
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+        else
+        {
+
+            /* Directory size is the number of entries in the root directory.  */
+            directory_size =  (ULONG)media_ptr -> fx_media_root_directory_entries;
+        }
+
+        /* Loop through entries in the directory.  Yes, this is a
+           linear search!  */
+        i =      0;
+        found =  FX_FALSE;
+
+#ifdef FX_ENABLE_EXFAT
+        if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+        {
+
+            /* Get name hash.  */
+            hash =  _fx_utility_exFAT_name_hash_get(name);
+        }
+#endif /* FX_ENABLE_EXFAT */
+
+        do
+        {
+
+            /* Read an entry from the directory.  */
+#ifdef FX_ENABLE_EXFAT
+            status =  _fx_directory_entry_read_ex(media_ptr, search_dir_ptr, &i, entry_ptr, hash);
+#else
+            status =  _fx_directory_entry_read(media_ptr, search_dir_ptr, &i, entry_ptr);
+#endif /* FX_ENABLE_EXFAT */
+
+            i++;
+
+            /* Check for error status.  */
+            if (status != FX_SUCCESS)
+            {
+                return(status);
+            }
+
+            /* Determine if this is the last directory entry.  */
+#ifdef FX_ENABLE_EXFAT
+            if (entry_ptr -> fx_dir_entry_type == FX_EXFAT_DIR_ENTRY_TYPE_END_MARKER)
+#else
+            if ((UCHAR)entry_ptr -> fx_dir_entry_name[0] == (UCHAR)FX_DIR_ENTRY_DONE)
+#endif /* FX_ENABLE_EXFAT */
+            {
+                break;
+            }
+
+            /* Determine if the entry is a volume label entry */
+            if ((entry_ptr -> fx_dir_entry_attributes & FX_VOLUME))
+            {
+                continue;
+            }
+
+            /* Determine if this is an empty entry.  */
+#ifdef FX_ENABLE_EXFAT
+            if (entry_ptr -> fx_dir_entry_type != FX_EXFAT_DIR_ENTRY_TYPE_FILE_DIRECTORY)
+#else
+            if (((UCHAR)entry_ptr -> fx_dir_entry_name[0] == (UCHAR)FX_DIR_ENTRY_FREE) && (entry_ptr -> fx_dir_entry_short_name[0] == 0))
+#endif /* FX_ENABLE_EXFAT */
+            {
+                continue;
+            }
+
+            /* Compare the input name and extension with the directory
+               entry.  */
+            work_ptr =      &name[0];
+            dir_name_ptr =  &(entry_ptr -> fx_dir_entry_name[0]);
+
+            /* Loop to compare names.  */
+            do
+            {
+
+                /* Pickup character of directory name.  */
+                alpha =  *dir_name_ptr;
+
+                /* Pickup character of name.  */
+                name_alpha =  *work_ptr;
+
+                /* Determine if its case needs to be changed.  */
+                if ((alpha >= 'a') && (alpha <= 'z'))
+                {
+
+                    /* Yes, make upper case.  */
+                    alpha =  (CHAR)((INT)alpha - 0x20);
+                }
+
+                /* Determine if its case needs to be changed.  */
+                if ((name_alpha >= 'a') && (name_alpha <= 'z'))
+                {
+
+                    /* Yes, make upper case.  */
+                    name_alpha =  (CHAR)((INT)name_alpha - 0x20);
+                }
+
+                /* Compare name with directory name.  */
+                if (alpha != name_alpha)
+                {
+
+                    /* The names don't match, get out of the loop. */
+                    break;
+                }
+
+                /* Otherwise, increment the name pointers.  */
+                work_ptr++;
+                dir_name_ptr++;
+            } while (*dir_name_ptr);
+
+            /* Determine if the requested name has been found.  If so,
+               return success to the caller.  */
+            if ((*dir_name_ptr == 0) && (*work_ptr == *dir_name_ptr))
+            {
+
+                /* Yes, the name was located.  All pertinent directory
+                   information is in the directory entry field.  */
+                found =  FX_TRUE;
+            }
+            /* Determine if there is a short name to check.  */
+#ifdef FX_ENABLE_EXFAT
+            else if ((media_ptr -> fx_media_FAT_type != FX_exFAT) &&
+                     (entry_ptr -> fx_dir_entry_short_name[0] != 0))
+#else
+            else if (entry_ptr -> fx_dir_entry_short_name[0] != 0)
+#endif /* FX_ENABLE_EXFAT */
+            {
+
+                /* Yes, check for the short part of the name.  */
+
+                /* Compare the input name and extension with the directory entry.  */
+                work_ptr =      &name[0];
+                dir_name_ptr =  &(entry_ptr -> fx_dir_entry_short_name[0]);
+
+                /* Loop to compare names.  */
+                do
+                {
+
+                    /* Pickup character of directory name.  */
+                    alpha =  *dir_name_ptr;
+
+                    /* Pickup character of name.  */
+                    name_alpha =  *work_ptr;
+
+                    /* Determine if its case needs to be changed.  */
+                    if ((name_alpha >= 'a') && (name_alpha <= 'z'))
+                    {
+
+                        /* Yes, make upper case.  */
+                        name_alpha =  (CHAR)((INT)name_alpha - 0x20);
+                    }
+
+                    /* Compare name with directory name.  */
+                    if (alpha != name_alpha)
+                    {
+
+                        /* The names don't match, get out of the loop. */
+                        break;
+                    }
+
+                    /* Otherwise, move the name pointers and increment the
+                       count.  */
+                    work_ptr++;
+                    dir_name_ptr++;
+                } while (*dir_name_ptr);
+
+                /* Determine if the names match.  */
+                if ((*dir_name_ptr == 0) && (*work_ptr == *dir_name_ptr))
+                {
+
+                    /* Yes, the name was located.  All pertinent directory
+                        information is in the directory entry field.  */
+                    found =  FX_TRUE;
+                }
+            }
+        } while ((i < directory_size) && (!found));
+
+        /* Now determine if we have a match.  */
+        if (!found)
+        {
+
+            /* Return a "not found" status to the caller.  */
+            return(FX_NOT_FOUND);
+        }
+
+        /* Determine if the found entry is indeed a sub-directory.  */
+        if (entry_ptr -> fx_dir_entry_attributes & FX_DIRECTORY)
+        {
+
+            /* Move the directory search pointer to this entry.  */
+            search_dir =      *entry_ptr;
+            search_dir_ptr =  &search_dir;
+
+            /* Ensure that the search directory's last search cluster is cleared.  */
+            search_dir_ptr -> fx_dir_entry_last_search_cluster =  0;
+
+            /* Now determine if the new search directory is the root
+               directory.  */
+#ifdef FX_ENABLE_EXFAT
+            if ((!search_dir_ptr -> fx_dir_entry_cluster)
+                && (media_ptr -> fx_media_FAT_type != FX_exFAT))
+#else
+            if (!search_dir_ptr -> fx_dir_entry_cluster)
+#endif /* FX_ENABLE_EXFAT */
+            {
+
+                /* This is a backward link to the root directory.  Make
+                   sure this is indicated in the search directory
+                   information.  */
+                search_dir_ptr -> fx_dir_entry_name[0] =  0;
+
+                /* Determine if we need to remember this in the last
+                   directory searched return area.  */
+                if (last_dir_ptr)
+                {
+
+                    /* Yes, return this value to the caller.  */
+
+                    /* First, save the name pointer from the list directory pointer.  */
+                    destination_name_ptr =  last_dir_ptr -> fx_dir_entry_name;
+
+                    /* Copy the entire directory entry structure.  */
+                    *last_dir_ptr =  *search_dir_ptr;
+
+                    /* Restore the original name buffer pointer.  */
+                    last_dir_ptr -> fx_dir_entry_name =  destination_name_ptr;
+
+                    /* Pickup pointer to name to copy.  */
+                    source_name_ptr =  search_dir_ptr -> fx_dir_entry_name;
+
+                    /* Loop to copy the name into the last directory name buffer.  */
+                    for (n = 0; n < FX_MAX_LONG_NAME_LEN; n++)
+                    {
+
+                        /* Copy a character.  */
+                        destination_name_ptr[n] =  source_name_ptr[n];
+                    }
+                }
+
+                /* Set the search directory pointer to NULL to indicate
+                   we are at the root directory.  */
+                search_dir_ptr =  FX_NULL;
+            }
+        }
+        else
+        {
+
+            /* This is not a directory, we better return not found
+               since we can't continue the search.  */
+            if (name_ptr)
+            {
+
+                /* Return not-found status to caller.  */
+                return(FX_NOT_FOUND);
+            }
+        }
+    } while (name_ptr);
+
+    /* If you reach this point, the directory is found absolutely, since !found will return directly in the loop above.   */
+#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
+
+
+    /* At this point, cache the found information.  If a subsequent search for the same name is done,
+       it will return immediately.  */
+
+    /* Set the index of the saved name string.  */
+    v=  0;
+
+    /* First, build the full path and name.  */
+    if ((*original_name != '\\') && (*original_name != '/') && (path_ptr))
+    {
+
+        /* Copy the path into the destination.  */
+        while ((v< (FX_MAX_LAST_NAME_LEN - 1)) && (path_ptr[v]))
+        {
+
+            /* Copy one character.   */
+            media_ptr -> fx_media_last_found_name[v] =  path_ptr[v];
+
+            /* Move to next character.  */
+            v++;
+        }
+    }
+
+    /* Now see if there is no directory path symbol in the name itself.  */
+    if ((*original_name != '\\') && (*original_name != '/'))
+    {
+
+        /* If there is room, place a directory separator character.  */
+        if (v < (FX_MAX_LAST_NAME_LEN - 1))
+        {
+            media_ptr -> fx_media_last_found_name[v++] =  '/';
+        }
+    }
+
+    /* Now append the name to the path.  */
+    j =  0;
+    while ((v < FX_MAX_LAST_NAME_LEN) && (original_name[j]))
+    {
+
+        /* Copy one character.   */
+        media_ptr -> fx_media_last_found_name[v] =  original_name[j];
+
+        /* Move to next character.  */
+        v++;
+        j++;
+    }
+
+    /* Null terminate the last name string.   */
+    if (v< FX_MAX_LAST_NAME_LEN)
+    {
+
+        /* Null terminate.  */
+        media_ptr -> fx_media_last_found_name[v] =  FX_NULL;
+    }
+    else
+    {
+
+        /* The string is too big, NULL the string so it won't be used in searching.  */
+        media_ptr -> fx_media_last_found_name[0] =  FX_NULL;
+    }
+
+    /* Determine if there is a search pointer.  */
+    if (search_dir_ptr)
+    {
+
+        /* Yes, there is a search directory pointer so save it!   */
+        media_ptr -> fx_media_last_found_directory =  *search_dir_ptr;
+
+        /* Indicate the search directory is valid.  */
+        media_ptr -> fx_media_last_found_directory_valid =  FX_TRUE;
+    }
+    else
+    {
+
+        /* Indicate the search directory is not valid.  */
+        media_ptr -> fx_media_last_found_directory_valid =  FX_FALSE;
+    }
+
+    /* Copy the directory entry.  */
+    media_ptr -> fx_media_last_found_entry =  *entry_ptr;
+
+    /* Setup the directory entry for the last found internal file name.  */
+    media_ptr -> fx_media_last_found_entry.fx_dir_entry_name =  media_ptr -> fx_media_last_found_file_name;
+
+    /* Copy the actual directory name into the cached directory name.  */
+    for (index = 0; index < FX_MAX_LONG_NAME_LEN; index++)
+    {
+
+        /* Copy character into the cached directory name.  */
+        media_ptr -> fx_media_last_found_file_name[index] =  entry_ptr ->  fx_dir_entry_name[index];
+
+        /* See if we have copied the NULL termination character.  */
+        if (entry_ptr -> fx_dir_entry_name[index] == (CHAR)FX_NULL)
+        {
+                
+            /* Check to see if we use the break to get out of the loop.  */
+            if (index < (FX_MAX_LONG_NAME_LEN - 1))
+            {
+                    
+                /* Yes, not at the end of the string, break.  */
+                break;
+            }
+        }
+    }
+#endif
+
+    return(FX_SUCCESS);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_short_name_get.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_short_name_get.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_short_name_get.c	(revision 30)
@@ -0,0 +1,85 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_directory.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_directory_short_name_get                        PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function gets the short file name via the supplied long file   */
+/*    name. If the long file name is really a short file name, the short  */
+/*    file name will be returned.                                         */
+/*                                                                        */
+/*    Note, this API is deprecated as fx_directory_short_name_get_extended*/
+/*    should be used. The maximum written size to short_file_name could   */
+/*    be FX_MAX_SHORT_NAME_LEN.                                           */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    long_file_name                        Pointer to long (max 255) name*/
+/*    short_file_name                       Pointer to short (8.3) name   */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_short_name_get_extended Actual short name get service */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_directory_short_name_get(FX_MEDIA *media_ptr, CHAR *long_file_name, CHAR *short_file_name)
+{
+
+    /* Call the extended version with maximum short name length.  */
+    return(_fx_directory_short_name_get_extended(media_ptr, long_file_name, short_file_name, FX_MAX_SHORT_NAME_LEN));
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_short_name_get_extended.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_short_name_get_extended.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_directory_short_name_get_extended.c	(revision 30)
@@ -0,0 +1,170 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_directory.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_directory_short_name_get_extended               PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function gets the short file name via the supplied long file   */
+/*    name. If the long file name is really a short file name, the short  */
+/*    file name will be returned.                                         */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    long_file_name                        Pointer to long (max 255) name*/
+/*    short_file_name                       Pointer to short (8.3) name   */
+/*    short_file_name_length                Buffer length for short name  */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_search                  Search for the file name in   */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_directory_short_name_get_extended(FX_MEDIA *media_ptr, CHAR *long_file_name, CHAR *short_file_name, UINT short_file_name_length)
+{
+
+UINT         status;
+UINT         i;
+FX_DIR_ENTRY dir_entry;
+
+
+    /* Setup pointer to media name buffer.  */
+    dir_entry.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
+
+    /* Clear the short name string.  */
+    dir_entry.fx_dir_entry_short_name[0] =  0;
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_DIRECTORY_SHORT_NAME_GET, media_ptr, long_file_name, short_file_name, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+    /* Search the system for the supplied short directory name.  */
+    status =  _fx_directory_search(media_ptr, long_file_name, &dir_entry, FX_NULL, FX_NULL);
+
+    /* Determine if the search was successful.  */
+    if (status != FX_SUCCESS)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the error code.  */
+        return(status);
+    }
+
+    /* Determine if there is a short name.  */
+    if (dir_entry.fx_dir_entry_short_name[0])
+    {
+
+        /* Yes, there is a short name. Copy the short file name portion into the destination string.  */
+        i =  0;
+        while ((i < (FX_MAX_SHORT_NAME_LEN - 1)) && (dir_entry.fx_dir_entry_short_name[i]) && (i < (short_file_name_length - 1)))
+        {
+
+            /* Copy a character of the long file name into the destination name.  */
+            short_file_name[i] =   dir_entry.fx_dir_entry_short_name[i];
+
+            /* Move to next character.  */
+            i++;
+        }
+
+        /* Ensure the short file name is NULL terminated.  */
+        short_file_name[i] =  FX_NULL;
+        
+        /* Check if the buffer is too short for the name.  */
+        if ((i == (short_file_name_length - 1)) && (dir_entry.fx_dir_entry_short_name[i]))
+        {
+
+            /* Buffer too short, return error.  */
+            status =  FX_BUFFER_ERROR;
+        }
+    }
+    else
+    {
+
+        /* There is no long file name, simply copy the long file name into the short file name destination.  */
+        i =  0;
+        while ((i < (FX_MAX_SHORT_NAME_LEN - 1)) && (dir_entry.fx_dir_entry_name[i]) && (i < (short_file_name_length - 1)))
+        {
+
+            /* Copy a character of the file name into the destination name.  */
+            short_file_name[i] =   dir_entry.fx_dir_entry_name[i];
+
+            /* Move to next character.  */
+            i++;
+        }
+
+        /* Ensure the short file name is NULL terminated.  */
+        short_file_name[i] =  FX_NULL;
+
+        /* Check if the buffer is too short for the name.  */
+        if ((i == (short_file_name_length - 1)) && (dir_entry.fx_dir_entry_name[i]))
+        {
+
+            /* Buffer too short, return error.  */
+            status =  FX_BUFFER_ERROR;
+        }
+    }
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* Return the completion status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_add_FAT_log.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_add_FAT_log.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_add_FAT_log.c	(revision 30)
@@ -0,0 +1,113 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Fault Tolerant                                                      */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+#include "fx_api.h"
+#include "fx_utility.h"
+#include "fx_fault_tolerant.h"
+
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_fault_tolerant_add_FAT_log                      PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function converts FAT write into log entry and add it into     */
+/*    log file.                                                           */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    cluster                               Cluster entry number          */
+/*    value                                 Next cluster value            */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_16_unsigned_write         Write a USHORT from memory    */
+/*    _fx_utility_32_unsigned_write         Write a UINT from memory      */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    _fx_utility_FAT_entry_write                                         */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT _fx_fault_tolerant_add_FAT_log(FX_MEDIA *media_ptr, ULONG cluster, ULONG value)
+{
+ULONG                      file_size;
+FX_FAULT_TOLERANT_FAT_LOG *fat_log;
+
+    /* Increment the size of the log file. */
+    file_size = media_ptr -> fx_media_fault_tolerant_file_size + FX_FAULT_TOLERANT_FAT_LOG_ENTRY_SIZE;
+
+    /* Check whether log file exceeds the buffer. */
+    if (file_size > media_ptr -> fx_media_fault_tolerant_memory_buffer_size)
+    {
+
+        /*  Log file exceeds the size of the log buffer.  This is a failure. */
+        return(FX_NO_MORE_SPACE);
+    }
+
+    /* Set log pointer. */
+    fat_log = (FX_FAULT_TOLERANT_FAT_LOG *)(media_ptr -> fx_media_fault_tolerant_memory_buffer +
+                                            media_ptr -> fx_media_fault_tolerant_file_size);
+
+    /* Set log type. */
+    _fx_utility_16_unsigned_write((UCHAR *)&fat_log -> fx_fault_tolerant_FAT_log_type,
+                                  FX_FAULT_TOLERANT_FAT_LOG_TYPE);
+
+    /* Size of log. */
+    _fx_utility_16_unsigned_write((UCHAR *)&fat_log -> fx_fault_tolerant_FAT_log_size,
+                                  FX_FAULT_TOLERANT_FAT_LOG_ENTRY_SIZE);
+
+    /* Set cluster and value. */
+    _fx_utility_32_unsigned_write((UCHAR *)&fat_log -> fx_fault_tolerant_FAT_log_cluster, cluster);
+    _fx_utility_32_unsigned_write((UCHAR *)&fat_log -> fx_fault_tolerant_FAT_log_value, value);
+
+    /* Update log information. */
+    media_ptr -> fx_media_fault_tolerant_file_size = (USHORT)file_size;
+    media_ptr -> fx_media_fault_tolerant_total_logs += 1;
+
+    return(FX_SUCCESS);
+}
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_add_bitmap_log.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_add_bitmap_log.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_add_bitmap_log.c	(revision 30)
@@ -0,0 +1,114 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Fault Tolerant                                                      */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+#include "fx_api.h"
+#include "fx_utility.h"
+#include "fx_fault_tolerant.h"
+
+
+#if defined(FX_ENABLE_FAULT_TOLERANT) && defined(FX_ENABLE_EXFAT)
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_fault_tolerant_add_bitmap_log                   PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function converts bitmap write into log entries and add them   */
+/*    into log file.                                                      */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    cluster                               Cluster entry number          */
+/*    value                                 Valud of cluster state        */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_16_unsigned_write         Write a USHORT from memory    */
+/*    _fx_utility_32_unsigned_write         Write a UINT from memory      */
+/*    memcpy                                Memory Copy                   */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    _fx_directory_exFAT_unicode_entry_write                             */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT _fx_fault_tolerant_add_bitmap_log(FX_MEDIA *media_ptr, ULONG cluster, ULONG value)
+{
+ULONG                         file_size;
+FX_FAULT_TOLERANT_BITMAP_LOG *bitmap_log;
+
+    /* Increment the size of the log file. */
+    file_size = media_ptr -> fx_media_fault_tolerant_file_size + FX_FAULT_TOLERANT_BITMAP_LOG_ENTRY_SIZE;
+
+    /* Check whether log file exceeds the buffer. */
+    if (file_size > media_ptr -> fx_media_fault_tolerant_memory_buffer_size)
+    {
+
+        /*  Log file exceeds the size of the log buffer.  This is a failure. */
+        return(FX_NO_MORE_SPACE);
+    }
+
+    /* Set log pointer. */
+    bitmap_log = (FX_FAULT_TOLERANT_BITMAP_LOG *)(media_ptr -> fx_media_fault_tolerant_memory_buffer +
+                                                  media_ptr -> fx_media_fault_tolerant_file_size);
+
+    /* Set log type. */
+    _fx_utility_16_unsigned_write((UCHAR *)&bitmap_log -> fx_fault_tolerant_bitmap_log_type,
+                                  FX_FAULT_TOLERANT_BITMAP_LOG_TYPE);
+
+    /* Size of log. */
+    _fx_utility_16_unsigned_write((UCHAR *)&bitmap_log -> fx_fault_tolerant_bitmap_log_size,
+                                  FX_FAULT_TOLERANT_BITMAP_LOG_ENTRY_SIZE);
+
+    /* Set cluster and value. */
+    _fx_utility_32_unsigned_write((UCHAR *)&bitmap_log -> fx_fault_tolerant_bitmap_log_cluster, cluster);
+    _fx_utility_32_unsigned_write((UCHAR *)&bitmap_log -> fx_fault_tolerant_bitmap_log_value, value);
+
+    /* Update log information. */
+    media_ptr -> fx_media_fault_tolerant_file_size = (USHORT)file_size;
+    media_ptr -> fx_media_fault_tolerant_total_logs += 1;
+
+    return(FX_SUCCESS);
+}
+#endif /* FX_ENABLE_FAULT_TOLERANT && FX_ENABLE_EXFAT */
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_add_checksum_log.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_add_checksum_log.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_add_checksum_log.c	(revision 30)
@@ -0,0 +1,155 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Fault Tolerant                                                      */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+#include "fx_api.h"
+#include "fx_utility.h"
+#include "fx_fault_tolerant.h"
+
+
+#if defined(FX_ENABLE_FAULT_TOLERANT) && defined(FX_ENABLE_EXFAT)
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_fault_tolerant_add_checksum_log                 PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function converts checksum of exFAT directory entry write into */
+/*    log entries and add it into log file.                               */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    logical_sector                        Original sector to write to   */
+/*    offset                                Offset in original sector     */
+/*    checksum                              Value of checksum             */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_16_unsigned_read          Read a USHORT from memory     */
+/*    _fx_utility_32_unsigned_read          Read a ULONG from memory      */
+/*    _fx_utility_64_unsigned_read          Read a ULONG64 from memory    */
+/*    _fx_utility_16_unsigned_write         Write a USHORT from memory    */
+/*    memcpy                                Memory Copy                   */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    _fx_directory_exFAT_unicode_entry_write                             */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT _fx_fault_tolerant_add_checksum_log(FX_MEDIA *media_ptr, ULONG64 logical_sector, ULONG offset, USHORT checksum)
+{
+ULONG                      logs_remaining;
+UCHAR                     *current_ptr;
+ULONG                      size;
+USHORT                     type;
+ULONG                      log_len;
+ULONG64                    log_sector;
+ULONG                      log_offset;
+FX_FAULT_TOLERANT_DIR_LOG *dir_log;
+
+    /* Get fault tolerant data. */
+    logs_remaining = media_ptr -> fx_media_fault_tolerant_total_logs;
+
+    /* Get size of all logs. */
+    size = media_ptr -> fx_media_fault_tolerant_file_size - FX_FAULT_TOLERANT_LOG_CONTENT_OFFSET;
+
+    /* Get the first log pointer. */
+    current_ptr = media_ptr -> fx_media_fault_tolerant_memory_buffer +
+                  FX_FAULT_TOLERANT_LOG_CONTENT_OFFSET +
+                  FX_FAULT_TOLERANT_LOG_CONTENT_HEADER_SIZE;
+
+    /* Loop throught all DIR logs. */
+    while (logs_remaining)
+    {
+
+        /* Check log type. */
+        type = (USHORT)_fx_utility_16_unsigned_read(current_ptr);
+
+        /* Get log length. */
+        log_len = _fx_utility_16_unsigned_read(current_ptr + 2);
+
+        /* Validate the size value. */
+        if (log_len > size)
+        {
+
+            /* Log file is corrupted.  Nothing can be done.  Return.*/
+            return(FX_FILE_CORRUPT);
+        }
+        size -= log_len;
+
+        /* Check log type. */
+        if (type == FX_FAULT_TOLERANT_DIR_LOG_TYPE)
+        {
+
+            /* Set the log pointer. */
+            dir_log = (FX_FAULT_TOLERANT_DIR_LOG *)current_ptr;
+
+            /* Get the sector of log. */
+            log_sector = _fx_utility_64_unsigned_read((UCHAR *)&dir_log -> fx_fault_tolerant_dir_log_sector);
+
+            /* Get the offset of log. */
+            log_offset = _fx_utility_32_unsigned_read((UCHAR *)&dir_log -> fx_fault_tolerant_dir_log_offset);
+
+            /* Is the checksum for this directory log? */
+            if ((log_sector == logical_sector) && (offset == log_offset + 2))
+            {
+
+                /* Yes. Update the checksum field. */
+                _fx_utility_16_unsigned_write(current_ptr + FX_FAULT_TOLERANT_DIR_LOG_ENTRY_SIZE + 2, checksum);
+
+                /* Return success. */
+                return(FX_SUCCESS);
+            }
+        }
+
+        /* Decrease the logs_remaining counter. */
+        logs_remaining--;
+
+        /* Move to start position of next log entry. */
+        current_ptr += log_len;
+    }
+
+    /* The directory is not found. Log file is corrupted. */
+    return(FX_FILE_CORRUPT);
+}
+#endif /* FX_ENABLE_FAULT_TOLERANT && FX_ENABLE_EXFAT */
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_add_dir_log.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_add_dir_log.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_add_dir_log.c	(revision 30)
@@ -0,0 +1,133 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Fault Tolerant                                                      */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+#include "fx_api.h"
+#include "fx_utility.h"
+#include "fx_fault_tolerant.h"
+
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_fault_tolerant_add_dir_log                      PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function converts directory entry write into log entry and add */
+/*    it into log file.                                                   */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    logical_sector                        Original sector to write to   */
+/*    offset                                Offset in original sector     */
+/*    data                                  Data of log                   */
+/*    data_size                             Size of data                  */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_16_unsigned_write         Write a USHORT from memory    */
+/*    _fx_utility_32_unsigned_write         Write a ULONG from memory     */
+/*    _fx_utility_64_unsigned_write         Write a ULONG64 from memory   */
+/*    memcpy                                Memory Copy                   */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    _fx_directory_entry_write                                           */
+/*    _fx_directory_exFAT_unicode_entry_write                             */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s), verified */
+/*                                            memcpy usage,               */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT _fx_fault_tolerant_add_dir_log(FX_MEDIA *media_ptr, ULONG64 logical_sector, ULONG offset,
+                                    UCHAR *data, ULONG data_size)
+{
+ULONG                      file_size;
+FX_FAULT_TOLERANT_DIR_LOG *dir_log;
+
+    /* Increment the size of the log file. */
+    file_size = media_ptr -> fx_media_fault_tolerant_file_size + data_size + FX_FAULT_TOLERANT_DIR_LOG_ENTRY_SIZE;
+
+    /* Check whether log file exceeds the buffer. */
+    if (file_size > media_ptr -> fx_media_fault_tolerant_memory_buffer_size)
+    {
+
+        /*  Log file exceeds the size of the log buffer.  This is a failure. */
+        return(FX_NO_MORE_SPACE);
+    }
+
+    /* Any data to write? */
+    if (data_size == 0)
+    {
+
+        /* No. Just return. */
+        return FX_SUCCESS;
+    }
+
+    /* Set log pointer. */
+    dir_log = (FX_FAULT_TOLERANT_DIR_LOG *)(media_ptr -> fx_media_fault_tolerant_memory_buffer +
+                                            media_ptr -> fx_media_fault_tolerant_file_size);
+
+    /* Set log type. */
+    _fx_utility_16_unsigned_write((UCHAR *)&dir_log -> fx_fault_tolerant_dir_log_type,
+                                  FX_FAULT_TOLERANT_DIR_LOG_TYPE);
+
+    /* Size of log. */
+    _fx_utility_16_unsigned_write((UCHAR *)&dir_log -> fx_fault_tolerant_dir_log_size,
+                                  data_size + FX_FAULT_TOLERANT_DIR_LOG_ENTRY_SIZE);
+
+    /* Set sector and offset. */
+    _fx_utility_64_unsigned_write((UCHAR *)&dir_log -> fx_fault_tolerant_dir_log_sector, logical_sector);
+    _fx_utility_32_unsigned_write((UCHAR *)&dir_log -> fx_fault_tolerant_dir_log_offset, offset);
+
+    memcpy(media_ptr -> fx_media_fault_tolerant_memory_buffer +  /* Use case of memcpy is verified. */
+           media_ptr -> fx_media_fault_tolerant_file_size + FX_FAULT_TOLERANT_DIR_LOG_ENTRY_SIZE,
+           data, data_size);
+
+
+    /* Update log information. */
+    media_ptr -> fx_media_fault_tolerant_file_size = (USHORT)file_size;
+    media_ptr -> fx_media_fault_tolerant_total_logs += 1;
+
+    return(FX_SUCCESS);
+}
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_apply_logs.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_apply_logs.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_apply_logs.c	(revision 30)
@@ -0,0 +1,338 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Fault Tolerant                                                      */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+#include "fx_api.h"
+#include "fx_utility.h"
+#include "fx_fault_tolerant.h"
+
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_fault_tolerant_apply_logs                       PORTABLE C      */
+/*                                                           6.2.0        */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function applies changes to the file system.  The changes are  */
+/*    already recorded in the fault tolerant log file.  Therefore this    */
+/*    function reads the content of the log entries and apply these       */
+/*    changes to the file system.                                         */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_logical_sector_write      Write a logical sector        */
+/*    _fx_utility_logical_sector_read       Read a logical sector         */
+/*    _fx_utility_16_unsigned_read          Read a USHORT from memory     */
+/*    _fx_utility_32_unsigned_read          Read a ULONG from memory      */
+/*    _fx_utility_64_unsigned_read          Read a ULONG64 from memory    */
+/*    _fx_utility_FAT_entry_write           Write a FAT entry             */
+/*    _fx_utility_exFAT_cluster_state_set   Set state of exFAT cluster    */
+/*    _fx_fault_tolerant_cleanup_FAT_chain  Cleanup FAT chain             */
+/*    memcpy                                Memory Copy                   */
+/*    _fx_utility_exFAT_bitmap_flush        Flush exFAT allocation bitmap */
+/*    _fx_utility_FAT_flush                 Flush written FAT entries     */
+/*    _fx_utility_logical_sector_flush      Flush written logical sectors */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    _fx_fault_tolerant_enable                                           */
+/*    _fx_fault_tolerant_transaction_end                                  */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s), verified */
+/*                                            memcpy usage,               */
+/*                                            resulting in version 6.1    */
+/*  10-31-2022     Tiejun Zhou              Modified comment(s), fixed    */
+/*                                            overflow in log size check, */
+/*                                            resulting in version 6.2.0  */
+/*                                                                        */
+/**************************************************************************/
+UINT _fx_fault_tolerant_apply_logs(FX_MEDIA *media_ptr)
+{
+UINT                           status;
+ULONG64                        log_sector;
+ULONG                          remaining_logs;
+ULONG                          copy_size;
+ULONG                          copy_offset;
+UCHAR                         *current_ptr;
+ULONG                          size;
+USHORT                         log_type;
+ULONG                          log_len;
+FX_FAULT_TOLERANT_LOG_HEADER  *log_header;
+FX_FAULT_TOLERANT_FAT_CHAIN   *FAT_chain;
+FX_FAULT_TOLERANT_LOG_CONTENT *log_content;
+FX_FAULT_TOLERANT_FAT_LOG     *fat_log;
+FX_FAULT_TOLERANT_DIR_LOG     *dir_log;
+#ifdef FX_ENABLE_EXFAT
+FX_FAULT_TOLERANT_BITMAP_LOG  *bitmap_log;
+ULONG                          current_cluster;
+ULONG                          head_cluster;
+ULONG                          tail_cluster;
+#endif /* FX_ENABLE_EXFAT */
+
+    /* Set log header, FAT chain and log content pointer. */
+    log_header = (FX_FAULT_TOLERANT_LOG_HEADER *)media_ptr -> fx_media_fault_tolerant_memory_buffer;
+    FAT_chain = (FX_FAULT_TOLERANT_FAT_CHAIN *)(media_ptr -> fx_media_fault_tolerant_memory_buffer + FX_FAULT_TOLERANT_FAT_CHAIN_OFFSET);
+    log_content = (FX_FAULT_TOLERANT_LOG_CONTENT *)(media_ptr -> fx_media_fault_tolerant_memory_buffer +
+                                                    FX_FAULT_TOLERANT_LOG_CONTENT_OFFSET);
+
+    /* Find the size of the log file. */
+    size = _fx_utility_16_unsigned_read((UCHAR *)&log_header -> fx_fault_tolerant_log_header_total_size);
+
+    /* Extended port-specific processing macro, which is by default defined to white space.  */
+    FX_FAULT_TOLERANT_APPLY_LOGS_EXTENSION
+
+    size -= FX_FAULT_TOLERANT_LOG_CONTENT_HEADER_SIZE;
+
+    /* Find the number of log entries. */
+    remaining_logs = _fx_utility_16_unsigned_read((UCHAR *)&log_content -> fx_fault_tolerant_log_content_count);
+
+    /* Get start address of logs. */
+    current_ptr = (UCHAR *)log_content + FX_FAULT_TOLERANT_LOG_CONTENT_HEADER_SIZE;
+
+    /* Loop through all the logs to apply the changes. */
+    while (remaining_logs)
+    {
+
+        /* Obtain log type of this entry. */
+        log_type = (USHORT)_fx_utility_16_unsigned_read(current_ptr);
+
+        /* Read log length.  */
+        log_len = _fx_utility_16_unsigned_read(current_ptr + 2);
+
+
+        /* Validate log entry size. */
+        if (log_len > size)
+        {
+
+            /* Something wrong with log file. */
+            return(FX_FILE_CORRUPT);
+        }
+
+        /* Reduce the total log file size. */
+        size -= log_len;
+
+        /* Process log entry by type. */
+        switch (log_type)
+        {
+        case FX_FAULT_TOLERANT_FAT_LOG_TYPE:
+
+            /* This is a FAT log. */
+            fat_log = (FX_FAULT_TOLERANT_FAT_LOG *)current_ptr;
+
+            /* Write FAT entry. */
+            status = _fx_utility_FAT_entry_write(media_ptr,
+                                                 _fx_utility_32_unsigned_read((UCHAR *)&fat_log -> fx_fault_tolerant_FAT_log_cluster),
+                                                 _fx_utility_32_unsigned_read((UCHAR *)&fat_log -> fx_fault_tolerant_FAT_log_value));
+
+            if (status != FX_SUCCESS)
+            {
+
+                /* Return the error status.  */
+                return(status);
+            }
+            break;
+
+#ifdef FX_ENABLE_EXFAT
+        case FX_FAULT_TOLERANT_BITMAP_LOG_TYPE:
+
+            /* This is a bitmap log. */
+            bitmap_log = (FX_FAULT_TOLERANT_BITMAP_LOG *)current_ptr;
+
+            /* Set bitmap entry. */
+            status = _fx_utility_exFAT_cluster_state_set(media_ptr,
+                                                         _fx_utility_32_unsigned_read((UCHAR *)&bitmap_log -> fx_fault_tolerant_bitmap_log_cluster),
+                                                         (UCHAR)_fx_utility_32_unsigned_read((UCHAR *)&bitmap_log -> fx_fault_tolerant_bitmap_log_value));
+
+            if (status != FX_SUCCESS)
+            {
+
+                /* Return the error status.  */
+                return(status);
+            }
+            break;
+
+#endif /* FX_ENABLE_EXFAT */
+        case FX_FAULT_TOLERANT_DIR_LOG_TYPE:
+
+            /* This is a DIR log. */
+            dir_log = (FX_FAULT_TOLERANT_DIR_LOG *)current_ptr;
+
+            log_sector = _fx_utility_64_unsigned_read((UCHAR *)&dir_log -> fx_fault_tolerant_dir_log_sector);
+
+            /* Get the destination sector. */
+            status =  _fx_utility_logical_sector_read(media_ptr,
+                                                      log_sector,
+                                                      media_ptr -> fx_media_memory_buffer,
+                                                      ((ULONG) 1), FX_DATA_SECTOR);
+
+            if (status != FX_SUCCESS)
+            {
+
+                /* Return the error status.  */
+                return(status);
+            }
+
+            /* Set copy information. */
+            copy_offset = _fx_utility_32_unsigned_read((UCHAR *)&dir_log -> fx_fault_tolerant_dir_log_offset);
+
+
+            copy_size = log_len - FX_FAULT_TOLERANT_DIR_LOG_ENTRY_SIZE;
+
+            if (((ULONG64)copy_offset + (ULONG64)copy_size) > (ULONG64)(media_ptr -> fx_media_memory_size))
+            {
+                return(FX_FILE_CORRUPT);
+            }
+
+            /* Copy data into destination sector. */
+            memcpy(media_ptr -> fx_media_memory_buffer + copy_offset, /* Use case of memcpy is verified. */
+                   current_ptr + FX_FAULT_TOLERANT_DIR_LOG_ENTRY_SIZE, copy_size);
+
+
+            /* Write back the current logical sector.  */
+            status = _fx_utility_logical_sector_write(media_ptr,
+                                                      log_sector,
+                                                      media_ptr -> fx_media_memory_buffer,
+                                                      ((ULONG) 1), FX_DIRECTORY_SECTOR);
+
+            if (status != FX_SUCCESS)
+            {
+
+                /* Return the error status.  */
+                return(status);
+            }
+            break;
+
+        default:
+
+            /* Wrong type.  */
+            return(FX_SECTOR_INVALID);
+        }
+
+        /* Decrement the remaining log counter.  */
+        remaining_logs--;
+
+        /* Move to start position of next log entry. */
+        current_ptr += log_len;
+    }
+
+    /* Check whether or not to process FAT chain. */
+    if (FAT_chain -> fx_fault_tolerant_FAT_chain_flag & FX_FAULT_TOLERANT_FLAG_FAT_CHAIN_VALID)
+    {
+
+        /* Free old link of FAT. */
+#ifdef FX_ENABLE_EXFAT
+        if (FAT_chain -> fx_fault_tolerant_FAT_chain_flag & FX_FAULT_TOLERANT_FLAG_BITMAP_USED)
+        {
+
+            /* Process FAT chain. */
+            /* Get head and tail cluster from FAT chain. */
+            head_cluster = _fx_utility_32_unsigned_read((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_head_original);
+            tail_cluster = _fx_utility_32_unsigned_read((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_insertion_back);
+
+            if ((head_cluster >= FX_FAT_ENTRY_START) && (head_cluster < media_ptr -> fx_media_fat_reserved))
+            {
+                for (current_cluster = head_cluster; current_cluster < tail_cluster; current_cluster++)
+                {
+
+                    /* Free bitmap. */
+                    status = _fx_utility_exFAT_cluster_state_set(media_ptr, current_cluster, FX_EXFAT_BITMAP_CLUSTER_FREE);
+                    if (status != FX_SUCCESS)
+                    {
+
+                        /* Return the error status.  */
+                        return(status);
+                    }
+
+                    /* Increase the available clusters in the media control block. */
+                    media_ptr -> fx_media_available_clusters++;
+                }
+            }
+        }
+        else
+        {
+#endif /* FX_ENABLE_EXFAT */
+            status = _fx_fault_tolerant_cleanup_FAT_chain(media_ptr, FX_FAULT_TOLERANT_FAT_CHAIN_CLEANUP);
+            if (status != FX_SUCCESS)
+            {
+
+                /* Return the error status.  */
+                return(status);
+            }
+#ifdef FX_ENABLE_EXFAT
+        }
+#endif /* FX_ENABLE_EXFAT */
+    }
+
+    /* Flush the internal logical sector cache.  */
+    status =  _fx_utility_logical_sector_flush(media_ptr, 1, (ULONG64) media_ptr -> fx_media_total_sectors, FX_FALSE);
+
+    /* Check for a bad status.  */
+    if (status != FX_SUCCESS)
+    {
+
+        /* Return the bad status.  */
+        return(status);
+    }
+
+    /* Flush FAT table. */
+#ifdef FX_FAULT_TOLERANT
+#ifdef FX_ENABLE_EXFAT
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+
+        /* Flush exFAT bitmap.  */
+        _fx_utility_exFAT_bitmap_flush(media_ptr);
+    }
+#endif /* FX_ENABLE_EXFAT */
+
+    /* Ensure the new FAT chain is properly written to the media.  */
+
+    /* Flush the cached individual FAT entries */
+    _fx_utility_FAT_flush(media_ptr);
+#endif
+
+    /* Return success. */
+    return(FX_SUCCESS);
+}
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_calculate_checksum.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_calculate_checksum.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_calculate_checksum.c	(revision 30)
@@ -0,0 +1,103 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Fault Tolerant                                                      */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+#include "fx_api.h"
+#include "fx_fault_tolerant.h"
+#include "fx_utility.h"
+
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_fault_tolerant_calculate_checksum               PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function calculates checksum for consecutive data.  The size   */
+/*    of the log file is required to be 4-byte aligned.  Therefore this   */
+/*    checksum routine is able to perform 4-byte access.                  */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    data                                  Pointer to data               */
+/*    len                                   Data length                   */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    Computed checksum value                                             */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*     _fx_utility_32_unsigned_read         Read a UINT from memory       */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    _fx_fault_tolerant_enable                                           */
+/*    _fx_fault_tolerant_cleanup_FAT_chain                                */
+/*    _fx_fault_tolerant_reset_log_file                                   */
+/*    _fx_fault_tolerant_set_FAT_chain                                    */
+/*    _fx_fault_tolerant_transaction_end                                  */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+USHORT  _fx_fault_tolerant_calculate_checksum(UCHAR *data, UINT len)
+{
+ULONG checksum = 0;
+ULONG long_value;
+
+    while (len >= 4)
+    {
+
+        /* Read first long value. */
+        long_value = _fx_utility_32_unsigned_read(data);
+
+        /* Calculate checksum. */
+        checksum += (long_value >> 16) + (long_value & 0xFFFF);
+
+        /* Decrease length. */
+        len -= sizeof(ULONG);
+        data += sizeof(ULONG);
+    }
+
+    /* Trim high 16 bits of checksum. */
+    checksum = (checksum & 0xFFFF) + (checksum >> 16);
+    checksum = (checksum & 0xFFFF) + (checksum >> 16);
+
+    return((USHORT)((~checksum) & 0xFFFF));
+}
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_cleanup_FAT_chain.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_cleanup_FAT_chain.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_cleanup_FAT_chain.c	(revision 30)
@@ -0,0 +1,389 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Fault Tolerant                                                      */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+#include "fx_api.h"
+#include "fx_utility.h"
+#include "fx_fault_tolerant.h"
+
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_utility_FAT_entry_multiple_sectors_check        PORTABLE C      */
+/*                                                           6.2.0        */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    Tiejun Zhou, Microsoft Corporation                                  */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks whether the FAT entry spans multiple sectors.  */
+/*    It is only possible when the file system is FAT12.                  */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    cluster                               Cluster entry number          */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    FX_TRUE                               FAT entry spans two sectors   */
+/*    FX_FALSE                              FAT entry in one sector       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    _fx_fault_tolerant_cleanup_FAT_chain                                */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  10-31-2022     Tiejun Zhou              Initial Version 6.2.0         */
+/*                                                                        */
+/**************************************************************************/
+static UINT _fx_utility_FAT_entry_multiple_sectors_check(FX_MEDIA *media_ptr, ULONG cluster)
+{
+ULONG byte_offset;
+ULONG FAT_sector;
+
+    /* Check FAT format.  */
+    if (!media_ptr -> fx_media_12_bit_FAT)
+    {
+
+        /* Not FAT12. The FAT entry will be in one sector.  */
+        return(FX_FALSE);
+    }
+
+    /* File system is FAT12.  */
+    /* Calculate the byte offset to the cluster entry.  */
+    byte_offset =  (((ULONG)cluster << 1) + cluster) >> 1;
+
+    /* Calculate the FAT sector the requested FAT entry resides in.  */
+    FAT_sector =  (byte_offset / media_ptr -> fx_media_bytes_per_sector) +
+        (ULONG)media_ptr -> fx_media_reserved_sectors;
+
+    /* Now calculate the byte offset into this FAT sector.  */
+    byte_offset =  byte_offset -
+        ((FAT_sector - (ULONG)media_ptr -> fx_media_reserved_sectors) *
+            media_ptr -> fx_media_bytes_per_sector);
+
+    /* Determine if we are now past the end of the FAT buffer in memory.  */
+    if (byte_offset == (ULONG)(media_ptr -> fx_media_bytes_per_sector - 1))
+    {
+
+        /* Yes, we are past the end of the FAT buffer.  */
+        return(FX_TRUE);
+    }
+    else
+    {
+
+        /* No, we are not past the end of the FAT buffer.  */
+        return(FX_FALSE);
+    }
+}
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_fault_tolerant_cleanup_FAT_chain                PORTABLE C      */
+/*                                                           6.2.0        */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function cleans up FAT chain. In order to prevent failures     */
+/*    during the link-list walk, and to improve efficiency, this function */
+/*    frees the FAT entry chain in sections.  For each section, it frees  */
+/*    FAT entry from the last entry in the chain and works backwards.     */
+/*    Using this method, if the system fails in the middle of the free    */
+/*    operation, the head is preserved, and fault tolerant module can     */
+/*    "redo" this operation next time it starts up.                       */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    operation                             Recover a failure operation or*/
+/*                                            cleanup old FAT chain       */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_exFAT_cluster_state_get   Get state of exFAT cluster    */
+/*    _fx_utility_exFAT_cluster_state_set   Set state of exFAT cluster    */
+/*    _fx_utility_FAT_entry_read            Read a FAT entry              */
+/*    _fx_utility_FAT_entry_write           Write a FAT entry             */
+/*    _fx_utility_16_unsigned_write         Write a USHORT from memory    */
+/*    _fx_utility_32_unsigned_write         Write a ULONG from memory     */
+/*    _fx_utility_32_unsigned_read          Read a ULONG from memory      */
+/*    _fx_utility_exFAT_bitmap_flush        Flush exFAT allocation bitmap */
+/*    _fx_utility_FAT_flush                 Flush written FAT entries     */
+/*    _fx_fault_tolerant_calculate_checksum Compute Checksum of data      */
+/*    _fx_fault_tolerant_write_log_file     Write log file                */
+/*    _fx_utility_FAT_entry_multiple_sectors_check                        */
+/*                                          Check sectors for FAT entry   */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    _fx_fault_tolerant_apply_logs                                       */
+/*    _fx_fault_tolerant_recover                                          */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*  10-31-2022     Tiejun Zhou              Modified comment(s),          */
+/*                                            fixed FAT entry span two    */
+/*                                            sectors for FAT12,          */
+/*                                            resulting in version 6.2.0  */
+/*                                                                        */
+/**************************************************************************/
+UINT    _fx_fault_tolerant_cleanup_FAT_chain(FX_MEDIA *media_ptr, UINT operation)
+{
+UINT                         status;
+ULONG                        current_cluster;
+ULONG                        next_cluster = 0;
+ULONG                        head_cluster;
+ULONG                        tail_cluster;
+ULONG                        cache_count;
+ULONG                        cache_max = FX_FAULT_TOLERANT_CACHE_SIZE >> 2;
+ULONG                       *cache_ptr = media_ptr -> fx_media_fault_tolerant_cache;
+ULONG                        next_session;
+USHORT                       checksum;
+ULONG                        i;
+FX_FAULT_TOLERANT_FAT_CHAIN *FAT_chain;
+ULONG                        FAT_sector;
+ULONG                        last_FAT_sector;
+
+    /* Set FAT chain pointer. */
+    FAT_chain = (FX_FAULT_TOLERANT_FAT_CHAIN *)(media_ptr -> fx_media_fault_tolerant_memory_buffer + FX_FAULT_TOLERANT_FAT_CHAIN_OFFSET);
+
+    /* Get head and tail cluster. */
+    if (operation == FX_FAULT_TOLERANT_FAT_CHAIN_RECOVER)
+    {
+
+        /* Recover phase. Cleanup (remove) new FAT chain. */
+        head_cluster = _fx_utility_32_unsigned_read((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_head_new);
+    }
+    else
+    {
+
+        /* Cleanup phase. Cleanup (remove) old FAT chain. */
+        head_cluster = _fx_utility_32_unsigned_read((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_head_original);
+    }
+
+    /* At this point, the head_cluster points to the cluster chain that is to be removed. */
+
+    /* Tail cluster points to the back of the origianal FAT chain where the new chain is attached to.
+       The remove process terminates once this cluster is encountered. */
+    tail_cluster = _fx_utility_32_unsigned_read((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_insertion_back);
+
+    /* Are there any clusters to free? */
+    if ((head_cluster < FX_FAT_ENTRY_START) || (head_cluster >= media_ptr -> fx_media_fat_reserved))
+    {
+        return(FX_SUCCESS);
+    }
+
+    /* To optimize the deletion process of a long FAT chain, the deletion is done in sessions.  During one session,
+       a set of FAT entries are removed.  If one session is interrupted, after restart the deletion process resumes and
+       picks up from where it left.
+
+       During one deletion session, all FAT entries are between head_cluster(inclusive) and next_session (exclusive).
+     */
+    next_session = _fx_utility_32_unsigned_read((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_next_deletion);
+
+    /* Loop to cleanup all FAT entries. */
+    while ((head_cluster >= FX_FAT_ENTRY_START) && (head_cluster < media_ptr -> fx_media_fat_reserved))
+    {
+
+        /* Initialize. */
+        current_cluster = head_cluster;
+        cache_count = 0;
+
+        /* Loop from head cluster to find entries to cleanup and store this information into cache. */
+        do
+        {
+
+            /* Get the next FAT entry. */
+            status = _fx_utility_FAT_entry_read(media_ptr, current_cluster, &next_cluster);
+            if (status != FX_SUCCESS)
+            {
+
+                /* Return the error status.  */
+                return(status);
+            }
+
+            /* Whether or not the cluster is occupied. */
+            if (next_cluster == FX_FREE_CLUSTER)
+            {
+
+                /* Current cluster has already been released. */
+                break;
+            }
+
+            /* Cache the FAT list. */
+            cache_ptr[cache_count++] = current_cluster;
+
+            /* Check whether FAT entry spans multiple sectors.  */
+            if (_fx_utility_FAT_entry_multiple_sectors_check(media_ptr, current_cluster))
+            {
+                if (head_cluster == next_session || next_session == FX_FREE_CLUSTER)
+                {
+                    next_session = next_cluster;
+                }
+                break;
+            }
+
+            /* Move to next cluster. */
+            current_cluster = next_cluster;
+        } while ((next_cluster >= FX_FAT_ENTRY_START) &&
+                 (next_cluster < media_ptr -> fx_media_fat_reserved) &&
+                 (next_cluster != tail_cluster) &&
+                 (cache_count < cache_max));
+
+        /* Get next session. */
+        if (cache_count == cache_max)
+        {
+            next_session = next_cluster;
+        }
+
+        /* Update head cluster and next session into log file. */
+        _fx_utility_32_unsigned_write((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_next_deletion, next_session);
+        if (operation == FX_FAULT_TOLERANT_FAT_CHAIN_RECOVER)
+        {
+            _fx_utility_32_unsigned_write((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_head_new, head_cluster);
+        }
+        else
+        {
+            _fx_utility_32_unsigned_write((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_head_original, head_cluster);
+        }
+
+        /* Update checksum. */
+        _fx_utility_16_unsigned_write((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_checksumm, 0);
+        checksum = _fx_fault_tolerant_calculate_checksum((UCHAR *)FAT_chain, FX_FAULT_TOLERANT_FAT_CHAIN_SIZE);
+        _fx_utility_16_unsigned_write((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_checksumm, checksum);
+
+        /* Flush the fault tolerant log into the file system.  */
+        _fx_fault_tolerant_write_log_file(media_ptr, 0);
+
+        /* Loop to free FAT in cache from back to front. */
+        if (cache_count > 0)
+        {
+
+            /* Get sector of last FAT entry. */
+            last_FAT_sector = _fx_utility_FAT_sector_get(media_ptr, cache_ptr[cache_count - 1]);
+            i = cache_count;
+            while (i > 0)
+            {
+                i--;
+
+                /* Get sector of current FAT entry. */
+                FAT_sector = _fx_utility_FAT_sector_get(media_ptr, cache_ptr[i]);
+                if (FAT_sector != last_FAT_sector)
+                {
+
+                    /* Current FAT entry is located in different sector. Force flush. */
+                    /* Flush the cached individual FAT entries */
+                    _fx_utility_FAT_flush(media_ptr);
+#ifdef FX_ENABLE_EXFAT
+                    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+                    {
+
+                        /* Flush exFAT bitmap.  */
+                        _fx_utility_exFAT_bitmap_flush(media_ptr);
+                    }
+#endif /* FX_ENABLE_EXFAT */
+
+                    /* Update sector of current FAT entry. */
+                    last_FAT_sector = FAT_sector;
+                }
+
+                /* Free current_cluster. */
+                status = _fx_utility_FAT_entry_write(media_ptr, cache_ptr[i], FX_FREE_CLUSTER);
+                if (status != FX_SUCCESS)
+                {
+
+                    /* Return the error status.  */
+                    return(status);
+                }
+
+#ifdef FX_ENABLE_EXFAT
+                if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+                {
+
+                    /* Free bitmap. */
+                    status = _fx_utility_exFAT_cluster_state_set(media_ptr, cache_ptr[i], FX_EXFAT_BITMAP_CLUSTER_FREE);
+                    if (status != FX_SUCCESS)
+                    {
+
+                        /* Return the error status.  */
+                        return(status);
+                    }
+                }
+#endif /* FX_ENABLE_EXFAT */
+            }
+
+            /* Increase the available clusters in the media control block. */
+            media_ptr -> fx_media_available_clusters  += cache_count;
+        }
+
+        /* Flush the cached individual FAT entries */
+        _fx_utility_FAT_flush(media_ptr);
+#ifdef FX_ENABLE_EXFAT
+        if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+        {
+
+            /* Flush exFAT bitmap.  */
+            _fx_utility_exFAT_bitmap_flush(media_ptr);
+        }
+#endif /* FX_ENABLE_EXFAT */
+
+
+        /* Get head cluster. */
+        if (head_cluster == next_session)
+        {
+            break;
+        }
+        head_cluster = next_session;
+    }
+
+    return(FX_SUCCESS);
+}
+#endif /* FX_ENABLE_FAULT_TOLERANT */
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_create_log_file.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_create_log_file.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_create_log_file.c	(revision 30)
@@ -0,0 +1,417 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Fault Tolerant                                                      */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+#include "fx_api.h"
+#include "fx_utility.h"
+#include "fx_directory.h"
+#include "fx_fault_tolerant.h"
+
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_fault_tolerant_create_log_file                  PORTABLE C      */
+/*                                                           6.1.11       */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function finds an available cluster used by log file. Then it  */
+/*    sets the cluster number to boot sector.                             */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_exFAT_cluster_state_set   Set state of exFAT cluster    */
+/*    _fx_utility_FAT_entry_read            Read a FAT entry              */
+/*    _fx_utility_FAT_entry_write           Write a FAT entry             */
+/*    _fx_utility_exFAT_bitmap_flush        Flush exFAT allocation bitmap */
+/*    _fx_utility_FAT_flush                 Flush written FAT entries     */
+/*    _fx_utility_32_unsigned_write         Write a ULONG from memory     */
+/*    _fx_utility_exFAT_system_sector_write Write data into boot sector   */
+/*    _fx_utility_exFAT_system_area_checksum_write                        */
+/*                                          Write checksum of boot sector */
+/*    _fx_utility_exFAT_bitmap_free_cluster_find                          */
+/*                                          Find a free cluster           */
+/*    _fx_utility_logical_sector_read       Read a logical sector         */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    _fx_fault_tolerant_enable                                           */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*  01-31-2022     Bhupendra Naphade        Modified comment(s), replaced */
+/*                                            sector size constant,       */
+/*                                            resulting in version 6.1.10 */
+/*  04-25-2022     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1.11 */
+/*                                                                        */
+/**************************************************************************/
+UINT _fx_fault_tolerant_create_log_file(FX_MEDIA *media_ptr)
+{
+ULONG  clusters;
+ULONG  FAT_index;
+ULONG  FAT_value = 0;
+UINT   found;
+UINT   status;
+UINT   i;
+#ifdef FX_ENABLE_EXFAT
+ULONG  checksum;
+UINT   count;
+UCHAR *byte_ptr;
+UCHAR  cluster_state;
+#endif /* FX_ENABLE_EXFAT */
+
+    /* Yes. Create a log file. */
+    /* First find a free cluster. */
+    if (media_ptr -> fx_media_available_clusters < media_ptr -> fx_media_fault_tolerant_clusters)
+    {
+
+        /* Out of disk space.  */
+        return(FX_NO_MORE_SPACE);
+    }
+
+    /* Now we need to find the consecutive clusters.  */
+    clusters = media_ptr -> fx_media_fault_tolerant_clusters;
+    FAT_index =  FX_FAT_ENTRY_START;
+    found =  FX_FALSE;
+    while (FAT_index <= (media_ptr -> fx_media_total_clusters - clusters + FX_FAT_ENTRY_START))
+    {
+
+        /* Determine if enough consecutive FAT entries are available.  */
+        i =  0;
+
+#ifdef FX_ENABLE_EXFAT
+        if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+        {
+            do
+            {
+
+                /* Get cluster state.  */
+                status = _fx_utility_exFAT_cluster_state_get(media_ptr, (FAT_index + i), &cluster_state);
+
+                /* Check for a successful status.  */
+                if (status != FX_SUCCESS)
+                {
+
+                    /* Return the error status.  */
+                    return(status);
+                }
+
+                /* Determine if the entry is free.  */
+                if (cluster_state == FX_EXFAT_BITMAP_CLUSTER_OCCUPIED)
+                {
+                    break;
+                }
+
+                /* Otherwise, increment the consecutive FAT indices.  */
+                i++;
+            } while (i < clusters);
+        }
+        else
+        {
+#endif /* FX_ENABLE_EXFAT */
+
+            do
+            {
+
+                /* Read a FAT entry.  */
+                status =  _fx_utility_FAT_entry_read(media_ptr, (FAT_index + i), &FAT_value);
+
+                /* Check for a successful status.  */
+                if (status != FX_SUCCESS)
+                {
+
+                    /* Return the error status.  */
+                    return(status);
+                }
+
+                /* Determine if the entry is free.  */
+                if (FAT_value != FX_FREE_CLUSTER)
+                {
+                    break;
+                }
+
+                /* Otherwise, increment the consecutive FAT indices.  */
+                i++;
+            } while (i < clusters);
+#ifdef FX_ENABLE_EXFAT
+        }
+#endif /* FX_ENABLE_EXFAT */
+
+        /* Determine if we found enough FAT entries.  */
+        if (i >= clusters)
+        {
+
+            /* Yes, we have found enough FAT entries - set the found
+               flag and get out of this loop.  */
+            found =  FX_TRUE;
+            break;
+        }
+        else
+        {
+#ifdef FX_ENABLE_EXFAT
+            if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+            {
+
+                /* Find free cluster from exFAT media.  */
+                status = _fx_utility_exFAT_bitmap_free_cluster_find(media_ptr,
+                                                                    FAT_index + i + 1,
+                                                                    &FAT_value);
+                if (status != FX_SUCCESS)
+                {
+
+                    /* Return the error status.  */
+                    return(status);
+                }
+
+                if (FAT_value < FAT_index + i + 1)
+                {
+
+                    /* If we wrapped.  */
+                    FAT_index = media_ptr -> fx_media_total_clusters + FX_FAT_ENTRY_START;
+                }
+                else
+                {
+                    FAT_index = FAT_value;
+                }
+            }
+            else
+            {
+#endif /* FX_ENABLE_EXFAT */
+                /* Position to the next possibly free FAT entry.  */
+                FAT_index =  FAT_index + i + 1;
+#ifdef FX_ENABLE_EXFAT
+            }
+#endif /* FX_ENABLE_EXFAT */
+        }
+    }
+
+    /* Determine if we found enough consecutive clusters to satisfy the
+       request.  */
+    if (!found)
+    {
+
+        /* Not enough contiguous space on the media.  Return error status.  */
+        return(FX_NO_MORE_SPACE);
+    }
+
+    /* Update the link pointers in the new clusters.  */
+    for (i = 0; i < (clusters - 1); i++)
+    {
+
+        /* Update the cluster links.  Since the allocation is
+           sequential, we just have to link each FAT entry to the
+           next one.  */
+        status =  _fx_utility_FAT_entry_write(media_ptr, FAT_index + i, FAT_index + i + 1);
+
+        /* Check for a bad status.  */
+        if (status != FX_SUCCESS)
+        {
+
+            /* Return the error status.  */
+            return(status);
+        }
+
+#ifdef FX_ENABLE_EXFAT
+
+        if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+        {
+
+            /* Mark the cluster as used.  */
+            status = _fx_utility_exFAT_cluster_state_set(media_ptr, FAT_index + i, FX_EXFAT_BITMAP_CLUSTER_OCCUPIED);
+
+            /* Check for a bad status.  */
+            if (status != FX_SUCCESS)
+            {
+
+                /* Return the error status.  */
+                return(status);
+            }
+        }
+#endif /* FX_ENABLE_EXFAT */
+    }
+
+    /* Now place an EOF in the last cluster entry.  */
+    status =  _fx_utility_FAT_entry_write(media_ptr, FAT_index + clusters - 1, media_ptr -> fx_media_fat_last);
+
+    /* Check for a bad status.  */
+    if (status != FX_SUCCESS)
+    {
+
+        /* Return the error status.  */
+        return(status);
+    }
+
+#ifdef FX_ENABLE_EXFAT
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+
+        /* Mark the cluster as used.  */
+        status = _fx_utility_exFAT_cluster_state_set(media_ptr, FAT_index + clusters - 1, FX_EXFAT_BITMAP_CLUSTER_OCCUPIED);
+
+        /* Check for a bad status.  */
+        if (status != FX_SUCCESS)
+        {
+
+            /* Return the error status.  */
+            return(status);
+        }
+    }
+#endif /* FX_ENABLE_EXFAT */
+
+#ifdef FX_FAULT_TOLERANT
+
+    /* Flush the cached individual FAT entries */
+    _fx_utility_FAT_flush(media_ptr);
+
+#ifdef FX_ENABLE_EXFAT
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+        _fx_utility_exFAT_bitmap_flush(media_ptr);
+    }
+#endif /* FX_ENABLE_EXFAT */
+#endif /* FX_FAULT_TOLERANT */
+
+    /* Write start cluster for the file tolerant log file into the boot sector. */
+    _fx_utility_32_unsigned_write(media_ptr -> fx_media_fault_tolerant_memory_buffer + FX_FAULT_TOLERANT_BOOT_INDEX, FAT_index);
+
+    /* Write the boot sector.  */
+    media_ptr -> fx_media_driver_request =       FX_DRIVER_BOOT_WRITE;
+    media_ptr -> fx_media_driver_status =        FX_IO_ERROR;
+    media_ptr -> fx_media_driver_buffer =        media_ptr -> fx_media_fault_tolerant_memory_buffer;
+    media_ptr -> fx_media_driver_sectors =       1;
+    media_ptr -> fx_media_driver_sector_type =   FX_BOOT_SECTOR;
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_BOOT_WRITE, media_ptr, media_ptr -> fx_media_fault_tolerant_memory_buffer, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+    /* Invoke the driver to read the boot sector.  */
+    (media_ptr -> fx_media_driver_entry) (media_ptr);
+
+    /* Determine if the boot sector was read correctly. */
+    if (media_ptr -> fx_media_driver_status != FX_SUCCESS)
+    {
+
+        /* Return the boot sector error status.  */
+        return(FX_BOOT_ERROR);
+    }
+
+#ifdef FX_ENABLE_EXFAT
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+
+        /* Write backup. */
+        status = _fx_utility_exFAT_system_sector_write(media_ptr, media_ptr -> fx_media_fault_tolerant_memory_buffer,
+                                                       FX_EXFAT_FAT_MAIN_SYSTEM_AREA_SIZE,
+                                                       1, FX_BOOT_SECTOR);
+
+        /* Determine if the boot sector was read correctly. */
+        if (status != FX_SUCCESS)
+        {
+
+            /* Return the boot sector error status.  */
+            return(FX_BOOT_ERROR);
+        }
+
+        /* Calculate checksum. */
+        checksum = 0;
+        byte_ptr = media_ptr -> fx_media_fault_tolerant_memory_buffer;
+
+        /* Calculate Boot Sector Check Sum.  */
+        for (i = 0; i < media_ptr -> fx_media_bytes_per_sector; i++)
+        {
+            if ((FX_EF_VOLUME_FLAGS     == i) ||
+                (FX_EF_VOLUME_FLAGS + 1 == i) ||
+                (FX_EF_PERCENT_IN_USE   == i))
+            {
+                continue;
+            }
+
+            checksum = ((checksum >> 1) | (checksum << 31)) + (ULONG)byte_ptr[i];
+        }
+
+        for (count = 1; count < FX_EXFAT_FAT_CHECK_SUM_OFFSET; count++)
+        {
+
+            /* Read sector. */
+            status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) count,
+                                                      media_ptr -> fx_media_fault_tolerant_memory_buffer, ((ULONG) 1), FX_BOOT_SECTOR);
+
+            /* Check for good completion status.  */
+            if (status !=  FX_SUCCESS)
+            {
+
+                /* Return the error status.  */
+                return(status);
+            }
+
+            /* Calculate Check Sum for System Area  */
+            for (i = 0; i < media_ptr -> fx_media_bytes_per_sector; i++)
+            {
+                checksum = ((checksum >> 1) | (checksum << 31)) + (ULONG)byte_ptr[i];
+            }
+        }
+
+        /* Write System Area CheckSum.  */
+        status = _fx_utility_exFAT_system_area_checksum_write(media_ptr, media_ptr -> fx_media_fault_tolerant_memory_buffer,
+                                                              &checksum);
+
+        if (status != FX_SUCCESS)
+        {
+
+            return(status);
+        }
+    }
+#endif /* FX_ENABLE_EXFAT */
+
+    /* Set the start cluster. */
+    media_ptr -> fx_media_fault_tolerant_start_cluster = FAT_index;
+
+    /* Decrease available cluster. */
+    media_ptr -> fx_media_available_clusters =
+        media_ptr -> fx_media_available_clusters - clusters;
+
+    /* Return success.  */
+    return(FX_SUCCESS);
+}
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_enable.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_enable.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_enable.c	(revision 30)
@@ -0,0 +1,538 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Fault Tolerant                                                      */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+#include "fx_api.h"
+#include "fx_utility.h"
+#include "fx_directory.h"
+#include "fx_fault_tolerant.h"
+
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_fault_tolerant_enable                           PORTABLE C      */
+/*                                                           6.2.0        */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function enables the FileX Fault Tolerant feature. It first    */
+/*    searches for a valid log file.  A valid log file indicates the      */
+/*    previous write operation failed, and appropriate action now must    */
+/*    be taken to restore the integrity of the file system.  Once the     */
+/*    recovery effort is completed, the file system is properly restored. */
+/*    An empty log file indicates the previous write operation was        */
+/*    successfully completed and no action needs to be taken at this      */
+/*    point.  If the file system does not have a log file, or the         */
+/*    checksum is not valid, it is an indication either the file system   */
+/*    is not under the protection of FileX Fault Tolerant.  A new log     */
+/*    file is created.                                                    */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    memory_buffer                         Pointer to memory buffer.     */
+/*    memory_size                           Size of memory buffer.        */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_fault_tolerant_calculate_checksum Compute Checksum of data      */
+/*    _fx_fault_tolerant_apply_logs         Apply logs into file system   */
+/*    _fx_fault_tolerant_recover            Recover FAT chain             */
+/*    _fx_fault_tolerant_reset_log_file     Reset the log file            */
+/*    _fx_fault_tolerant_read_log_file      Read log file to cache        */
+/*    _fx_utility_exFAT_cluster_state_get   Get state of exFAT cluster    */
+/*    _fx_utility_FAT_entry_read            Read a FAT entry              */
+/*    _fx_utility_16_unsigned_read          Read a USHORT from memory     */
+/*    _fx_utility_32_unsigned_read          Read a ULONG from memory      */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*  10-31-2022     Tiejun Zhou              Modified comment(s),          */
+/*                                            fixed memory buffer when    */
+/*                                            cache is disabled,          */
+/*                                            resulting in version 6.2.0  */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_fault_tolerant_enable(FX_MEDIA *media_ptr, VOID *memory_buffer, UINT memory_size)
+{
+ULONG                         start_cluster;
+ULONG                         FAT_value;
+UINT                          status;
+ULONG                         checksum;
+ULONG                         total_size;
+FX_FAULT_TOLERANT_LOG_HEADER *log_header;
+FX_FAULT_TOLERANT_FAT_CHAIN  *FAT_chain;
+ULONG                         cluster_number;
+ULONG                         i, j;
+ULONG                         FAT_entry, FAT_sector, FAT_read_sectors;
+ULONG                         bytes_in_buffer;
+ULONG                         clusters;
+ULONG                         bytes_per_sector; 
+ULONG                         bytes_per_cluster; 
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+    /* Calculate clusters needed for fault tolerant log. */
+    bytes_per_sector = media_ptr -> fx_media_bytes_per_sector;
+    bytes_per_cluster = bytes_per_sector * media_ptr -> fx_media_sectors_per_cluster;
+
+    if (bytes_per_cluster == 0)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        return(FX_MEDIA_INVALID);
+    }
+
+    clusters = (FX_FAULT_TOLERANT_MAXIMUM_LOG_FILE_SIZE + bytes_per_cluster - 1) / bytes_per_cluster;
+    media_ptr -> fx_media_fault_tolerant_clusters = clusters;
+
+    /* Check buffer size requirement. */
+    if (memory_size < bytes_per_sector)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        return(FX_NOT_ENOUGH_MEMORY);
+    }
+
+
+    if (media_ptr -> fx_media_FAT32_additional_info_sector)
+    {
+
+        /* A 32-bit FAT is present. Read directly into the logical sector
+           cache memory to optimize I/O on larger devices. Since we are looking for
+           values of zero, endian issues are not important.  */
+        /* Force update the available cluster. */
+
+#ifndef FX_DISABLE_CACHE
+        /* Invalidate the current logical sector cache.  */
+        _fx_utility_logical_sector_flush(media_ptr, ((ULONG64) 1), (ULONG64) (media_ptr -> fx_media_total_sectors), FX_TRUE);
+
+        /* Reset the memory pointer.  */
+        media_ptr -> fx_media_memory_buffer = media_ptr -> fx_media_sector_cache[0].fx_cached_sector_memory_buffer;
+#endif /* FX_DISABLE_CACHE */
+
+        /* Reset the available cluster. */
+        media_ptr -> fx_media_available_clusters = 0;
+
+        /* Loop through all FAT sectors in the primary FAT.  The first two entries are
+           examined in this loop, but they are always unavailable.  */
+        cluster_number =  0;
+#ifndef FX_DISABLE_CACHE
+        for (i = 0; i < media_ptr -> fx_media_sectors_per_FAT; i = i + media_ptr -> fx_media_sector_cache_size)
+        {
+
+            /* Calculate the starting next FAT sector.  */
+            FAT_sector =  media_ptr -> fx_media_reserved_sectors + i;
+
+            /* Calculate how many sectors to read.  */
+            FAT_read_sectors =  media_ptr -> fx_media_sectors_per_FAT - i;
+
+            /* Determine if there is not enough memory to read the remaining FAT sectors.  */
+            if (FAT_read_sectors > media_ptr -> fx_media_sector_cache_size)
+            {
+                FAT_read_sectors =  media_ptr -> fx_media_sector_cache_size;
+            }
+#else
+        /* Reset the buffer sector.  */
+        media_ptr -> fx_media_memory_buffer_sector = (ULONG64)-1;
+        for (i = 0; i < media_ptr -> fx_media_sectors_per_FAT; i++)
+        {
+
+            /* Calculate the starting next FAT sector.  */
+            FAT_sector =  media_ptr -> fx_media_reserved_sectors + i;
+
+            /* Calculate how many sectors to read.  */
+            FAT_read_sectors =  1;
+#endif /* FX_DISABLE_CACHE */
+
+            /* Read the FAT sectors directly from the driver.  */
+            media_ptr -> fx_media_driver_request =          FX_DRIVER_READ;
+            media_ptr -> fx_media_driver_status =           FX_IO_ERROR;
+            media_ptr -> fx_media_driver_buffer =           media_ptr -> fx_media_memory_buffer;
+            media_ptr -> fx_media_driver_logical_sector =   FAT_sector;
+            media_ptr -> fx_media_driver_sectors =          FAT_read_sectors;
+            media_ptr -> fx_media_driver_sector_type =      FX_FAT_SECTOR;
+
+            /* If trace is enabled, insert this event into the trace buffer.  */
+            FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_READ, media_ptr, FAT_sector, FAT_read_sectors, media_ptr -> fx_media_memory_buffer, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+            /* Invoke the driver to read the FAT sectors.  */
+            (media_ptr -> fx_media_driver_entry) (media_ptr);
+
+            /* Determine if the read was successful.  */
+            if (media_ptr -> fx_media_driver_status != FX_SUCCESS)
+            {
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                return(FX_FAT_READ_ERROR);
+            }
+
+            /* Calculate the number of bytes in the buffer.  */
+            bytes_in_buffer =  (media_ptr -> fx_media_bytes_per_sector * FAT_read_sectors);
+
+            /* Walk through the sector cache memory to search for available clusters and the first
+               available if not already found.  */
+            for (j = 0; j < bytes_in_buffer;)
+            {
+
+                /* Pickup 32-bit FAT entry.  */
+                FAT_entry =  *((ULONG *)&(media_ptr -> fx_media_memory_buffer[j]));
+
+                /* Advance to next FAT entry.  */
+                j = j + 4;
+
+                /* Determine if the FAT entry is free.  */
+                if (FAT_entry == FX_FREE_CLUSTER)
+                {
+
+                    /* Entry is free, increment available clusters.  */
+                    media_ptr -> fx_media_available_clusters++;
+
+                    /* Determine if the starting free cluster has been found yet.  */
+                    if (media_ptr -> fx_media_cluster_search_start == 0)
+                    {
+
+                        /* Remember the first free cluster to start further searches from.  */
+                        media_ptr -> fx_media_cluster_search_start =  cluster_number;
+                    }
+                }
+
+                /* Increment the cluster number.  */
+                cluster_number++;
+
+                /* Determine if we have reviewed all FAT entries.  */
+                if (cluster_number >= (media_ptr -> fx_media_total_clusters + FX_FAT_ENTRY_START))
+                {
+
+                    /* Yes, we have looked at all the FAT entries.  */
+
+                    /* Ensure that the outer loop terminates as well.  */
+                    i = media_ptr -> fx_media_sectors_per_FAT;
+                    break;
+                }
+            }
+        }
+    }
+
+    /* Store memory buffer and size. */
+    media_ptr -> fx_media_fault_tolerant_memory_buffer = (UCHAR *)memory_buffer;
+    if (memory_size > (clusters * bytes_per_cluster))
+    {
+        media_ptr -> fx_media_fault_tolerant_memory_buffer_size = clusters * bytes_per_cluster;
+    }
+    else
+    {
+        media_ptr -> fx_media_fault_tolerant_memory_buffer_size = memory_size / bytes_per_sector * bytes_per_sector;
+    }
+
+    /* Read the boot sector from the device.  */
+    media_ptr -> fx_media_driver_request =          FX_DRIVER_BOOT_READ;
+    media_ptr -> fx_media_driver_status =           FX_IO_ERROR;
+    media_ptr -> fx_media_driver_buffer =           (UCHAR *)memory_buffer;
+    media_ptr -> fx_media_driver_sectors =          1;
+    media_ptr -> fx_media_driver_sector_type =      FX_BOOT_SECTOR;
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_BOOT_READ, media_ptr, memory_buffer, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+    /* Invoke the driver to read the boot sector.  */
+    (media_ptr -> fx_media_driver_entry) (media_ptr);
+
+    /* Determine if the boot sector was read correctly. */
+    if (media_ptr -> fx_media_driver_status != FX_SUCCESS)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the boot sector error status.  */
+        return(FX_BOOT_ERROR);
+    }
+
+    /* Check whether the boot index is used. */
+    start_cluster = _fx_utility_32_unsigned_read((UCHAR *)memory_buffer + FX_FAULT_TOLERANT_BOOT_INDEX);
+    if (start_cluster != 0)
+    {
+
+        /* The location of the fault tolerant log file is found.  Need to verify the integrity of the log file. */
+        if ((start_cluster >= FX_FAT_ENTRY_START) && (start_cluster < media_ptr -> fx_media_fat_reserved))
+        {
+
+            /* Check whether this cluster is used. */
+#ifdef FX_ENABLE_EXFAT
+            if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+            {
+            UCHAR cluste_state;
+
+                for (i = 0; i < clusters; i++)
+                {
+
+                    /* Update Bitmap */
+                    status = _fx_utility_exFAT_cluster_state_get(media_ptr, start_cluster + i, &cluste_state);
+
+                    /* Check for a bad status.  */
+                    if (status != FX_SUCCESS)
+                    {
+
+                        /* Release media protection.  */
+                        FX_UNPROTECT
+
+                        /* Return the bad status.  */
+                        return(status);
+                    }
+
+                    if (cluste_state != FX_EXFAT_BITMAP_CLUSTER_OCCUPIED)
+                    {
+
+                        /* Mark invalid. */
+                        start_cluster = 0;
+                        break;
+                    }
+                }
+            }
+            else
+            {
+#endif /* FX_ENABLE_EXFAT */
+                for (i = 0; i < clusters; i++)
+                {
+
+                    /* Read FAT entry.  */
+                    status =  _fx_utility_FAT_entry_read(media_ptr, start_cluster + i, &FAT_value);
+
+                    /* Check for a bad status.  */
+                    if (status != FX_SUCCESS)
+                    {
+
+                        /* Release media protection.  */
+                        FX_UNPROTECT
+
+                        /* Return the bad status.  */
+                        return(status);
+                    }
+
+                    if (i < clusters - 1)
+                    {
+                        if (FAT_value != (start_cluster + i + 1))
+                        {
+
+                            /* Mark invalid. */
+                            start_cluster = 0;
+                            break;
+                        }
+                    }
+                    else if (FAT_value != media_ptr -> fx_media_fat_last)
+                    {
+
+                        /* Mark invalid. */
+                        start_cluster = 0;
+                        break;
+                    }
+                }
+#ifdef FX_ENABLE_EXFAT
+            }
+#endif /* FX_ENABLE_EXFAT */
+
+            /* Is this FAT entry occupied by log file? */
+            if (start_cluster)
+            {
+
+                /* Set the start cluster. */
+                media_ptr -> fx_media_fault_tolerant_start_cluster = start_cluster;
+
+                /* Read log file from file system to memory. */
+                status = _fx_fault_tolerant_read_log_file(media_ptr);
+
+                /* Check for good completion status.  */
+                if (status !=  FX_SUCCESS)
+                {
+
+                    /* Release media protection.  */
+                    FX_UNPROTECT
+
+                    /* Return the error status.  */
+                    return(status);
+                }
+
+                /* Set log header and FAT chain pointer. */
+                log_header = (FX_FAULT_TOLERANT_LOG_HEADER *)media_ptr -> fx_media_fault_tolerant_memory_buffer;
+                FAT_chain = (FX_FAULT_TOLERANT_FAT_CHAIN *)(media_ptr -> fx_media_fault_tolerant_memory_buffer +
+                                                            FX_FAULT_TOLERANT_FAT_CHAIN_OFFSET);
+
+                /* Verify ID field. */
+                if (_fx_utility_32_unsigned_read((UCHAR *)&log_header -> fx_fault_tolerant_log_header_id) == FX_FAULT_TOLERANT_ID)
+                {
+
+                    /* Calculate checksum of log header. */
+                    checksum = _fx_fault_tolerant_calculate_checksum((UCHAR *)log_header,
+                                                                     FX_FAULT_TOLERANT_LOG_HEADER_SIZE);
+
+                    if (checksum == 0)
+                    {
+
+                        /* Fault tolerant log file is valid. */
+                        /* Initialize file size. */
+                        total_size = _fx_utility_16_unsigned_read((UCHAR *)&log_header -> fx_fault_tolerant_log_header_total_size);
+                        media_ptr -> fx_media_fault_tolerant_file_size = total_size;
+
+
+                        /* Verify the checksum of the FAT chain. */
+                        checksum = _fx_fault_tolerant_calculate_checksum((UCHAR *)FAT_chain,
+                                                                         FX_FAULT_TOLERANT_FAT_CHAIN_SIZE);
+
+                        if (checksum == 0)
+                        {
+
+                            /* Checksum of FAT chain is correct. */
+
+                            if (total_size > (FX_FAULT_TOLERANT_LOG_CONTENT_OFFSET + FX_FAULT_TOLERANT_LOG_HEADER_SIZE))
+                            {
+
+                                /* Log content is present. */
+                                /* Now verify the checksum of log content. */
+                                checksum = _fx_fault_tolerant_calculate_checksum((media_ptr -> fx_media_fault_tolerant_memory_buffer +
+                                                                                  FX_FAULT_TOLERANT_LOG_CONTENT_OFFSET),
+                                                                                 (total_size - FX_FAULT_TOLERANT_LOG_CONTENT_OFFSET));
+                                if (checksum == 0)
+                                {
+
+                                    /* Checksum of log content is correct. */
+
+                                    /* Extended port-specific processing macro, which is by default defined to white space.  */
+                                    FX_FAULT_TOLERANT_ENABLE_EXTENSION
+
+                                    /* This is the situation where the log file contains log entries.  This is an indication
+                                       that previous write operation did not complete successfully.  Need to apply the log entries
+                                       to recover the previous write operation, effectively to finish up the previous write operation. */
+                                    status = _fx_fault_tolerant_apply_logs(media_ptr);
+                                }
+                            }
+                            else
+                            {
+
+                                /* Extended port-specific processing macro, which is by default defined to white space.  */
+                                FX_FAULT_TOLERANT_ENABLE_EXTENSION
+
+                                /* The log file does not contain log content but the FAT chain operation information is present.
+                                   This is the situation where the FAT chain has been modified but the rest of the content of these
+                                   clusters are not updated yet.  In this situation, the previous FAT chain operation needs to be
+                                   reverted to restore the file system back to its state prior to the write operation. */
+                                status = _fx_fault_tolerant_recover(media_ptr);
+                            }
+
+                            if (status !=  FX_SUCCESS)
+                            {
+
+                                /* Release media protection.  */
+                                FX_UNPROTECT
+
+                                /* Return the error status.  */
+                                return(status);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        else
+        {
+
+            /* Not a valid cluster number. Set the flag to create a new log file. */
+            start_cluster = 0;
+        }
+    }
+
+    /* Check whether or not to create a log file. */
+    if (start_cluster == 0)
+    {
+
+        /* Create log file. */
+        status = _fx_fault_tolerant_create_log_file(media_ptr);
+
+        if (status !=  FX_SUCCESS)
+        {
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* Return the error status.  */
+            return(status);
+        }
+    }
+
+    /* Reset log file. */
+    status = _fx_fault_tolerant_reset_log_file(media_ptr);
+
+    if (status !=  FX_SUCCESS)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the error status.  */
+        return(status);
+    }
+
+    /* Mark fault tolerant feature is enabled. */
+    media_ptr -> fx_media_fault_tolerant_enabled = FX_TRUE;
+
+    /* Reset the transaction count. */
+    media_ptr -> fx_media_fault_tolerant_transaction_count = 0;
+
+    /* Initialize the sector number of cached FAT entries. */
+    media_ptr -> fx_media_fault_tolerant_cached_FAT_sector = 0;
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* Return the error status.  */
+    return(FX_SUCCESS);
+}
+
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_read_FAT.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_read_FAT.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_read_FAT.c	(revision 30)
@@ -0,0 +1,193 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Fault Tolerant                                                      */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+#include "fx_api.h"
+#include "fx_utility.h"
+#include "fx_fault_tolerant.h"
+
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_fault_tolerant_read_FAT                         PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function reads value of a FAT entry from log file if it        */
+/*    exists.  During file or directory operations with Fault Tolerant    */
+/*    protection, intermediate operations are written to the fault        */
+/*    tolerant log files.  Therefore, FAT-entry read should search for    */
+/*    fault tolerant log before the request can be passed to normal FAT   */
+/*    entry read routine.                                                 */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    cluster                               Cluster entry number          */
+/*    value                                 Pointer to value for the entry*/
+/*    log_type                              FAT or bitmap                 */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_16_unsigned_read          Read a USHORT from memory     */
+/*    _fx_utility_32_unsigned_read          Read a ULONG from memory      */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    _fx_utility_exFAT_cluster_state_get                                 */
+/*    _fx_utility_FAT_entry_read                                          */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT    _fx_fault_tolerant_read_FAT(FX_MEDIA *media_ptr, ULONG cluster, ULONG *value, ULONG log_type)
+{
+ULONG                         logs_remaining;
+UCHAR                        *current_ptr;
+UCHAR                         found = FX_FALSE;
+ULONG                         size;
+USHORT                        type;
+ULONG                         log_len;
+FX_FAULT_TOLERANT_FAT_LOG    *fat_log;
+#ifdef FX_ENABLE_EXFAT
+FX_FAULT_TOLERANT_BITMAP_LOG *bitmap_log;
+#endif
+
+
+    /* Get fault tolerant data. */
+    logs_remaining = media_ptr -> fx_media_fault_tolerant_total_logs;
+
+    /* Any redo logs? */
+    if (logs_remaining == 0)
+    {
+
+        /* No. Just return. */
+        return(FX_READ_CONTINUE);
+    }
+
+    /* Get size of all logs. */
+    size = media_ptr -> fx_media_fault_tolerant_file_size - FX_FAULT_TOLERANT_LOG_CONTENT_OFFSET;
+
+    /* Get the first log pointer. */
+    current_ptr = media_ptr -> fx_media_fault_tolerant_memory_buffer +
+        FX_FAULT_TOLERANT_LOG_CONTENT_OFFSET +
+        FX_FAULT_TOLERANT_LOG_CONTENT_HEADER_SIZE;
+
+    /* Loop throught all FAT logs. */
+    while (logs_remaining)
+    {
+
+        /* Check log type. */
+        type = (USHORT)_fx_utility_16_unsigned_read(current_ptr);
+
+        /* Get log length. */
+        log_len = _fx_utility_16_unsigned_read(current_ptr + 2);
+
+        /* Validate the size value. */
+        if (log_len > size)
+        {
+
+            /* Log file is corrupted.  Nothing can be done.  Return.*/
+            return(FX_FILE_CORRUPT);
+        }
+        size -= log_len;
+
+        /* Check log type. */
+        if (type == log_type)
+        {
+
+            /* This is the log with same type . */
+            /* Get the log pointer. */
+#ifdef FX_ENABLE_EXFAT
+            if (type == FX_FAULT_TOLERANT_BITMAP_LOG_TYPE)
+            {
+                bitmap_log = (FX_FAULT_TOLERANT_BITMAP_LOG *)current_ptr;
+
+                /* Is this bitmap log entry the one looking for? */
+                if (_fx_utility_32_unsigned_read((UCHAR *)&bitmap_log -> fx_fault_tolerant_bitmap_log_cluster) == cluster)
+                {
+
+                    /* Yes, it is. */
+                    *value = _fx_utility_32_unsigned_read((UCHAR *)&bitmap_log -> fx_fault_tolerant_bitmap_log_value);
+
+                    /* Do not return since there may be more than one log for this cluster. */
+                    found = FX_TRUE;
+                }
+            }
+            else
+            {
+#endif /* FX_ENABLE_EXFAT */
+                fat_log = (FX_FAULT_TOLERANT_FAT_LOG *)current_ptr;
+
+                /* Is this FAT log entry the one looking for? */
+                if (_fx_utility_32_unsigned_read((UCHAR *)&fat_log -> fx_fault_tolerant_FAT_log_cluster) == cluster)
+                {
+
+                    /* Yes, it is. */
+                    *value = _fx_utility_32_unsigned_read((UCHAR *)&fat_log -> fx_fault_tolerant_FAT_log_value);
+
+                    /* Do not return since there may be more than one log for this cluster. */
+                    found = FX_TRUE;
+                }
+#ifdef FX_ENABLE_EXFAT
+            }
+#endif /* FX_ENABLE_EXFAT */
+        }
+
+        /* Decrease the logs_remaining counter. */
+        logs_remaining--;
+
+        /* Get next log pointer. */
+        current_ptr += log_len;
+    }
+
+    if (found != FX_TRUE)
+    {
+
+        /* Pass the request to FAT entry read. */
+        return(FX_READ_CONTINUE);
+    }
+
+    /* Return success. */
+    return(FX_SUCCESS);
+}
+
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_read_directory_sector.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_read_directory_sector.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_read_directory_sector.c	(revision 30)
@@ -0,0 +1,178 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Fault Tolerant                                                      */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+#include "fx_api.h"
+#include "fx_utility.h"
+#include "fx_fault_tolerant.h"
+
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_fault_tolerant_read_directory_sector            PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function handles directory sector read requests. During file or*/
+/*    directory operations with Fault Tolerant protection, intermediate   */
+/*    operations are written to the fault tolerant log files.  Therefore, */
+/*    sector read should search for fault tolerant log before the request */
+/*    can be passed to normal directory entry read routine.               */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    logical_sector                        Logical sector number         */
+/*    buffer_ptr                            Pointer of receiving buffer   */
+/*    sectors                               Number of sectors to read     */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_16_unsigned_read          Read a USHORT from memory     */
+/*    _fx_utility_32_unsigned_read          Read a ULONG from memory      */
+/*    memcpy                                Memory Copy                   */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    _fx_utility_logical_sector_read                                     */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s), verified */
+/*                                            memcpy usage,               */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT    _fx_fault_tolerant_read_directory_sector(FX_MEDIA *media_ptr, ULONG64 logical_sector,
+                                                 VOID *buffer_ptr, ULONG64 sectors)
+{
+ULONG                      logs_remaining;
+ULONG                      copy_offset;
+ULONG                      copy_size;
+UCHAR                     *current_ptr;
+UCHAR                     *current_buffer_ptr;
+ULONG                      size;
+USHORT                     type;
+ULONG                      log_len;
+ULONG64                    log_sector;
+FX_FAULT_TOLERANT_DIR_LOG *dir_log;
+
+    /* Get fault tolerant data. */
+    logs_remaining = media_ptr -> fx_media_fault_tolerant_total_logs;
+
+    /* Any redo logs? */
+    if (logs_remaining == 0)
+    {
+
+        /* No. Just return. */
+        return(FX_SUCCESS);
+    }
+
+    /* Get size of all logs. */
+    size = media_ptr -> fx_media_fault_tolerant_file_size - FX_FAULT_TOLERANT_LOG_CONTENT_OFFSET;
+
+    /* Get the first log pointer. */
+    current_ptr = media_ptr -> fx_media_fault_tolerant_memory_buffer +
+                  FX_FAULT_TOLERANT_LOG_CONTENT_OFFSET +
+                  FX_FAULT_TOLERANT_LOG_CONTENT_HEADER_SIZE;
+
+    /* Loop throught all FAT logs. */
+    while (logs_remaining)
+    {
+
+        /* Check log type. */
+        type = (USHORT)_fx_utility_16_unsigned_read(current_ptr);
+
+        /* Get log length. */
+        log_len = _fx_utility_16_unsigned_read(current_ptr + 2);
+
+        /* Validate the size value. */
+        if (log_len > size)
+        {
+
+            /* Log file is corrupted.  Nothing can be done.  Return.*/
+            return(FX_FILE_CORRUPT);
+        }
+        size -= log_len;
+
+        /* Check log type. */
+        if (type == FX_FAULT_TOLERANT_DIR_LOG_TYPE)
+        {
+
+            /* Get the log pointer. */
+            dir_log = (FX_FAULT_TOLERANT_DIR_LOG *)current_ptr;
+
+            /* Get the sector of log. */
+            log_sector = _fx_utility_64_unsigned_read((UCHAR *)&dir_log -> fx_fault_tolerant_dir_log_sector);
+
+            /* Is this log sector in the range of sectors to read? */
+            if ((log_sector >= logical_sector) && (log_sector < logical_sector + sectors))
+            {
+
+                /* Yes. Update the content in this sector. */
+                current_buffer_ptr = ((UCHAR *)buffer_ptr) + (log_sector - logical_sector) *
+                    media_ptr -> fx_media_bytes_per_sector;
+
+                /* Set copy information. */
+                copy_offset = _fx_utility_32_unsigned_read((UCHAR *)&dir_log -> fx_fault_tolerant_dir_log_offset);
+
+                copy_size = log_len - FX_FAULT_TOLERANT_DIR_LOG_ENTRY_SIZE;
+
+                if ((copy_offset + copy_size) > media_ptr -> fx_media_bytes_per_sector)
+                {
+                    return(FX_FILE_CORRUPT);
+                }
+
+                /* Copy data into destination sector. */
+                memcpy(current_buffer_ptr + copy_offset,  /* Use case of memcpy is verified. */
+                       current_ptr + FX_FAULT_TOLERANT_DIR_LOG_ENTRY_SIZE, copy_size);
+            }
+        }
+
+        /* Decrease the logs_remaining counter. */
+        logs_remaining--;
+
+        /* Move to start position of next log entry. */
+        current_ptr += log_len;
+    }
+
+    /* Return success. */
+    return(FX_SUCCESS);
+}
+
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_read_log_file.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_read_log_file.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_read_log_file.c	(revision 30)
@@ -0,0 +1,93 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Fault Tolerant                                                      */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+#include "fx_api.h"
+#include "fx_utility.h"
+#include "fx_fault_tolerant.h"
+
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_fault_tolerant_read_log_file                    PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function reads the entire log file from file system into the   */
+/*    fault tolerant cache.                                               */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_logical_sector_read       Read a logical sector         */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    _fx_fault_tolerant_enable                                           */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT _fx_fault_tolerant_read_log_file(FX_MEDIA *media_ptr)
+{
+UINT  status;
+ULONG sectors;
+ULONG start_sector;
+
+    /* Calculate count of sectors to read. */
+    sectors = media_ptr -> fx_media_fault_tolerant_memory_buffer_size / media_ptr -> fx_media_bytes_per_sector;
+
+    /* Calculate the start sector of log file. */
+    start_sector = (media_ptr -> fx_media_fault_tolerant_start_cluster - FX_FAT_ENTRY_START) *
+                   media_ptr -> fx_media_sectors_per_cluster +
+                   media_ptr -> fx_media_data_sector_start;
+
+    status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) start_sector,
+                                              media_ptr -> fx_media_fault_tolerant_memory_buffer,
+                                              sectors, FX_DATA_SECTOR);
+
+    /* Return the status.  */
+    return(status);
+}
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_recover.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_recover.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_recover.c	(revision 30)
@@ -0,0 +1,168 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Fault Tolerant                                                      */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+#include "fx_api.h"
+#include "fx_utility.h"
+#include "fx_fault_tolerant.h"
+
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_fault_tolerant_recover                          PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function is called after the FAT chain is been updated but     */
+/*    the rest of the write operation fails.  At this point, there is     */
+/*    need to undo the FAT chain operation, which includes:               */
+/*    (1) Remove newly allocated FAT entries;                             */
+/*    (2) Restore the origianl FAT chain removed during the FAT chain     */
+/*        update;                                                         */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_fault_tolerant_cleanup_FAT_chain  Cleanup FAT chain             */
+/*    _fx_utility_32_unsigned_read          Read a ULONG from memory      */
+/*    _fx_utility_FAT_entry_write           Write a FAT entry             */
+/*    _fx_utility_exFAT_bitmap_flush        Flush exFAT allocation bitmap */
+/*    _fx_utility_FAT_flush                 Flush written FAT entries     */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    _fx_directory_attributes_set                                        */
+/*    _fx_directory_create                                                */
+/*    _fx_directory_delete                                                */
+/*    _fx_directory_rename                                                */
+/*    _fx_file_allocate                                                   */
+/*    _fx_file_attributes_set                                             */
+/*    _fx_file_best_effort_allocate                                       */
+/*    _fx_file_create                                                     */
+/*    _fx_file_delete                                                     */
+/*    _fx_file_rename                                                     */
+/*    _fx_file_truncate                                                   */
+/*    _fx_file_truncate_release                                           */
+/*    _fx_file_write                                                      */
+/*    _fx_unicode_directory_create                                        */
+/*    _fx_unicode_file_create                                             */
+/*    _fx_fault_tolerant_enable                                           */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT _fx_fault_tolerant_recover(FX_MEDIA *media_ptr)
+{
+UINT                         status;
+ULONG                        insertion_front;
+ULONG                        origianl_head_cluster;
+FX_FAULT_TOLERANT_FAT_CHAIN *FAT_chain;
+
+
+    /* Set fault tolerant state to IDLE. */
+    media_ptr -> fx_media_fault_tolerant_state = FX_FAULT_TOLERANT_STATE_IDLE;
+
+    /* Set FAT chain pointer. */
+    FAT_chain = (FX_FAULT_TOLERANT_FAT_CHAIN *)(media_ptr -> fx_media_fault_tolerant_memory_buffer + FX_FAULT_TOLERANT_FAT_CHAIN_OFFSET);
+
+    /* Whether or not the supplied FAT chain is valid. */
+    if (!(FAT_chain -> fx_fault_tolerant_FAT_chain_flag & FX_FAULT_TOLERANT_FLAG_FAT_CHAIN_VALID))
+    {
+
+        /* Invalid, which indiates the FAT chain has been cleaned up already.  In this case, just return. */
+        return(FX_SUCCESS);
+    }
+
+    /* Set FAT chain pointer. */
+    FAT_chain = (FX_FAULT_TOLERANT_FAT_CHAIN *)(media_ptr -> fx_media_fault_tolerant_memory_buffer + FX_FAULT_TOLERANT_FAT_CHAIN_OFFSET);
+
+    /* Recover FAT chain. */
+    status = _fx_fault_tolerant_cleanup_FAT_chain(media_ptr, FX_FAULT_TOLERANT_FAT_CHAIN_RECOVER);
+    if (status != FX_SUCCESS)
+    {
+
+        /* Return the error status.  */
+        return(status);
+    }
+
+    /* Now, link the front of the insertion point back to the origianl FAT chain. */
+    insertion_front = _fx_utility_32_unsigned_read((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_insertion_front);
+    origianl_head_cluster = _fx_utility_32_unsigned_read((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_head_original);
+
+    if (insertion_front != FX_FREE_CLUSTER)
+    {
+
+        /* Front of the insertion point exists. Link the origianl chain back to the front of the insertion point. */
+        status = _fx_utility_FAT_entry_write(media_ptr, insertion_front, origianl_head_cluster);
+        if (status != FX_SUCCESS)
+        {
+
+            /* Return the error status.  */
+            return(status);
+        }
+    }
+
+    /* New FAT chain is always linked by FAT entries. */
+
+    /* Flush FAT table. */
+#ifdef FX_FAULT_TOLERANT
+#ifdef FX_ENABLE_EXFAT
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+
+        /* Flush exFAT bitmap.  */
+        _fx_utility_exFAT_bitmap_flush(media_ptr);
+    }
+#endif /* FX_ENABLE_EXFAT */
+
+    /* Ensure the new FAT chain is properly written to the media.  */
+
+    /* Flush the cached individual FAT entries */
+    _fx_utility_FAT_flush(media_ptr);
+#endif
+
+    /* Return success. */
+    return(FX_SUCCESS);
+}
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_reset_log_file.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_reset_log_file.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_reset_log_file.c	(revision 30)
@@ -0,0 +1,142 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Fault Tolerant                                                      */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+#include "fx_api.h"
+#include "fx_utility.h"
+#include "fx_directory.h"
+#include "fx_fault_tolerant.h"
+
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_fault_tolerant_reset_log_file                   PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function removes all log entries from the log file, and        */
+/*    it to its initial state.                                            */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_16_unsigned_write         Write a USHORT from memory    */
+/*    _fx_utility_32_unsigned_write         Write a ULONG from memory     */
+/*    _fx_fault_tolerant_calculate_checksum Compute Checksum of data      */
+/*    _fx_fault_tolerant_write_log_file     Write log file                */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    _fx_directory_attributes_set                                        */
+/*    _fx_directory_create                                                */
+/*    _fx_directory_delete                                                */
+/*    _fx_directory_rename                                                */
+/*    _fx_file_allocate                                                   */
+/*    _fx_file_attributes_set                                             */
+/*    _fx_file_best_effort_allocate                                       */
+/*    _fx_file_create                                                     */
+/*    _fx_file_delete                                                     */
+/*    _fx_file_rename                                                     */
+/*    _fx_file_truncate                                                   */
+/*    _fx_file_truncate_release                                           */
+/*    _fx_file_write                                                      */
+/*    _fx_unicode_directory_create                                        */
+/*    _fx_unicode_file_create                                             */
+/*    _fx_fault_tolerant_enable                                           */
+/*    _fx_fault_tolerant_transaction_end                                  */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+
+UINT _fx_fault_tolerant_reset_log_file(FX_MEDIA *media_ptr)
+{
+UINT                           status;
+USHORT                         checksum;
+FX_FAULT_TOLERANT_LOG_HEADER  *log_header;
+FX_FAULT_TOLERANT_FAT_CHAIN   *FAT_chain;
+FX_FAULT_TOLERANT_LOG_CONTENT *log_content;
+
+    /* Set log header, FAT chain and log content pointer. */
+    log_header = (FX_FAULT_TOLERANT_LOG_HEADER *)media_ptr -> fx_media_fault_tolerant_memory_buffer;
+    FAT_chain = (FX_FAULT_TOLERANT_FAT_CHAIN *)(media_ptr -> fx_media_fault_tolerant_memory_buffer +
+                                                FX_FAULT_TOLERANT_FAT_CHAIN_OFFSET);
+    log_content = (FX_FAULT_TOLERANT_LOG_CONTENT *)(media_ptr -> fx_media_fault_tolerant_memory_buffer +
+                                                    FX_FAULT_TOLERANT_LOG_CONTENT_OFFSET);
+
+    /* Reset the log file header. */
+    _fx_utility_32_unsigned_write((UCHAR *)&log_header -> fx_fault_tolerant_log_header_id, FX_FAULT_TOLERANT_ID);
+    _fx_utility_16_unsigned_write((UCHAR *)&log_header -> fx_fault_tolerant_log_header_total_size,
+                                  (FX_FAULT_TOLERANT_LOG_HEADER_SIZE + FX_FAULT_TOLERANT_FAT_CHAIN_SIZE));
+    _fx_utility_16_unsigned_write((UCHAR *)&log_header -> fx_fault_tolerant_log_header_checksum, 0);
+    log_header -> fx_fault_tolerant_log_header_version_major = FX_FAULT_TOLERANT_VERSION_MAJOR;
+    log_header -> fx_fault_tolerant_log_header_version_minor = FX_FAULT_TOLERANT_VERSION_MINOR;
+    _fx_utility_16_unsigned_write((UCHAR *)&log_header -> fx_fault_tolerant_log_header_reserved, 0);
+    checksum = _fx_fault_tolerant_calculate_checksum((UCHAR *)log_header, FX_FAULT_TOLERANT_LOG_HEADER_SIZE);
+    _fx_utility_16_unsigned_write((UCHAR *)&log_header -> fx_fault_tolerant_log_header_checksum, checksum);
+
+    /* Reset the undo log section. */
+    _fx_utility_16_unsigned_write((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_checksumm, 0xFFFF);
+    FAT_chain -> fx_fault_tolerant_FAT_chain_flag = 0;
+    FAT_chain -> fx_fault_tolerant_FAT_chain_reserved = 0;
+    _fx_utility_32_unsigned_write((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_insertion_front, 0);
+    _fx_utility_32_unsigned_write((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_head_new, 0);
+    _fx_utility_32_unsigned_write((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_head_original, 0);
+    _fx_utility_32_unsigned_write((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_insertion_back, 0);
+    _fx_utility_32_unsigned_write((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_next_deletion, 0);
+
+    /* Reset log content header. */
+    _fx_utility_16_unsigned_write((UCHAR *)&log_content -> fx_fault_tolerant_log_content_checksum, 0xFFFF);
+    _fx_utility_16_unsigned_write((UCHAR *)&log_content -> fx_fault_tolerant_log_content_count, 0xFFFF);
+
+    /* No matter success or fail, close this transaction. */
+    media_ptr -> fx_media_fault_tolerant_state = FX_FAULT_TOLERANT_STATE_IDLE;
+
+    /* Write the log header and FAT chain.  */
+    status =  _fx_fault_tolerant_write_log_file(media_ptr, 0);
+
+    /* Return the status.  */
+    return(status);
+}
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_set_FAT_chain.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_set_FAT_chain.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_set_FAT_chain.c	(revision 30)
@@ -0,0 +1,133 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Fault Tolerant                                                      */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+#include "fx_api.h"
+#include "fx_utility.h"
+#include "fx_fault_tolerant.h"
+
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_fault_tolerant_set_FAT_chain                     PORTABLE C     */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function sets data of FAT chain.                               */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    use_bitmap                            Whether or not the orignal    */
+/*                                            FAT chain uses bitmap       */
+/*    insertion_front                       Previous cluster of head      */
+/*    new_head_cluster                      Head cluster of new chain     */
+/*    origianl_head_cluster                 Head cluster of the original  */
+/*                                            chain                       */
+/*    insertion_back                        next cluster of chain tail    */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_16_unsigned_write         Write a USHORT from memory    */
+/*    _fx_utility_32_unsigned_write         Write a ULONG from memory     */
+/*    _fx_fault_tolerant_calculate_checksum Compute Checksum of data      */
+/*    _fx_fault_tolerant_write_log_file     Write log file                */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    _fx_file_allocate                                                   */
+/*    _fx_file_best_effort_allocate                                       */
+/*    _fx_file_delete                                                     */
+/*    _fx_file_truncate_release                                           */
+/*    _fx_file_write                                                      */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT    _fx_fault_tolerant_set_FAT_chain(FX_MEDIA *media_ptr, UINT use_bitmap, ULONG insertion_front,
+                                         ULONG new_head_cluster, ULONG original_head_cluster,
+                                         ULONG insertion_back)
+{
+UINT                         status;
+USHORT                       checksum;
+UCHAR                        flag = FX_FAULT_TOLERANT_FLAG_FAT_CHAIN_VALID;
+FX_FAULT_TOLERANT_FAT_CHAIN *FAT_chain;
+
+    /* Set FAT chain pointer. */
+    FAT_chain = (FX_FAULT_TOLERANT_FAT_CHAIN *)(media_ptr -> fx_media_fault_tolerant_memory_buffer + FX_FAULT_TOLERANT_FAT_CHAIN_OFFSET);
+
+#ifdef FX_ENABLE_EXFAT
+    /* Check flag for bitmap. */
+    if (use_bitmap == FX_TRUE)
+    {
+        flag |= FX_FAULT_TOLERANT_FLAG_BITMAP_USED;
+    }
+#else
+    /* Parameters not used. Avoid compiler warnings. */
+    FX_PARAMETER_NOT_USED(use_bitmap);
+#endif /* FX_ENABLE_EXFAT */
+
+
+    /* Reset checksum first. */
+    _fx_utility_16_unsigned_write((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_checksumm, 0);
+
+    /* Set clusters. */
+    _fx_utility_32_unsigned_write((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_insertion_front, insertion_front);
+    _fx_utility_32_unsigned_write((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_head_new, new_head_cluster);
+    _fx_utility_32_unsigned_write((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_head_original, original_head_cluster);
+    _fx_utility_32_unsigned_write((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_insertion_back, insertion_back);
+    _fx_utility_32_unsigned_write((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_next_deletion, FX_FREE_CLUSTER);
+
+    /* Set flag and reserved. */
+    FAT_chain -> fx_fault_tolerant_FAT_chain_flag = flag;
+    FAT_chain -> fx_fault_tolerant_FAT_chain_reserved = (UCHAR)0;
+
+    /* Calculate checksum. */
+    checksum = _fx_fault_tolerant_calculate_checksum((UCHAR *)FAT_chain, FX_FAULT_TOLERANT_FAT_CHAIN_SIZE);
+    _fx_utility_16_unsigned_write((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_checksumm, checksum);
+
+    /* Write the log header and FAT chain.  */
+    status =  _fx_fault_tolerant_write_log_file(media_ptr, 0);
+
+    /* Return the status.  */
+    return(status);
+}
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_transaction_end.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_transaction_end.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_transaction_end.c	(revision 30)
@@ -0,0 +1,207 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Fault Tolerant                                                      */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+#include "fx_api.h"
+#include "fx_fault_tolerant.h"
+#include "fx_utility.h"
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_fault_tolerant_transaction_end                  PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function completes a file system update operation protected    */
+/*    by fault tolerant.  This function first computes the checksum       */
+/*    for the log entries, flush the log file to the file system (a       */
+/*    necessary step to record vital information for the file system to   */
+/*    recover, in case the update operation fails midway).  After the     */
+/*    log entries are written to the physical medium, the actualy file    */
+/*    system changes (FAT table, directory entries) are applied.          */
+/*                                                                        */
+/*    If the file system changes are successfully applied, the log        */
+/*    entries can be removed.                                             */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_16_unsigned_write         Write a USHORT from memory    */
+/*    _fx_fault_tolerant_apply_logs         Apply logs into file system   */
+/*    _fx_fault_tolerant_calculate_checksum Compute Checksum of data      */
+/*    _fx_fault_tolerant_write_log_file     Write log file                */
+/*    _fx_fault_tolerant_reset_log_file     Reset the log file            */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    _fx_directory_attributes_set                                        */
+/*    _fx_directory_create                                                */
+/*    _fx_directory_delete                                                */
+/*    _fx_directory_rename                                                */
+/*    _fx_file_allocate                                                   */
+/*    _fx_file_attributes_set                                             */
+/*    _fx_file_best_effort_allocate                                       */
+/*    _fx_file_create                                                     */
+/*    _fx_file_delete                                                     */
+/*    _fx_file_rename                                                     */
+/*    _fx_file_truncate                                                   */
+/*    _fx_file_truncate_release                                           */
+/*    _fx_file_write                                                      */
+/*    _fx_unicode_directory_create                                        */
+/*    _fx_unicode_file_create                                             */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT    _fx_fault_tolerant_transaction_end(FX_MEDIA *media_ptr)
+{
+ULONG                          relative_sector;
+UINT                           status;
+USHORT                         checksum;
+UINT                           offset;
+FX_FAULT_TOLERANT_LOG_HEADER  *log_header;
+FX_FAULT_TOLERANT_LOG_CONTENT *log_content;
+
+    /* Is fault tolerant enabled? */
+    if (media_ptr -> fx_media_fault_tolerant_enabled == FX_FALSE)
+    {
+        return(FX_SUCCESS);
+    }
+
+    /* Decrease the transaction. */
+    media_ptr -> fx_media_fault_tolerant_transaction_count--;
+
+    /* Is transaction finished? */
+    if (media_ptr -> fx_media_fault_tolerant_transaction_count != 0)
+    {
+        return(FX_SUCCESS);
+    }
+
+    /* Close this transaction. */
+    media_ptr -> fx_media_fault_tolerant_state = FX_FAULT_TOLERANT_STATE_IDLE;
+
+    /* Set log header and FAT chain pointer. */
+    log_header = (FX_FAULT_TOLERANT_LOG_HEADER *)media_ptr -> fx_media_fault_tolerant_memory_buffer;
+    log_content = (FX_FAULT_TOLERANT_LOG_CONTENT *)(media_ptr -> fx_media_fault_tolerant_memory_buffer +
+                                                    FX_FAULT_TOLERANT_LOG_CONTENT_OFFSET);
+
+    /* Reset checksum field and update log entry counter field. */
+    _fx_utility_16_unsigned_write((UCHAR *)&log_content -> fx_fault_tolerant_log_content_checksum, 0);
+    _fx_utility_16_unsigned_write((UCHAR *)&log_content -> fx_fault_tolerant_log_content_count,
+                                  media_ptr -> fx_media_fault_tolerant_total_logs);
+
+    /* Now calculate the checksum of log content. */
+    checksum = _fx_fault_tolerant_calculate_checksum((media_ptr -> fx_media_fault_tolerant_memory_buffer +
+                                                      FX_FAULT_TOLERANT_LOG_CONTENT_OFFSET),
+                                                     (media_ptr -> fx_media_fault_tolerant_file_size -
+                                                      FX_FAULT_TOLERANT_LOG_CONTENT_OFFSET));
+
+    /* Record checksum field of log content. */
+    _fx_utility_16_unsigned_write((UCHAR *)&log_content -> fx_fault_tolerant_log_content_checksum, checksum);
+
+    /* Record log header. */
+    _fx_utility_16_unsigned_write((UCHAR *)&log_header -> fx_fault_tolerant_log_header_total_size,
+                                  media_ptr -> fx_media_fault_tolerant_file_size);
+    _fx_utility_16_unsigned_write((UCHAR *)&log_header -> fx_fault_tolerant_log_header_checksum, 0);
+
+    /* Calculate checksum of the header. */
+    checksum = _fx_fault_tolerant_calculate_checksum((UCHAR *)log_header, FX_FAULT_TOLERANT_LOG_HEADER_SIZE);
+
+    /* Record checksum field of the header. */
+    _fx_utility_16_unsigned_write((UCHAR *)&log_header -> fx_fault_tolerant_log_header_checksum, checksum);
+
+    /* Flush log content and flush first sector at last. The first sector contains size of total log file.
+     * The log file will contain wrong value of size when it is interrupted after first sector flushed to file system. */
+    relative_sector = 1;
+    offset = media_ptr -> fx_media_bytes_per_sector;
+    while (offset < media_ptr -> fx_media_fault_tolerant_file_size)
+    {
+
+        /* Write back the log.  */
+        status =  _fx_fault_tolerant_write_log_file(media_ptr, relative_sector);
+
+        /* Check for good completion status.  */
+        if (status !=  FX_SUCCESS)
+        {
+
+            /* Error.  */
+            return(status);
+        }
+
+        /* Increase relative sector and offset. */
+        relative_sector++;
+        offset += media_ptr -> fx_media_bytes_per_sector;
+    }
+
+    /* Flush first sector.  */
+    status =  _fx_fault_tolerant_write_log_file(media_ptr, 0);
+
+    /* Check for good completion status.  */
+    if (status !=  FX_SUCCESS)
+    {
+
+        /* Error.  */
+        return(status);
+    }
+
+    /* At this pointer, the vital information has been flushed to the physical medium.
+       Update the file system (FAT table, directory entry) using information recorded in the
+       log file.  */
+    status = _fx_fault_tolerant_apply_logs(media_ptr);
+
+    /* Check for a bad status.  */
+    if (status != FX_SUCCESS)
+    {
+
+        /* Return the bad status.  */
+        return(status);
+    }
+
+    /* The file system has been updated successfully.  Remove and reset the fault tolerant
+       log file. */
+    status = _fx_fault_tolerant_reset_log_file(media_ptr);
+
+    return(status);
+}
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_transaction_fail.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_transaction_fail.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_transaction_fail.c	(revision 30)
@@ -0,0 +1,105 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Fault Tolerant                                                      */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOUCE_CODE
+
+#include "fx_api.h"
+#include "fx_fault_tolerant.h"
+
+#if defined(FX_ENABLE_FAULT_TOLERANT) && defined(FX_FAULT_TOLERANT_TRANSACTION_FAIL_FUNCTION)
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_fault_tolerant_transaction_fail                 PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function cleans up resources created by fault tolerant when    */
+/*    transaction fails.                                                  */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    _fx_directory_attributes_set                                        */
+/*    _fx_directory_create                                                */
+/*    _fx_directory_delete                                                */
+/*    _fx_directory_rename                                                */
+/*    _fx_file_allocate                                                   */
+/*    _fx_file_attributes_set                                             */
+/*    _fx_file_best_effort_allocate                                       */
+/*    _fx_file_create                                                     */
+/*    _fx_file_delete                                                     */
+/*    _fx_file_rename                                                     */
+/*    _fx_file_truncate                                                   */
+/*    _fx_file_truncate_release                                           */
+/*    _fx_file_write                                                      */
+/*    _fx_unicode_directory_create                                        */
+/*    _fx_unicode_file_create                                             */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT _fx_fault_tolerant_transaction_fail(FX_MEDIA *media_ptr)
+{
+
+    /* Check whether fault tolerant is enabled or not. */
+    if (media_ptr -> fx_media_fault_tolerant_enabled == FX_TRUE)
+    {
+
+        /* Yes. Decrease the counter for transaction. */
+        media_ptr -> fx_media_fault_tolerant_transaction_count--;
+
+        /* Is this the last transaction? */
+        if (media_ptr -> fx_media_fault_tolerant_transaction_count == 0)
+        {
+
+            /* Yes. Perform recover and reset the log file. */
+            _fx_fault_tolerant_recover(media_ptr);
+            _fx_fault_tolerant_reset_log_file(media_ptr);
+        }
+    }
+
+    return(FX_SUCCESS);
+}
+#endif
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_transaction_start.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_transaction_start.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_transaction_start.c	(revision 30)
@@ -0,0 +1,115 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Fault Tolerant                                                      */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+#include "fx_api.h"
+#include "fx_fault_tolerant.h"
+
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_fault_tolerant_transaction_start                PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function is called at the beginning of an update to FileX      */
+/*    file, directory entry, or FAT table.  It resets fault tolerant      */
+/*    internal state information.                                         */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    _fx_directory_attributes_set                                        */
+/*    _fx_directory_create                                                */
+/*    _fx_directory_delete                                                */
+/*    _fx_directory_rename                                                */
+/*    _fx_file_allocate                                                   */
+/*    _fx_file_attributes_set                                             */
+/*    _fx_file_best_effort_allocate                                       */
+/*    _fx_file_create                                                     */
+/*    _fx_file_delete                                                     */
+/*    _fx_file_rename                                                     */
+/*    _fx_file_truncate                                                   */
+/*    _fx_file_truncate_release                                           */
+/*    _fx_file_write                                                      */
+/*    _fx_unicode_directory_create                                        */
+/*    _fx_unicode_file_create                                             */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT    _fx_fault_tolerant_transaction_start(FX_MEDIA *media_ptr)
+{
+
+    /* Is fault tolerant enabled? */
+    if (media_ptr -> fx_media_fault_tolerant_enabled == FX_TRUE)
+    {
+
+        /* Is this a new transaction? */
+        if (media_ptr -> fx_media_fault_tolerant_transaction_count == 0)
+        {
+
+            /* Yes. Initialize data. */
+            media_ptr -> fx_media_fault_tolerant_file_size = FX_FAULT_TOLERANT_LOG_HEADER_SIZE +
+                                                             FX_FAULT_TOLERANT_FAT_CHAIN_SIZE +
+                                                             FX_FAULT_TOLERANT_LOG_CONTENT_HEADER_SIZE;
+
+            /* Reset total logs. */
+            media_ptr -> fx_media_fault_tolerant_total_logs = 0;
+
+            /* Set state of fault tolerant. */
+            media_ptr -> fx_media_fault_tolerant_state = FX_FAULT_TOLERANT_STATE_STARTED;
+        }
+
+        /* Increase the transaction. */
+        media_ptr -> fx_media_fault_tolerant_transaction_count++;
+    }
+
+    return(FX_SUCCESS);
+}
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_write_log_file.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_write_log_file.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_fault_tolerant_write_log_file.c	(revision 30)
@@ -0,0 +1,112 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Fault Tolerant                                                      */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+#include "fx_api.h"
+#include "fx_utility.h"
+#include "fx_directory.h"
+#include "fx_fault_tolerant.h"
+
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_fault_tolerant_write_log_file                   PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function writes data of one sector of fault tolerant data      */
+/*    from memory to log file in file system.                             */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    relative_sector                       Relative sector number of the */
+/*                                          log file to write to          */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_logical_sector_write      Write a logical sector        */
+/*    _fx_utility_logical_sector_flush      Flush written logical sectors */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    _fx_fault_tolerant_cleanup_FAT_chain                                */
+/*    _fx_fault_tolerant_reset_log_file                                   */
+/*    _fx_fault_tolerant_set_FAT_chain                                    */
+/*    _fx_fault_tolerant_transaction_end                                  */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT _fx_fault_tolerant_write_log_file(FX_MEDIA *media_ptr, ULONG relative_sector)
+{
+UINT  status;
+ULONG start_sector;
+
+    /* Calculate the start sector of log file. */
+    start_sector = (media_ptr -> fx_media_fault_tolerant_start_cluster - FX_FAT_ENTRY_START) *
+                   media_ptr -> fx_media_sectors_per_cluster +
+                   media_ptr -> fx_media_data_sector_start;
+
+
+    /* Write sector directly. */
+    status =  _fx_utility_logical_sector_write(media_ptr, (ULONG64) (start_sector + relative_sector),
+                                               media_ptr -> fx_media_fault_tolerant_memory_buffer +
+                                               media_ptr -> fx_media_bytes_per_sector * relative_sector,
+                                               ((ULONG) 1), FX_DATA_SECTOR);
+
+    /* Check for a bad status.  */
+    if (status != FX_SUCCESS)
+    {
+
+        /* Return the bad status.  */
+        return(status);
+    }
+
+    /* Flush the internal logical sector cache.  */
+    status =  _fx_utility_logical_sector_flush(media_ptr, (ULONG64) start_sector, ((ULONG64) 1), FX_FALSE);
+
+    FX_FAULT_TOLERANT_WRITE_LOG_FILE_EXTENSION
+
+    /* Return the status.  */
+    return(status);
+}
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_allocate.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_allocate.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_allocate.c	(revision 30)
@@ -0,0 +1,84 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_file.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_file_allocate                                   PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function attempts to allocate the number of consecutive        */
+/*    clusters required to satisfy the user's request.  If there are      */
+/*    enough clusters, the clusters are allocated and linked to the file. */
+/*    Otherwise, if there are not enough consecutive clusters, an error   */
+/*    code is returned to the caller.                                     */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    file_ptr                              File control block pointer    */
+/*    size                                  Number of bytes to allocate   */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_file_extended_allocate            Allocate the clusters         */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s), and      */
+/*                                            Added conditional to        */
+/*                                            disable one line function,  */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+#ifndef FX_DISABLE_ONE_LINE_FUNCTION
+UINT  _fx_file_allocate(FX_FILE *file_ptr, ULONG size)
+{
+
+    return(_fx_file_extended_allocate(file_ptr, (ULONG64)size));
+}
+#endif /* FX_DISABLE_ONE_LINE_FUNCTION */
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_attributes_read.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_attributes_read.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_attributes_read.c	(revision 30)
@@ -0,0 +1,169 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_directory.h"
+#include "fx_file.h"
+#include "fx_utility.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_file_attributes_read                            PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function first attempts to find the specified file.  If found, */
+/*    the attribute read request is valid and the directory entry will be */
+/*    in order to pickup the file's attributes.  Otherwise, if the file   */
+/*    is not found, the appropriate error code is returned to the caller. */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    file_name                             File name pointer             */
+/*    attributes_ptr                        Return attributes pointer     */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_search                  Search for the file name in   */
+/*                                          the directory structure       */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_file_attributes_read(FX_MEDIA *media_ptr, CHAR *file_name, UINT *attributes_ptr)
+{
+
+UINT                   status;
+FX_DIR_ENTRY           dir_entry;
+
+#ifdef TX_ENABLE_EVENT_TRACE
+TX_TRACE_BUFFER_ENTRY *trace_event;
+ULONG                  trace_timestamp;
+#endif
+UCHAR                  not_a_file_attr;
+
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of times this service has been called.  */
+    media_ptr -> fx_media_file_attributes_reads++;
+#endif
+
+    /* Setup pointer to media name buffer.  */
+    dir_entry.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
+
+    /* Clear the short name string.  */
+    dir_entry.fx_dir_entry_short_name[0] =  0;
+
+    /* Check the media to make sure it is open.  */
+    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
+    {
+
+        /* Return the media not opened error.  */
+        return(FX_MEDIA_NOT_OPEN);
+    }
+
+#ifdef FX_ENABLE_EXFAT
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+        not_a_file_attr = FX_DIRECTORY;
+    }
+    else
+    {
+#endif /* FX_ENABLE_EXFAT */
+        not_a_file_attr = FX_DIRECTORY | FX_VOLUME;
+#ifdef FX_ENABLE_EXFAT
+    }
+#endif /* FX_ENABLE_EXFAT */
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_FILE_ATTRIBUTES_READ, media_ptr, file_name, 0, 0, FX_TRACE_FILE_EVENTS, &trace_event, &trace_timestamp)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+    /* Search the system for the supplied file name.  */
+    status =  _fx_directory_search(media_ptr, file_name, &dir_entry, FX_NULL, FX_NULL);
+
+    /* Determine if the search was successful.  */
+    if (status != FX_SUCCESS)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the error code.  */
+        return(status);
+    }
+
+    /* Check to make sure the found entry is a file.  */
+    if (dir_entry.fx_dir_entry_attributes & not_a_file_attr)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the not a file error code.  */
+        return(FX_NOT_A_FILE);
+    }
+
+    /* Place the current attributes into the destination.  */
+    *attributes_ptr =  (UINT)dir_entry.fx_dir_entry_attributes;
+
+    /* Update the trace event with the attributes read.  */
+    FX_TRACE_EVENT_UPDATE(trace_event, trace_timestamp, FX_TRACE_FILE_ATTRIBUTES_READ, 0, 0, dir_entry.fx_dir_entry_attributes, 0)
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* File attribute read is complete, return successful status.  */
+    return(FX_SUCCESS);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_attributes_set.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_attributes_set.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_attributes_set.c	(revision 30)
@@ -0,0 +1,243 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_directory.h"
+#include "fx_file.h"
+#include "fx_utility.h"
+#ifdef FX_ENABLE_FAULT_TOLERANT
+#include "fx_fault_tolerant.h"
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_file_attributes_set                             PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function first attempts to find the specified file.  If found, */
+/*    the attribute set request is valid and the directory entry will be  */
+/*    modified with the new attributes.  Otherwise, if the file is not    */
+/*    found, the appropriate error code is returned to the caller.        */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    file_name                             File name pointer             */
+/*    attributes                            New file attributes           */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_entry_write             Write the new directory entry */
+/*    _fx_directory_search                  Search for the file name in   */
+/*                                          the directory structure       */
+/*    _fx_fault_tolerant_transaction_start  Start fault tolerant          */
+/*                                            transaction                 */
+/*    _fx_fault_tolerant_transaction_end    End fault tolerant transaction*/
+/*    _fx_fault_tolerant_recover            Recover FAT chain             */
+/*    _fx_fault_tolerant_reset_log_file     Reset the log file            */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_file_attributes_set(FX_MEDIA *media_ptr, CHAR *file_name, UINT attributes)
+{
+
+UINT         status;
+ULONG        open_count;
+FX_FILE     *search_ptr;
+FX_DIR_ENTRY dir_entry;
+UCHAR        not_a_file_attr;
+
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of times this service has been called.  */
+    media_ptr -> fx_media_file_attributes_sets++;
+#endif
+
+    /* Setup pointer to media name buffer.  */
+    dir_entry.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
+
+    /* Clear the short name string.  */
+    dir_entry.fx_dir_entry_short_name[0] =  0;
+
+    /* Check the media to make sure it is open.  */
+    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
+    {
+
+        /* Return the media not opened error.  */
+        return(FX_MEDIA_NOT_OPEN);
+    }
+#ifdef FX_ENABLE_EXFAT
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+        not_a_file_attr = FX_DIRECTORY;
+    }
+    else
+    {
+#endif /* FX_ENABLE_EXFAT */
+        not_a_file_attr = FX_DIRECTORY | FX_VOLUME;
+#ifdef FX_ENABLE_EXFAT
+    }
+#endif /* FX_ENABLE_EXFAT */
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_FILE_ATTRIBUTES_SET, media_ptr, file_name, attributes, 0, FX_TRACE_FILE_EVENTS, 0, 0)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+    /* Check for write protect at the media level (set by driver).  */
+    if (media_ptr -> fx_media_driver_write_protect)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return write protect error.  */
+        return(FX_WRITE_PROTECT);
+    }
+
+    /* Search the system for the supplied file name.  */
+    status =  _fx_directory_search(media_ptr, file_name, &dir_entry, FX_NULL, FX_NULL);
+
+    /* Determine if the search was successful.  */
+    if (status != FX_SUCCESS)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the error code.  */
+        return(status);
+    }
+
+    /* Check to make sure the found entry is a file.  */
+    if (dir_entry.fx_dir_entry_attributes & not_a_file_attr)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the not a file error code.  */
+        return(FX_NOT_A_FILE);
+    }
+
+    /* Search the opened files to see if this file is currently
+       opened.  */
+    open_count =  media_ptr -> fx_media_opened_file_count;
+    search_ptr =  media_ptr -> fx_media_opened_file_list;
+    while (open_count)
+    {
+
+        /* Look at each opened file to see if the same file is opened.  */
+        if ((search_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector == dir_entry.fx_dir_entry_log_sector) &&
+            (search_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset == dir_entry.fx_dir_entry_byte_offset))
+        {
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* The file is currently open.  */
+            return(FX_ACCESS_ERROR);
+        }
+
+        /* Adjust the pointer and decrement the search count.  */
+        search_ptr =  search_ptr -> fx_file_opened_next;
+        open_count--;
+    }
+
+    /* Place the new attributes in the directory entry.  */
+    dir_entry.fx_dir_entry_attributes =  (UCHAR)attributes;
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    /* Start transaction. */
+    _fx_fault_tolerant_transaction_start(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Now write out the directory entry.  */
+#ifdef FX_ENABLE_EXFAT
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+        status = _fx_directory_exFAT_entry_write(media_ptr, &dir_entry, UPDATE_FILE);
+    }
+    else
+    {
+#endif /* FX_ENABLE_EXFAT */
+        status = _fx_directory_entry_write(media_ptr, &dir_entry);
+#ifdef FX_ENABLE_EXFAT
+    }
+#endif /* FX_ENABLE_EXFAT */
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    /* Check for a bad status.  */
+    if (status != FX_SUCCESS)
+    {
+
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the bad status.  */
+        return(status);
+    }
+
+    /* End transaction. */
+    status = _fx_fault_tolerant_transaction_end(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* File attribute set is complete, return status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_best_effort_allocate.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_best_effort_allocate.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_best_effort_allocate.c	(revision 30)
@@ -0,0 +1,97 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_file.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_file_best_effort_allocate                       PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function attempts to allocate the number of consecutive        */
+/*    clusters required to satisfy the user's request.  If there are not  */
+/*    enough clusters, the largest set of clusters are allocated and      */
+/*    linked to the file.  If there are no free clusters, an error        */
+/*    code is returned to the caller.                                     */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    file_ptr                              File control block pointer    */
+/*    size                                  Number of bytes to allocate   */
+/*    actual_size_allocated                 Number of bytes allocated     */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_file_extended_best_effort_allocate                              */
+/*                                          Allocate the largest set of   */
+/*                                            clusters                    */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_file_best_effort_allocate(FX_FILE *file_ptr, ULONG size, ULONG *actual_size_allocated)
+{
+
+UINT    status;
+ULONG64 temp_actual_size_allocated;
+
+    /* Call actual best effort file allocate service.  */
+    status = _fx_file_extended_best_effort_allocate(file_ptr, (ULONG64)size, &temp_actual_size_allocated);
+
+    /* Check status.  */
+    if (status == FX_SUCCESS)
+    {
+        *actual_size_allocated = (ULONG)temp_actual_size_allocated;
+    }
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_close.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_close.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_close.c	(revision 30)
@@ -0,0 +1,198 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_file.h"
+#include "fx_utility.h"
+#include "fx_directory.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_file_close                                      PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function closes the specified file.  If the file was written   */
+/*    to this function will also write the directory entry (with the new  */
+/*    size and time/date stamp) out to disk.                              */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    file_ptr                              File control block pointer    */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_entry_write             Write the directory entry     */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_file_close(FX_FILE *file_ptr)
+{
+
+UINT      status;
+FX_MEDIA *media_ptr;
+FX_INT_SAVE_AREA
+
+
+    /* First, determine if the file is still open.  */
+    if (file_ptr -> fx_file_id != FX_FILE_ID)
+    {
+
+        /* Return the file not open error status.  */
+        return(FX_NOT_OPEN);
+    }
+
+    /* Setup a pointer to the associated media.  */
+    media_ptr =  file_ptr -> fx_file_media_ptr;
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of times this service has been called.  */
+    media_ptr -> fx_media_file_closes++;
+#endif
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_FILE_CLOSE, file_ptr, file_ptr -> fx_file_current_file_size, 0, 0, FX_TRACE_FILE_EVENTS, 0, 0)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+    /* If trace is enabled, unregister this object.  */
+    FX_TRACE_OBJECT_UNREGISTER(file_ptr)
+
+    /* Remove this file from the opened list for the media.  */
+
+    /* See if the file is the only one on the open list for this media.  */
+    if (file_ptr == file_ptr -> fx_file_opened_next)
+    {
+
+        /* Only opened file, just set the opened list to NULL.  */
+        media_ptr -> fx_media_opened_file_list =  FX_NULL;
+    }
+    else
+    {
+
+        /* Otherwise, not the only opened file, link-up the neighbors.  */
+        (file_ptr -> fx_file_opened_next) -> fx_file_opened_previous =
+            file_ptr -> fx_file_opened_previous;
+        (file_ptr -> fx_file_opened_previous) -> fx_file_opened_next =
+            file_ptr -> fx_file_opened_next;
+
+        /* See if we have to update the opened list head pointer.  */
+        if (media_ptr -> fx_media_opened_file_list == file_ptr)
+        {
+
+            /* Yes, move the head pointer to the next opened file. */
+            media_ptr -> fx_media_opened_file_list =  file_ptr -> fx_file_opened_next;
+        }
+    }
+
+    /* Decrement the opened file counter.  */
+    media_ptr -> fx_media_opened_file_count--;
+
+    /* Finally, Indicate that this file is closed.  */
+    file_ptr -> fx_file_id =  FX_FILE_CLOSED_ID;
+
+    /* Check to see if this file needs to have its directory entry written
+       back to the media.  */
+    if ((file_ptr -> fx_file_open_mode == FX_OPEN_FOR_WRITE) &&
+        (file_ptr -> fx_file_modified))
+    {
+
+        /* Lockout interrupts for time/date access.  */
+        FX_DISABLE_INTS
+
+        /* Set the new time and date.  */
+        file_ptr -> fx_file_dir_entry.fx_dir_entry_time =  _fx_system_time;
+        file_ptr -> fx_file_dir_entry.fx_dir_entry_date =  _fx_system_date;
+
+        /* Set the last access date.  */
+        file_ptr -> fx_file_dir_entry.fx_dir_entry_last_accessed_date =  _fx_system_date;
+
+        /* Restore interrupts.  */
+        FX_RESTORE_INTS
+
+        /* Copy the new file size into the directory entry.  */
+        file_ptr -> fx_file_dir_entry.fx_dir_entry_file_size =
+            file_ptr -> fx_file_current_file_size;
+
+        /* Write the directory entry to the media.  */
+#ifdef FX_ENABLE_EXFAT
+        if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+        {
+            status = _fx_directory_exFAT_entry_write(
+                    media_ptr, &(file_ptr -> fx_file_dir_entry), UPDATE_STREAM);
+        }
+        else
+        {
+#endif /* FX_ENABLE_EXFAT */
+            status = _fx_directory_entry_write(media_ptr, &(file_ptr -> fx_file_dir_entry));
+#ifdef FX_ENABLE_EXFAT
+        }
+#endif /* FX_ENABLE_EXFAT */
+
+        /* Check for a good status.  */
+        if (status != FX_SUCCESS)
+        {
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* Error writing the directory.  */
+            return(status);
+        }
+    }
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* Return status to the caller.  */
+    return(FX_SUCCESS);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_create.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_create.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_create.c	(revision 30)
@@ -0,0 +1,392 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_directory.h"
+#include "fx_file.h"
+#include "fx_utility.h"
+#ifdef FX_ENABLE_FAULT_TOLERANT
+#include "fx_fault_tolerant.h"
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_file_create                                     PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function first attempts to find the specified file.  If found, */
+/*    the create request is invalid and an error is returned to the       */
+/*    caller.  After the file name verification is made, a search for a   */
+/*    free directory entry will be made.  If nothing is available, an     */
+/*    error will be returned to the caller.  Otherwise, if all is okay, a */
+/*    file of 0 bytes will be created.                                    */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    file_name                             File name                     */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_entry_write             Write the new directory entry */
+/*    _fx_directory_name_extract            Extract directory name        */
+/*    _fx_directory_search                  Search for the file name in   */
+/*                                          the directory structure       */
+/*    _fx_directory_free_search             Search for a free directory   */
+/*                                            entry                       */
+/*    _fx_fault_tolerant_transaction_start  Start fault tolerant          */
+/*                                            transaction                 */
+/*    _fx_fault_tolerant_transaction_end    End fault tolerant transaction*/
+/*    _fx_fault_tolerant_recover            Recover FAT chain             */
+/*    _fx_fault_tolerant_reset_log_file     Reset the log file            */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_file_create(FX_MEDIA *media_ptr, CHAR *file_name)
+{
+
+FX_INT_SAVE_AREA
+
+UINT         status;
+CHAR        *name_ptr;
+UINT         i;
+CHAR        *work_ptr;
+FX_DIR_ENTRY dir_entry;
+FX_DIR_ENTRY search_directory;
+#ifdef FX_ENABLE_EXFAT
+ULONG64      dir_size;
+#endif /* FX_ENABLE_EXFAT */
+
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of times this service has been called.  */
+    media_ptr -> fx_media_file_creates++;
+#endif
+
+    /* Determine if the supplied name is less than the maximum supported name size. The
+       maximum name (FX_MAX_LONG_NAME_LEN) is defined in fx_api.h.  */
+    i =  0;
+    work_ptr =  (CHAR *)file_name;
+    while (*work_ptr)
+    {
+
+        /* Determine if the character designates a new path.  */
+        if ((*work_ptr == '\\') || (*work_ptr == '/'))
+        {
+            /* Yes, reset the name size.  */
+            i =  0;
+        }
+        /* Check for leading spaces.  */
+        else if ((*work_ptr != ' ') || (i != 0))
+        {
+
+            /* No leading spaces, increment the name size.  */
+            i++;
+        }
+
+        /* Move to the next character.  */
+        work_ptr++;
+    }
+
+    /* Determine if the supplied name is valid.  */
+    if ((i == 0) || (i >= FX_MAX_LONG_NAME_LEN))
+    {
+
+        /* Return an invalid name value.  */
+        return(FX_INVALID_NAME);
+    }
+
+    /* Setup pointer to media name buffer.  */
+    dir_entry.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
+
+    /* Setup another pointer to another media name buffer.  */
+    search_directory.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN * 2;
+
+    /* Clear the short name strings.  */
+    dir_entry.fx_dir_entry_short_name[0] =        0;
+    search_directory.fx_dir_entry_short_name[0] = 0;
+
+    /* Check the media to make sure it is open.  */
+    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
+    {
+
+        /* Return the media not opened error.  */
+        return(FX_MEDIA_NOT_OPEN);
+    }
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_FILE_CREATE, media_ptr, file_name, 0, 0, FX_TRACE_FILE_EVENTS, 0, 0)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    /* Start transaction. */
+    _fx_fault_tolerant_transaction_start(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Check for write protect at the media level (set by driver).  */
+    if (media_ptr -> fx_media_driver_write_protect)
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return write protect error.  */
+        return(FX_WRITE_PROTECT);
+    }
+
+    /* Search the system for the supplied file name.  */
+    status =  _fx_directory_search(media_ptr, file_name, &dir_entry, &search_directory, &name_ptr);
+
+    /* Determine if the search was successful.  */
+    if (status == FX_SUCCESS)
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* File found - Return the error code.  */
+        return(FX_ALREADY_CREATED);
+    }
+
+    /* Determine if there is anything left after the name.  */
+    if (_fx_directory_name_extract(name_ptr, &dir_entry.fx_dir_entry_name[0]))
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Extra information after the file name, return an invalid path
+           error.  */
+        return(FX_INVALID_PATH);
+    }
+
+#ifdef FX_ENABLE_EXFAT
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+        if (((dir_entry.fx_dir_entry_name[0] == '.') && (dir_entry.fx_dir_entry_name[1] == 0)) ||
+            ((dir_entry.fx_dir_entry_name[0] == '.') && (dir_entry.fx_dir_entry_name[1] == '.') && (dir_entry.fx_dir_entry_name[2] == 0)))
+        {
+#ifdef FX_ENABLE_FAULT_TOLERANT
+            FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* We don't need '.' or '..' for exFAT */
+            return(FX_ALREADY_CREATED);
+        }
+    }
+
+    /* Save the directory entry size.  */
+    dir_size = search_directory.fx_dir_entry_file_size;
+#endif /* FX_ENABLE_EXFAT */
+
+    /* Find a free slot for the new file.  */
+    status =  _fx_directory_free_search(media_ptr, &search_directory, &dir_entry);
+
+    /* Determine if the search was successful.  */
+    if (status != FX_SUCCESS)
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the error code.  */
+        return(status);
+    }
+
+    /* Populate the directory entry.  */
+
+    /* Isolate the file name.  */
+    _fx_directory_name_extract(name_ptr, &dir_entry.fx_dir_entry_name[0]);
+
+    /* Disable interrupts for time/date access.  */
+    FX_DISABLE_INTS
+
+    /* Set time and date stamps.  */
+    dir_entry.fx_dir_entry_time =  _fx_system_time;
+    dir_entry.fx_dir_entry_date =  _fx_system_date;
+
+    /* Restore interrupts.  */
+    FX_RESTORE_INTS
+
+    /* Set the attributes for the file.  */
+    dir_entry.fx_dir_entry_attributes =  FX_ARCHIVE;
+
+    /* Set file size to 0. */
+    dir_entry.fx_dir_entry_file_size =  0;
+
+#ifdef FX_ENABLE_EXFAT
+    /* Set available file size to 0. */
+    dir_entry.fx_dir_entry_available_file_size = 0;
+#endif /* FX_ENABLE_EXFAT */
+
+    /* Set the cluster to NULL.  */
+    dir_entry.fx_dir_entry_cluster =    FX_NULL;
+
+    /* Is there a leading dot?  */
+    if (dir_entry.fx_dir_entry_name[0] == '.')
+    {
+
+        /* Yes, toggle the hidden attribute bit.  */
+        dir_entry.fx_dir_entry_attributes |=  FX_HIDDEN;
+    }
+
+#ifdef FX_ENABLE_EXFAT
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+
+        /* Don't use FAT by default.  */
+        dir_entry.fx_dir_entry_dont_use_fat = (CHAR)(((search_directory.fx_dir_entry_dont_use_fat & 1) << 1) | 1);
+
+        if (search_directory.fx_dir_entry_name[0])
+        {
+
+            /* Not root directory.  */
+            /* Copy the date and time from the actual sub-directory.  */
+            search_directory.fx_dir_entry_time = dir_entry.fx_dir_entry_time;
+            search_directory.fx_dir_entry_date = dir_entry.fx_dir_entry_date;
+
+            /* Check if the directory size has changed.  */
+            if (search_directory.fx_dir_entry_file_size == dir_size)
+            {
+
+                /* Not changed, we need only update time stamps.  */
+                status = _fx_directory_exFAT_entry_write(media_ptr, &search_directory, UPDATE_FILE);
+            }
+            else
+            {
+
+                /* Directory size changed, update time stamps and the stream size.  */
+                status = _fx_directory_exFAT_entry_write(media_ptr, &search_directory, UPDATE_STREAM);
+            }
+
+            /* Check for a bad status.  */
+            if (status != FX_SUCCESS)
+            {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* Return the bad status.  */
+                return(status);
+            }
+        }
+    }
+    else
+    {
+        dir_entry.fx_dir_entry_dont_use_fat = 0;
+    }
+#endif /* FX_ENABLE_EXFAT */
+
+    /* Now write out the directory entry.  */
+#ifdef FX_ENABLE_EXFAT
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+        status = _fx_directory_exFAT_entry_write(media_ptr, &dir_entry, UPDATE_FULL);
+    }
+    else
+    {
+#endif /* FX_ENABLE_EXFAT */
+        status = _fx_directory_entry_write(media_ptr, &dir_entry);
+#ifdef FX_ENABLE_EXFAT
+    }
+#endif /* FX_ENABLE_EXFAT */
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    /* Check for a bad status.  */
+    if (status != FX_SUCCESS)
+    {
+
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the bad status.  */
+        return(status);
+    }
+
+    /* End transaction. */
+    status = _fx_fault_tolerant_transaction_end(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* File create is complete, return status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_date_time_set.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_date_time_set.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_date_time_set.c	(revision 30)
@@ -0,0 +1,148 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_directory.h"
+#include "fx_file.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_file_date_time_set                              PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function sets the specified file's date and time with the      */
+/*    values provided.                                                    */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    file_name                             File name pointer             */
+/*    year                                  Year                          */
+/*    month                                 Month                         */
+/*    day                                   Day                           */
+/*    hour                                  Hour                          */
+/*    minute                                Minute                        */
+/*    second                                Second                        */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_search                  Search for the file name in   */
+/*                                          the directory structure       */
+/*    _fx_directory_entry_write             Write the directory entry     */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_file_date_time_set(FX_MEDIA *media_ptr, CHAR *file_name,
+                             UINT year, UINT month, UINT day, UINT hour, UINT minute, UINT second)
+{
+
+UINT         status;
+FX_DIR_ENTRY dir_entry;
+
+
+    /* Setup pointer to media name buffer.  */
+    dir_entry.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
+
+    /* Clear the short name string.  */
+    dir_entry.fx_dir_entry_short_name[0] =  0;
+
+    /* Check the media to make sure it is open.  */
+    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
+    {
+
+        /* Return the media not opened error.  */
+        return(FX_MEDIA_NOT_OPEN);
+    }
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_FILE_DATE_TIME_SET, media_ptr, file_name, year, month, FX_TRACE_FILE_EVENTS, 0, 0)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+    /* Search the system for the supplied directory name.  */
+    status =  _fx_directory_search(media_ptr, file_name, &dir_entry, FX_NULL, FX_NULL);
+
+    /* Determine if the search was successful.  */
+    if (status != FX_SUCCESS)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the error code.  */
+        return(status);
+    }
+
+    /* Set the new time and date.  */
+    dir_entry.fx_dir_entry_time =  (hour << FX_HOUR_SHIFT) | (minute << FX_MINUTE_SHIFT) | (second / 2);
+    dir_entry.fx_dir_entry_date =  ((year - FX_BASE_YEAR) << FX_YEAR_SHIFT) | (month << FX_MONTH_SHIFT) | day;
+
+    /* Write the directory entry to the media.  */
+#ifdef FX_ENABLE_EXFAT
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+        status = _fx_directory_exFAT_entry_write(media_ptr, &dir_entry, UPDATE_FILE);
+    }
+    else
+    {
+#endif /* FX_ENABLE_EXFAT */
+        status = _fx_directory_entry_write(media_ptr, &dir_entry);
+#ifdef FX_ENABLE_EXFAT
+    }
+#endif /* FX_ENABLE_EXFAT */
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* Directory information write is complete, return status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_delete.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_delete.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_delete.c	(revision 30)
@@ -0,0 +1,477 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_directory.h"
+#include "fx_file.h"
+#include "fx_utility.h"
+#ifdef FX_ENABLE_FAULT_TOLERANT
+#include "fx_fault_tolerant.h"
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_file_delete                                     PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function first attempts to find the specified file.  If found, */
+/*    the delete request is valid and all of its clusters will be         */
+/*    released and its directory entry will be marked as available.       */
+/*    Otherwise, if the file is not found, the appropriate error code is  */
+/*    returned to the caller.                                             */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    file_name                             File name pointer             */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_entry_write             Write the new directory entry */
+/*    _fx_directory_search                  Search for the file name in   */
+/*                                          the directory structure       */
+/*    _fx_utility_exFAT_cluster_state_set   Set cluster state             */
+/*    _fx_utility_FAT_entry_read            Read a FAT entry              */
+/*    _fx_utility_FAT_entry_write           Write a FAT entry             */
+/*    _fx_utility_FAT_flush                 Flush written FAT entries     */
+/*    _fx_fault_tolerant_transaction_start  Start fault tolerant          */
+/*                                            transaction                 */
+/*    _fx_fault_tolerant_transaction_end    End fault tolerant transaction*/
+/*    _fx_fault_tolerant_recover            Recover FAT chain             */
+/*    _fx_fault_tolerant_reset_log_file     Reset the log file            */
+/*    _fx_fault_tolerant_set_FAT_chain      Set data of FAT chain         */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_file_delete(FX_MEDIA *media_ptr, CHAR *file_name)
+{
+
+UINT         status;
+ULONG        cluster;
+ULONG        contents;
+ULONG        open_count;
+FX_FILE     *search_ptr;
+ULONG        cluster_count;
+FX_DIR_ENTRY dir_entry;
+UCHAR        not_a_file_attr;
+#ifdef FX_ENABLE_EXFAT
+ULONG        bytes_per_cluster;
+ULONG        clusters_count;
+#endif /* FX_ENABLE_EXFAT */
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of times this service has been called.  */
+    media_ptr -> fx_media_file_deletes++;
+#endif
+
+    /* Setup pointer to media name buffer.  */
+    dir_entry.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
+
+    /* Clear the short name string.  */
+    dir_entry.fx_dir_entry_short_name[0] =  0;
+
+    /* Check the media to make sure it is open.  */
+    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
+    {
+
+        /* Return the media not opened error.  */
+        return(FX_MEDIA_NOT_OPEN);
+    }
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_FILE_DELETE, media_ptr, file_name, 0, 0, FX_TRACE_FILE_EVENTS, 0, 0)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    /* Start transaction. */
+    _fx_fault_tolerant_transaction_start(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Check for write protect at the media level (set by driver).  */
+    if (media_ptr -> fx_media_driver_write_protect)
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return write protect error.  */
+        return(FX_WRITE_PROTECT);
+    }
+
+    /* Search the system for the supplied file name.  */
+    status =  _fx_directory_search(media_ptr, file_name, &dir_entry, FX_NULL, FX_NULL);
+
+    /* Determine if the search was successful.  */
+    if (status != FX_SUCCESS)
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the error code.  */
+        return(status);
+    }
+
+#ifdef FX_ENABLE_EXFAT
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+        not_a_file_attr = FX_DIRECTORY;
+    }
+    else
+    {
+#endif /* FX_ENABLE_EXFAT */
+        not_a_file_attr = FX_DIRECTORY | FX_VOLUME;
+#ifdef FX_ENABLE_EXFAT
+    }
+#endif /* FX_ENABLE_EXFAT */
+
+    /* Check to make sure the found entry is a file.  */
+    if (dir_entry.fx_dir_entry_attributes & not_a_file_attr)
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the not a file error code.  */
+        return(FX_NOT_A_FILE);
+    }
+
+    /* Check if the entry is read only */
+    if (dir_entry.fx_dir_entry_attributes & (UCHAR)(FX_READ_ONLY))
+    {
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the not a directory error code.  */
+        return(FX_WRITE_PROTECT);
+    }
+
+    /* Search the opened files to see if this file is currently
+       opened.  */
+    open_count =  media_ptr -> fx_media_opened_file_count;
+    search_ptr =  media_ptr -> fx_media_opened_file_list;
+    while (open_count)
+    {
+
+        /* Look at each opened file to see if the same file is opened.  */
+        if ((search_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector == dir_entry.fx_dir_entry_log_sector) &&
+            (search_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset == dir_entry.fx_dir_entry_byte_offset))
+        {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+            FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* The file is currently open.  */
+            return(FX_ACCESS_ERROR);
+        }
+
+        /* Adjust the pointer and decrement the search count.  */
+        search_ptr =  search_ptr -> fx_file_opened_next;
+        open_count--;
+    }
+
+    /* Pickup the starting cluster of the file.  */
+    cluster =           dir_entry.fx_dir_entry_cluster;
+
+    /* At this point, make the directory entry invalid in order to delete the file.  */
+
+#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
+
+    /* Invalidate the directory search saved information.  */
+    media_ptr -> fx_media_last_found_name[0] =  FX_NULL;
+#endif
+
+    /* Mark the directory entry as available, while leaving the other
+       information for the sake of posterity.  */
+    dir_entry.fx_dir_entry_name[0] =        (CHAR)FX_DIR_ENTRY_FREE;
+    dir_entry.fx_dir_entry_short_name[0] =  (CHAR)FX_DIR_ENTRY_FREE;
+
+    /* Now write out the directory entry.  */
+#ifdef FX_ENABLE_EXFAT
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+        status = _fx_directory_exFAT_entry_write(media_ptr, &dir_entry, UPDATE_DELETE);
+    }
+    else
+    {
+#endif /* FX_ENABLE_EXFAT */
+        status = _fx_directory_entry_write(media_ptr, &dir_entry);
+#ifdef FX_ENABLE_EXFAT
+    }
+#endif /* FX_ENABLE_EXFAT */
+
+    /* Determine if the write was successful.  */
+    if (status != FX_SUCCESS)
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the error code.  */
+        return(status);
+    }
+
+    /* Now that the directory entry is no longer valid and pointing at the chain of clusters,
+       walk the chain of allocated FAT entries and mark each of them as free.  */
+    cluster_count =     0;
+
+#ifdef FX_ENABLE_EXFAT
+    bytes_per_cluster =  ((ULONG)media_ptr -> fx_media_bytes_per_sector) *
+        ((ULONG)media_ptr -> fx_media_sectors_per_cluster);
+
+    clusters_count =
+        (ULONG)((dir_entry.fx_dir_entry_file_size + bytes_per_cluster - 1) / bytes_per_cluster - 1);
+#endif /* FX_ENABLE_EXFAT */
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    if (media_ptr -> fx_media_fault_tolerant_enabled)
+    {
+
+        /* Note:  Directory entries are already written to log files. FAT chain is updated as the last step.
+           Since there are no others FAT entries written to the log.  Therefore there is no need to set
+           the flag FX_FRAULT_TOLERANT_STATE_SET_FAT_CHAIN here. */
+#ifdef FX_ENABLE_EXFAT
+        if (dir_entry.fx_dir_entry_dont_use_fat & 1)
+        {
+            status = _fx_fault_tolerant_set_FAT_chain(media_ptr, FX_TRUE, 0,
+                                                      media_ptr -> fx_media_fat_last, cluster, cluster + clusters_count);
+        }
+        else
+        {
+#endif /* FX_ENABLE_EXFAT */
+            status = _fx_fault_tolerant_set_FAT_chain(media_ptr, FX_FALSE, 0,
+                                                      media_ptr -> fx_media_fat_last, cluster, media_ptr -> fx_media_fat_last);
+#ifdef FX_ENABLE_EXFAT
+        }
+#endif /* FX_ENABLE_EXFAT */
+
+        /* Determine if the write was successful.  */
+        if (status != FX_SUCCESS)
+        {
+
+            FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* Return the error code.  */
+            return(status);
+        }
+    }
+    else
+    {
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Follow the link of FAT entries.  */
+        while ((cluster >= FX_FAT_ENTRY_START) && (cluster < media_ptr -> fx_media_fat_reserved))
+        {
+
+            /* Increment the number of clusters.  */
+            cluster_count++;
+
+#ifdef FX_ENABLE_EXFAT
+            if (dir_entry.fx_dir_entry_dont_use_fat & 1)
+            {
+
+                /* Check for file size range.  */
+                if (cluster_count - 1 >= clusters_count)
+                {
+                    contents = FX_LAST_CLUSTER_exFAT;
+                }
+                else
+                {
+                    contents = cluster + 1;
+                }
+            }
+            else
+            {
+#endif /* FX_ENABLE_EXFAT */
+
+                /* Read the current cluster entry from the FAT.  */
+                status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &contents);
+
+                /* Check the return value.  */
+                if (status != FX_SUCCESS)
+                {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                    FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                    /* Release media protection.  */
+                    FX_UNPROTECT
+
+                    /* Return the error status.  */
+                    return(status);
+                }
+#ifdef FX_ENABLE_EXFAT
+            }
+#endif /* FX_ENABLE_EXFAT */
+
+            if ((cluster == contents) || (cluster_count > media_ptr -> fx_media_total_clusters))
+            {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* Return the bad status.  */
+                return(FX_FAT_READ_ERROR);
+            }
+
+#ifdef FX_ENABLE_EXFAT
+            if (!(dir_entry.fx_dir_entry_dont_use_fat & 1))
+            {
+#endif /* FX_ENABLE_EXFAT */
+
+                /* Make the current cluster available.  */
+                status =  _fx_utility_FAT_entry_write(media_ptr, cluster, FX_FREE_CLUSTER);
+
+                /* Check the return value.  */
+                if (status != FX_SUCCESS)
+                {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                    FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                    /* Release media protection.  */
+                    FX_UNPROTECT
+
+                    /* Return the error status.  */
+                    return(status);
+                }
+#ifdef FX_ENABLE_EXFAT
+            }
+
+            if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+            {
+
+                /* Mark the cluster as free.  */
+                status = _fx_utility_exFAT_cluster_state_set(media_ptr, cluster, FX_EXFAT_BITMAP_CLUSTER_FREE);
+
+                /* Check the return status.  */
+                if (status != FX_SUCCESS)
+                {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                    FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                    /* Release media protection.  */
+                    FX_UNPROTECT
+
+                    /* Return the bad status.  */
+                    return(status);
+                }
+            }
+#endif /* FX_ENABLE_EXFAT */
+
+            /* Setup for the next cluster.  */
+            cluster =  contents;
+        }
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    }
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Update the free clusters in the media control block.  */
+    media_ptr -> fx_media_available_clusters =
+        media_ptr -> fx_media_available_clusters + cluster_count;
+
+#ifdef FX_FAULT_TOLERANT
+
+    /* Flush the cached individual FAT entries */
+    _fx_utility_FAT_flush(media_ptr);
+#endif
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+
+    /* End transaction. */
+    status = _fx_fault_tolerant_transaction_end(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* File delete is complete, return status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_extended_allocate.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_extended_allocate.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_extended_allocate.c	(revision 30)
@@ -0,0 +1,871 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_file.h"
+#include "fx_utility.h"
+#include "fx_directory.h"
+#ifdef FX_ENABLE_FAULT_TOLERANT
+#include "fx_fault_tolerant.h"
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_file_extended_allocate                          PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function attempts to allocate the number of consecutive        */
+/*    clusters required to satisfy the user's request.  If there are      */
+/*    enough clusters, the clusters are allocated and linked to the file. */
+/*    Otherwise, if there are not enough consecutive clusters, an error   */
+/*    code is returned to the caller.                                     */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    file_ptr                              File control block pointer    */
+/*    size                                  Number of bytes to allocate   */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_entry_write             Update directory entry        */
+/*    _fx_utility_exFAT_bitmap_flush        Flush exFAT allocation bitmap */
+/*    _fx_utility_exFAT_bitmap_free_cluster_find                          */
+/*                                            Find exFAT free cluster     */
+/*    _fx_utility_exFAT_cluster_state_get   Get cluster state             */
+/*    _fx_utility_exFAT_cluster_state_set   Set cluster state             */
+/*    _fx_utility_FAT_entry_read            Read a FAT entry              */
+/*    _fx_utility_FAT_entry_write           Write a FAT entry             */
+/*    _fx_utility_FAT_flush                 Flush written FAT entries     */
+/*    _fx_utility_logical_sector_flush      Flush the written log sector  */
+/*    _fx_fault_tolerant_transaction_start  Start fault tolerant          */
+/*                                            transaction                 */
+/*    _fx_fault_tolerant_transaction_end    End fault tolerant transaction*/
+/*    _fx_fault_tolerant_recover            Recover FAT chain             */
+/*    _fx_fault_tolerant_reset_log_file     Reset the log file            */
+/*    _fx_fault_tolerant_set_FAT_chain      Set data of FAT chain         */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_file_extended_allocate(FX_FILE *file_ptr, ULONG64 size)
+{
+
+UINT                   status;
+ULONG                  i;
+UINT                   found;
+ULONG                  bytes_per_cluster;
+ULONG                  FAT_index;
+ULONG                  FAT_value;
+ULONG                  clusters;
+FX_MEDIA              *media_ptr;
+#ifdef FX_ENABLE_EXFAT
+UCHAR                  cluster_state;
+#endif /* FX_ENABLE_EXFAT */
+
+#ifdef TX_ENABLE_EVENT_TRACE
+TX_TRACE_BUFFER_ENTRY *trace_event;
+ULONG                  trace_timestamp;
+#endif
+
+
+    /* First, determine if the file is still open.  */
+    if (file_ptr -> fx_file_id != FX_FILE_ID)
+    {
+
+        /* Return the file not open error status.  */
+        return(FX_NOT_OPEN);
+    }
+
+    /* Setup pointer to media structure.  */
+    media_ptr =  file_ptr -> fx_file_media_ptr;
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of times this service has been called.  */
+    media_ptr -> fx_media_file_allocates++;
+#endif
+
+    /* Make sure this file is open for writing.  */
+    if (file_ptr -> fx_file_open_mode != FX_OPEN_FOR_WRITE)
+    {
+
+        /* Return the access error exception - a write was attempted from
+           a file opened for reading!  */
+        return(FX_ACCESS_ERROR);
+    }
+
+    /* Determine if the requested allocation is for zero bytes.  */
+    if (size == 0)
+    {
+
+        /* Return a successful completion - nothing needs to be done.  */
+        return(FX_SUCCESS);
+    }
+
+    /* Setup pointer to associated media control block.  */
+    media_ptr =  file_ptr -> fx_file_media_ptr;
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_FILE_ALLOCATE, file_ptr, size, file_ptr -> fx_file_current_available_size, 0, FX_TRACE_FILE_EVENTS, &trace_event, &trace_timestamp)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    /* Start transaction. */
+    _fx_fault_tolerant_transaction_start(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Check for write protect at the media level (set by driver).  */
+    if (media_ptr -> fx_media_driver_write_protect)
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return write protect error.  */
+        return(FX_WRITE_PROTECT);
+    }
+
+    /* Calculate the number of bytes per cluster.  */
+    bytes_per_cluster =  ((ULONG)media_ptr -> fx_media_bytes_per_sector) *
+        ((ULONG)media_ptr -> fx_media_sectors_per_cluster);
+
+    /* Check for invalid value.  */
+    if (bytes_per_cluster == 0)
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Invalid media, return error.  */
+        return(FX_MEDIA_INVALID);
+    }
+
+    /* Calculate the number of consecutive clusters needed to satisfy this
+       request.  */
+    clusters =  (ULONG)(((size + bytes_per_cluster - 1) / bytes_per_cluster));
+
+    /* Determine if cluster count is 0.  */
+    if (clusters == 0)
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Size overflow when rounding to the next cluster, return an error status.  */
+        return(FX_NO_MORE_SPACE);
+    }
+
+    /* Determine if there are enough available clusters on the media.  */
+    if (clusters > media_ptr -> fx_media_available_clusters)
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Not enough clusters, return an error status.  */
+        return(FX_NO_MORE_SPACE);
+    }
+
+    /* Determine if the requested file allocation would exceed the physical limit of the file.  */
+    if (((file_ptr -> fx_file_current_available_size + (((ULONG64) clusters) * ((ULONG64) bytes_per_cluster))) < file_ptr -> fx_file_current_available_size) ||
+        ((file_ptr -> fx_file_current_available_size + (((ULONG64) clusters) * ((ULONG64) bytes_per_cluster))) > 0xFFFFFFFFULL))
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the no more space error, since the new file size would be larger than
+           the 32-bit field to represent it in the file's directory entry.  */
+        return(FX_NO_MORE_SPACE);
+    }
+
+    /* Now we need to find the consecutive clusters.  */
+    FAT_index =  FX_FAT_ENTRY_START;
+    found =      FX_FALSE;
+
+#ifdef FX_ENABLE_EXFAT
+    if ((file_ptr -> fx_file_dir_entry.fx_dir_entry_dont_use_fat & 1) &&
+        (file_ptr -> fx_file_last_physical_cluster > FX_FAT_ENTRY_START) &&
+        (file_ptr -> fx_file_last_physical_cluster < media_ptr -> fx_media_total_clusters - clusters + FX_FAT_ENTRY_START))
+    {
+        found = FX_TRUE;
+        /* Try to keep clusters consecutive.  */
+        for (FAT_index = file_ptr -> fx_file_last_physical_cluster + 1;
+             FAT_index < clusters + file_ptr -> fx_file_last_physical_cluster + 1;
+             FAT_index++)
+        {
+
+            /* Get cluster state.  */
+            status = _fx_utility_exFAT_cluster_state_get(media_ptr, FAT_index, &cluster_state);
+
+            /* Check for a successful status.  */
+            if (status != FX_SUCCESS)
+            {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* Return the error status.  */
+                return(status);
+            }
+
+            /* Determine if the entry is free.  */
+            if (cluster_state == FX_EXFAT_BITMAP_CLUSTER_OCCUPIED)
+            {
+                found = FX_FALSE;
+                break;
+            }
+        }
+        FAT_index = file_ptr -> fx_file_last_physical_cluster + 1;
+    }
+
+    if (!found)
+    {
+#endif /* FX_ENABLE_EXFAT */
+
+        while (FAT_index <= (media_ptr -> fx_media_total_clusters - clusters + FX_FAT_ENTRY_START))
+        {
+
+            /* Determine if enough consecutive FAT entries are available.  */
+            i =  0;
+
+#ifdef FX_ENABLE_EXFAT
+            if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+            {
+                do
+                {
+
+                    /* Get cluster state.  */
+                    status = _fx_utility_exFAT_cluster_state_get(media_ptr, (FAT_index + i), &cluster_state);
+
+                    /* Check for a successful status.  */
+                    if (status != FX_SUCCESS)
+                    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                        /* Release media protection.  */
+                        FX_UNPROTECT
+
+                        /* Return the error status.  */
+                        return(status);
+                    }
+
+                    /* Determine if the entry is free.  */
+                    if (cluster_state == FX_EXFAT_BITMAP_CLUSTER_OCCUPIED)
+                    {
+                        break;
+                    }
+
+                    /* Otherwise, increment the consecutive FAT indices.  */
+                    i++;
+                } while (i < clusters);
+            }
+            else
+            {
+#endif /* FX_ENABLE_EXFAT */
+
+                do
+                {
+
+                    /* Read a FAT entry.  */
+                    status =  _fx_utility_FAT_entry_read(media_ptr, (FAT_index + i), &FAT_value);
+
+                    /* Check for a successful status.  */
+                    if (status != FX_SUCCESS)
+                    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                        /* Release media protection.  */
+                        FX_UNPROTECT
+
+                        /* Return the error status.  */
+                        return(status);
+                    }
+
+                    /* Determine if the entry is free.  */
+                    if (FAT_value != FX_FREE_CLUSTER)
+                    {
+                        break;
+                    }
+
+                    /* Otherwise, increment the consecutive FAT indices.  */
+                    i++;
+                } while (i < clusters);
+#ifdef FX_ENABLE_EXFAT
+            }
+#endif /* FX_ENABLE_EXFAT */
+
+            /* Determine if we found enough FAT entries.  */
+            if (i >= clusters)
+            {
+
+                /* Yes, we have found enough FAT entries - set the found
+                   flag and get out of this loop.  */
+                found =  FX_TRUE;
+                break;
+            }
+            else
+            {
+#ifdef FX_ENABLE_EXFAT
+                if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+                {
+
+                    /* Find free cluster from exFAT media.  */
+                    status = _fx_utility_exFAT_bitmap_free_cluster_find(media_ptr,
+                                                                        FAT_index + i + 1,
+                                                                        &FAT_value);
+                    if (status != FX_SUCCESS)
+                    {
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                        /* Release media protection.  */
+                        FX_UNPROTECT
+
+                        /* Return the error status.  */
+                        return(status);
+                    }
+
+                    if (FAT_value < FAT_index + i + 1)
+                    {
+                        /* If we wrapped.  */
+                        FAT_index = media_ptr -> fx_media_total_clusters + FX_FAT_ENTRY_START;
+                    }
+                    else
+                    {
+                        FAT_index = FAT_value;
+                    }
+                }
+                else
+                {
+#endif /* FX_ENABLE_EXFAT */
+                    /* Position to the next possibly free FAT entry.  */
+                    FAT_index =  FAT_index + i + 1;
+#ifdef FX_ENABLE_EXFAT
+                }
+#endif /* FX_ENABLE_EXFAT */
+            }
+        }
+#ifdef FX_ENABLE_EXFAT
+    }
+#endif
+
+    /* Determine if we found enough consecutive clusters to satisfy the
+       request.  */
+    if (found)
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        if (media_ptr -> fx_media_fault_tolerant_enabled)
+        {
+
+            /* Record the action that is about to take place.  This information
+               would aid the undo process should fault condition happens. */
+            media_ptr -> fx_media_fault_tolerant_state |= FX_FAULT_TOLERANT_STATE_SET_FAT_CHAIN;
+            _fx_fault_tolerant_set_FAT_chain(media_ptr, FX_FALSE, file_ptr -> fx_file_last_physical_cluster,
+                                             FAT_index, media_ptr -> fx_media_fat_last, media_ptr -> fx_media_fat_last);
+        }
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+#ifdef FX_ENABLE_EXFAT
+        if (file_ptr -> fx_file_dir_entry.fx_dir_entry_dont_use_fat & 1)
+        {
+            if ((file_ptr -> fx_file_total_clusters) &&
+                (FAT_index != file_ptr -> fx_file_last_physical_cluster + 1))
+            {
+                /* Clusters are not consecutive.  */
+                file_ptr -> fx_file_dir_entry.fx_dir_entry_dont_use_fat &= (CHAR)0xfe; /* Set 0bit to 0 */
+
+                /* Rebuild FAT.  */
+                FAT_value = file_ptr -> fx_file_dir_entry.fx_dir_entry_cluster +
+                            file_ptr -> fx_file_total_clusters - 1; /* Last cluster */
+
+                for (i = file_ptr -> fx_file_dir_entry.fx_dir_entry_cluster; i < FAT_value; ++i)
+                {
+                    status = _fx_utility_FAT_entry_write(media_ptr, i, i + 1);
+                    if (status != FX_SUCCESS)
+                    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                        /* Release media protection.  */
+                        FX_UNPROTECT
+
+                        /* Return the bad status.  */
+                        return(status);
+                    }
+                }
+
+                /* Close chain.  */
+                status = _fx_utility_FAT_entry_write(media_ptr, FAT_value, media_ptr -> fx_media_fat_last);
+                if (status != FX_SUCCESS)
+                {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                    FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                    /* Release media protection.  */
+                    FX_UNPROTECT
+
+                    /* Return the bad status.  */
+                    return(status);
+                }
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                if (media_ptr -> fx_media_fault_tolerant_enabled)
+                {
+
+                    /* Clear undo phase. */
+                    media_ptr -> fx_media_fault_tolerant_state &= (UCHAR)(~FX_FAULT_TOLERANT_STATE_SET_FAT_CHAIN & 0xff);
+                }
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                /* Update stream.  */
+                status = _fx_directory_exFAT_entry_write(
+                        media_ptr, &(file_ptr -> fx_file_dir_entry), UPDATE_STREAM);
+
+                if (status != FX_SUCCESS)
+                {
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                    FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                    /* Release media protection.  */
+                    FX_UNPROTECT
+
+                    /* Return the bad status.  */
+                    return(status);
+                }
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                if (media_ptr -> fx_media_fault_tolerant_enabled)
+                {
+
+                    /* Set undo phase. */
+                    media_ptr -> fx_media_fault_tolerant_state |= FX_FAULT_TOLERANT_STATE_SET_FAT_CHAIN;
+                }
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+            }
+        }
+#endif /* FX_ENABLE_EXFAT */
+
+        /* Update the link pointers in the new clusters.  */
+        for (i = 0; i < (clusters - 1); i++)
+        {
+#ifdef FX_ENABLE_EXFAT
+            if (!(file_ptr -> fx_file_dir_entry.fx_dir_entry_dont_use_fat & 1)
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                || (media_ptr -> fx_media_fault_tolerant_enabled == FX_TRUE)
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+               )
+            {
+#endif /* FX_ENABLE_EXFAT */
+
+                /* Update the cluster links.  Since the allocation is
+                   sequential, we just have to link each FAT entry to the
+                   next one.  */
+                status =  _fx_utility_FAT_entry_write(media_ptr, FAT_index + i, FAT_index + i + 1);
+
+                /* Check for a bad status.  */
+                if (status != FX_SUCCESS)
+                {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                    FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                    /* Release media protection.  */
+                    FX_UNPROTECT
+
+                    /* Return the error status.  */
+                    return(status);
+                }
+#ifdef FX_ENABLE_EXFAT
+            }
+
+            if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+            {
+
+                /* Mark the cluster as used.  */
+                status = _fx_utility_exFAT_cluster_state_set(media_ptr, FAT_index + i, FX_EXFAT_BITMAP_CLUSTER_OCCUPIED);
+
+                /* Check for a bad status.  */
+                if (status != FX_SUCCESS)
+                {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                    FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                    /* Release media protection.  */
+                    FX_UNPROTECT
+
+                    /* Return the error status.  */
+                    return(status);
+                }
+            }
+#endif /* FX_ENABLE_EXFAT */
+        }
+#ifdef FX_ENABLE_EXFAT
+        if (!(file_ptr -> fx_file_dir_entry.fx_dir_entry_dont_use_fat & 1))
+        {
+#endif /* FX_ENABLE_EXFAT */
+
+            /* Now place an EOF in the last cluster entry.  */
+            status =  _fx_utility_FAT_entry_write(media_ptr, FAT_index + clusters - 1, media_ptr -> fx_media_fat_last);
+
+            /* Check for a bad status.  */
+            if (status != FX_SUCCESS)
+            {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* Return the error status.  */
+                return(status);
+            }
+#ifdef FX_ENABLE_EXFAT
+        }
+
+        if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+        {
+
+            /* Mark the cluster as used.  */
+            status = _fx_utility_exFAT_cluster_state_set(media_ptr, FAT_index + clusters - 1, FX_EXFAT_BITMAP_CLUSTER_OCCUPIED);
+
+            /* Check for a bad status.  */
+            if (status != FX_SUCCESS)
+            {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* Return the error status.  */
+                return(status);
+            }
+        }
+#endif /* FX_ENABLE_EXFAT */
+
+#ifdef FX_FAULT_TOLERANT
+
+        /* Flush the cached individual FAT entries */
+        _fx_utility_FAT_flush(media_ptr);
+
+#ifdef FX_ENABLE_EXFAT
+        if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+        {
+            _fx_utility_exFAT_bitmap_flush(media_ptr);
+        }
+#endif /* FX_ENABLE_EXFAT */
+#endif
+
+        /* Actually link up the new clusters to the file.  */
+
+        /* Determine if there are already clusters allocated for this file.  */
+        if (file_ptr -> fx_file_total_clusters)
+        {
+#ifdef FX_ENABLE_EXFAT
+            if (!(file_ptr -> fx_file_dir_entry.fx_dir_entry_dont_use_fat & 1))
+            {
+#endif /* FX_ENABLE_EXFAT */
+
+                /* Linkup the last cluster.  */
+                status =  _fx_utility_FAT_entry_write(media_ptr,
+                                                      file_ptr -> fx_file_last_physical_cluster, FAT_index);
+
+                /* Check for a bad status.  */
+                if (status != FX_SUCCESS)
+                {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                    FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                    /* Release media protection.  */
+                    FX_UNPROTECT
+
+                    /* Return the error status.  */
+                    return(status);
+                }
+#ifdef FX_ENABLE_EXFAT
+            }
+#endif /* FX_ENABLE_EXFAT */
+
+            /* Determine if we are adding a sector after a write filled the previously
+               allocated cluster exactly.  */
+            if ((file_ptr -> fx_file_current_relative_sector >=
+                (media_ptr -> fx_media_sectors_per_cluster - 1)) &&           
+                (file_ptr -> fx_file_current_logical_offset >=
+                 media_ptr -> fx_media_bytes_per_sector))
+            {
+
+                /* Yes, we need to adjust all of the pertinent file parameters for
+                   access into this newly allocated cluster.  */
+                file_ptr -> fx_file_current_physical_cluster =  FAT_index;
+                file_ptr -> fx_file_current_relative_cluster++;
+                file_ptr -> fx_file_current_relative_sector =   0;
+                file_ptr -> fx_file_current_logical_sector =    ((ULONG)media_ptr -> fx_media_data_sector_start) +
+                    (((ULONG64)(FAT_index - FX_FAT_ENTRY_START)) *
+                     ((ULONG)media_ptr -> fx_media_sectors_per_cluster));
+                file_ptr -> fx_file_current_logical_offset =    0;
+            }
+        }
+        else
+        {
+
+            /* These new clusters are also the first!  Setup the initial
+               file parameters.  */
+            file_ptr -> fx_file_first_physical_cluster =    FAT_index;
+            file_ptr -> fx_file_current_physical_cluster =  file_ptr -> fx_file_first_physical_cluster;
+            file_ptr -> fx_file_current_relative_cluster =  0;
+            file_ptr -> fx_file_current_logical_sector =    ((ULONG)media_ptr -> fx_media_data_sector_start) +
+                (((ULONG64)(file_ptr -> fx_file_first_physical_cluster - FX_FAT_ENTRY_START)) *
+                 ((ULONG)media_ptr -> fx_media_sectors_per_cluster));
+            file_ptr -> fx_file_current_logical_offset =    0;
+            file_ptr -> fx_file_current_file_offset =       0;
+
+            /* Update the first cluster in the directory entry.  */
+            file_ptr -> fx_file_dir_entry.fx_dir_entry_cluster =  FAT_index;
+        }
+
+        /* Remember the last physical cluster.  */
+        file_ptr -> fx_file_last_physical_cluster =     FAT_index + clusters - 1;
+
+#ifdef FX_ENABLE_EXFAT
+        if (file_ptr -> fx_file_current_available_size > (file_ptr -> fx_file_current_available_size + (bytes_per_cluster * clusters)))
+        {
+            /* 64-bit wrap around condition is present.  Just set the available file size to all ones, which is
+               the maximum file size.  */
+            file_ptr -> fx_file_current_available_size =  0xFFFFFFFFFFFFFFFFULL;
+        }
+#endif /* FX_ENABLE_EXFAT */
+
+        /* Check for wrap-around when updating the available size.  */
+#ifdef FX_ENABLE_EXFAT
+        if ((media_ptr -> fx_media_FAT_type != FX_exFAT) &&
+            (file_ptr -> fx_file_current_available_size + (bytes_per_cluster * clusters) > 0xFFFFFFFFUL))
+        {
+
+            /* 32-bit wrap around condition is present.  Just set the available file size to all ones, which is
+               the maximum file size.  */
+            file_ptr -> fx_file_current_available_size =  ((ULONG)0xFFFFFFFF);
+        }
+        else
+        {
+
+            /* Normal condition, update the available size.  */
+            file_ptr -> fx_file_current_available_size =
+                file_ptr -> fx_file_current_available_size + (bytes_per_cluster * clusters);
+        }
+#else
+        /* Update the available size.  */
+        file_ptr -> fx_file_current_available_size =
+                file_ptr -> fx_file_current_available_size + (bytes_per_cluster * clusters);
+        
+#endif /* FX_ENABLE_EXFAT */
+
+        /* Increment the total clusters for this file.  */
+        file_ptr -> fx_file_total_clusters =
+            file_ptr -> fx_file_total_clusters + clusters;
+
+        /* Decrease the available clusters on the media.  */
+        media_ptr -> fx_media_available_clusters =
+            media_ptr -> fx_media_available_clusters - clusters;
+
+#if defined(FX_UPDATE_FILE_SIZE_ON_ALLOCATE) || defined(FX_ENABLE_FAULT_TOLERANT)
+
+        /* Set the file size the current size plus what what was added.  */
+        file_ptr -> fx_file_current_file_size +=  size;
+
+        /* Copy the new file size into the directory entry.  */
+        file_ptr -> fx_file_dir_entry.fx_dir_entry_file_size =  file_ptr -> fx_file_current_file_size;
+#endif
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        if (media_ptr -> fx_media_fault_tolerant_enabled)
+        {
+
+            /* Clear undo phase. */
+            media_ptr -> fx_media_fault_tolerant_state &= (UCHAR)(~FX_FAULT_TOLERANT_STATE_SET_FAT_CHAIN & 0xff);
+        }
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Update the trace event with the new size.  */
+        FX_TRACE_EVENT_UPDATE(trace_event, trace_timestamp, FX_TRACE_FILE_ALLOCATE, 0, 0, 0, file_ptr -> fx_file_current_file_size);
+
+        /* Write the directory entry to the media.  */
+#ifdef FX_ENABLE_EXFAT
+        if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+        {
+            status = _fx_directory_exFAT_entry_write(
+                    media_ptr, &(file_ptr -> fx_file_dir_entry), UPDATE_STREAM);
+        }
+        else
+        {
+#endif /* FX_ENABLE_EXFAT */
+            status = _fx_directory_entry_write(media_ptr, &(file_ptr -> fx_file_dir_entry));
+#ifdef FX_ENABLE_EXFAT
+        }
+#endif /* FX_ENABLE_EXFAT */
+
+        /* Check for a good status.  */
+        if (status != FX_SUCCESS)
+        {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+            FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* Return the error status.  */
+            return(status);
+        }
+    }
+    else
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Not enough contiguous space on the media.  Return error status.  */
+        return(FX_NO_MORE_SPACE);
+    }
+
+#ifdef FX_FAULT_TOLERANT
+
+    /* Flush the cached individual FAT entries */
+    _fx_utility_FAT_flush(media_ptr);
+#endif
+
+    /* Flush the internal logical sector cache.  */
+    status =  _fx_utility_logical_sector_flush(media_ptr, ((ULONG64) 1), (ULONG64)(media_ptr -> fx_media_sectors_per_FAT), FX_FALSE);
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    /* Check for a bad status.  */
+    if (status != FX_SUCCESS)
+    {
+
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the bad status.  */
+        return(status);
+    }
+
+    if (media_ptr -> fx_media_fault_tolerant_enabled)
+    {
+
+        /* Copy the new file size into the directory entry.  */
+        file_ptr -> fx_file_dir_entry.fx_dir_entry_file_size = file_ptr -> fx_file_current_file_size;
+    }
+
+    /* End transaction. */
+    status = _fx_fault_tolerant_transaction_end(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_extended_best_effort_allocate.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_extended_best_effort_allocate.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_extended_best_effort_allocate.c	(revision 30)
@@ -0,0 +1,918 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_file.h"
+#include "fx_utility.h"
+#include "fx_directory.h"
+#ifdef FX_ENABLE_FAULT_TOLERANT
+#include "fx_fault_tolerant.h"
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_file_extended_best_effort_allocate              PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function attempts to allocate the number of consecutive        */
+/*    clusters required to satisfy the user's request.  If there are not  */
+/*    enough clusters, the largest set of clusters are allocated and      */
+/*    linked to the file.  If there are no free clusters, an error        */
+/*    code is returned to the caller.                                     */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    file_ptr                              File control block pointer    */
+/*    size                                  Number of bytes to allocate   */
+/*    actual_size_allocated                 Number of bytes allocated     */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_entry_write             Update directory entry        */
+/*    _fx_utility_exFAT_bitmap_flush        Flush exFAT allocation bitmap */
+/*    _fx_utility_exFAT_bitmap_free_cluster_find                          */
+/*                                            Find exFAT free cluster     */
+/*    _fx_utility_exFAT_cluster_state_get   Get cluster state             */
+/*    _fx_utility_exFAT_cluster_state_set   Set cluster state             */
+/*    _fx_utility_FAT_entry_read            Read a FAT entry              */
+/*    _fx_utility_FAT_entry_write           Write a FAT entry             */
+/*    _fx_utility_FAT_flush                 Flush written FAT entries     */
+/*    _fx_utility_logical_sector_flush      Flush the written log sector  */
+/*    _fx_fault_tolerant_transaction_start  Start fault tolerant          */
+/*                                            transaction                 */
+/*    _fx_fault_tolerant_transaction_end    End fault tolerant transaction*/
+/*    _fx_fault_tolerant_recover            Recover FAT chain             */
+/*    _fx_fault_tolerant_reset_log_file     Reset the log file            */
+/*    _fx_fault_tolerant_set_FAT_chain      Set data of FAT chain         */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_file_extended_best_effort_allocate(FX_FILE *file_ptr, ULONG64 size, ULONG64 *actual_size_allocated)
+{
+
+UINT                   status;
+ULONG                  i;
+UINT                   found;
+ULONG                  bytes_per_cluster;
+ULONG                  FAT_index, start_FAT_index;
+ULONG                  FAT_value;
+ULONG                  clusters, maximum_clusters;
+FX_MEDIA              *media_ptr;
+
+#ifdef FX_ENABLE_EXFAT
+UCHAR                  cluster_state;
+#endif /* FX_ENABLE_EXFAT */
+
+#ifdef TX_ENABLE_EVENT_TRACE
+TX_TRACE_BUFFER_ENTRY *trace_event;
+ULONG                  trace_timestamp;
+#endif
+
+
+    /* First, determine if the file is still open.  */
+    if (file_ptr -> fx_file_id != FX_FILE_ID)
+    {
+
+        /* Return the file not open error status.  */
+        return(FX_NOT_OPEN);
+    }
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+    /* Setup pointer to media structure.  */
+    media_ptr =  file_ptr -> fx_file_media_ptr;
+
+    /* Increment the number of times this service has been called.  */
+    media_ptr -> fx_media_file_best_effort_allocates++;
+#endif
+
+    /* Make sure this file is open for writing.  */
+    if (file_ptr -> fx_file_open_mode != FX_OPEN_FOR_WRITE)
+    {
+
+        /* Return the access error exception - a write was attempted from
+           a file opened for reading!  */
+        return(FX_ACCESS_ERROR);
+    }
+
+    /* Determine if the requested allocation is for zero bytes.  */
+    if (size == 0)
+    {
+
+        /* Return a size allocated of zero.  */
+        *actual_size_allocated =  0;
+
+        /* Return a successful completion - nothing needs to be done.  */
+        return(FX_SUCCESS);
+    }
+
+    /* Setup pointer to associated media control block.  */
+    media_ptr =  file_ptr -> fx_file_media_ptr;
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_FILE_BEST_EFFORT_ALLOCATE, file_ptr, size, 0, 0, FX_TRACE_FILE_EVENTS, &trace_event, &trace_timestamp)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    /* Start transaction. */
+    _fx_fault_tolerant_transaction_start(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Check for write protect at the media level (set by driver).  */
+    if (media_ptr -> fx_media_driver_write_protect)
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return write protect error.  */
+        return(FX_WRITE_PROTECT);
+    }
+
+    /* Calculate the number of bytes per cluster.  */
+    bytes_per_cluster =  ((ULONG)media_ptr -> fx_media_bytes_per_sector) *
+        ((ULONG)media_ptr -> fx_media_sectors_per_cluster);
+
+    /* Check for invalid value.  */
+    if (bytes_per_cluster == 0)
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Invalid media, return error.  */
+        return(FX_MEDIA_INVALID);
+    }
+
+    /* Calculate the number of consecutive clusters needed to satisfy this
+       request.  */
+    clusters =  (ULONG)(((size + bytes_per_cluster - 1) / bytes_per_cluster));
+    
+    /* Determine if cluster count is 0.  */
+    if (clusters == 0)
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Size overflow when rounding to the next cluster, return an error status.  */
+        return(FX_NO_MORE_SPACE);
+    }
+
+    /* Determine if there are no available clusters on the media.  */
+    if (!media_ptr -> fx_media_available_clusters)
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return a size allocated of zero, since no clusters were available.  */
+        *actual_size_allocated =  0;
+
+        /* Not enough clusters, return an error status.  */
+        return(FX_NO_MORE_SPACE);
+    }
+
+    /* Determine if the requested file allocation would exceed the physical limit of the file.  */
+    if (((file_ptr -> fx_file_current_available_size + (((ULONG64) clusters) * ((ULONG64) bytes_per_cluster))) < file_ptr -> fx_file_current_available_size) ||
+        ((file_ptr -> fx_file_current_available_size + (((ULONG64) clusters) * ((ULONG64) bytes_per_cluster))) > 0xFFFFFFFFULL))
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the no more space error, since the new file size would be larger than
+           the 32-bit field to represent it in the file's directory entry.  */
+        return(FX_NO_MORE_SPACE);
+    }
+
+    /* Now we need to find the consecutive clusters.  */
+    found =             FX_FALSE;
+#ifdef FX_ENABLE_EXFAT
+    if ((file_ptr -> fx_file_dir_entry.fx_dir_entry_dont_use_fat & 1) &&
+        (file_ptr -> fx_file_last_physical_cluster > FX_FAT_ENTRY_START) &&
+        (file_ptr -> fx_file_last_physical_cluster < media_ptr -> fx_media_total_clusters - clusters + FX_FAT_ENTRY_START))
+    {
+        found = FX_TRUE;
+
+        /* Try to keep clusters consecutive.  */
+        for (FAT_index = file_ptr -> fx_file_last_physical_cluster + 1;
+             FAT_index < clusters + file_ptr -> fx_file_last_physical_cluster + 1;
+             FAT_index++)
+        {
+
+            /* Get cluster state.  */
+            status = _fx_utility_exFAT_cluster_state_get(media_ptr, FAT_index, &cluster_state);
+
+            /* Check for a successful status.  */
+            if (status != FX_SUCCESS)
+            {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* Return the error status.  */
+                return(status);
+            }
+
+            /* Determine if the entry is free.  */
+            if (cluster_state == FX_EXFAT_BITMAP_CLUSTER_OCCUPIED)
+            {
+                found = FX_FALSE;
+                break;
+            }
+        }
+        FAT_index = file_ptr -> fx_file_last_physical_cluster + 1;
+    }
+
+    if (!found)
+    {
+#endif /* FX_ENABLE_EXFAT */
+        FAT_index =         FX_FAT_ENTRY_START;
+        maximum_clusters =  0;
+        start_FAT_index =   FAT_index;
+
+        while (FAT_index < (media_ptr -> fx_media_total_clusters + FX_FAT_ENTRY_START))
+        {
+
+            /* Determine if enough consecutive FAT entries are available.  */
+            i =  0;
+
+#ifdef FX_ENABLE_EXFAT
+            if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+            {
+                do
+                {
+
+                    /* Get cluster state.  */
+                    status = _fx_utility_exFAT_cluster_state_get(media_ptr, (FAT_index + i), &cluster_state);
+
+                    /* Check for a successful status.  */
+                    if (status != FX_SUCCESS)
+                    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                        /* Release media protection.  */
+                        FX_UNPROTECT
+
+                        /* Return the error status.  */
+                        return(status);
+                    }
+
+                    /* Determine if the entry is free.  */
+                    if (cluster_state == FX_EXFAT_BITMAP_CLUSTER_OCCUPIED)
+                    {
+                        break;
+                    }
+
+                    /* Otherwise, increment the consecutive FAT indices.  */
+                    i++;
+                } while ((i < clusters) && ((FAT_index + i) < media_ptr -> fx_media_total_clusters + FX_FAT_ENTRY_START));
+            }
+            else
+            {
+#endif /* FX_ENABLE_EXFAT */
+
+                do
+                {
+
+                    /* Read a FAT entry.  */
+                    status =  _fx_utility_FAT_entry_read(media_ptr, (FAT_index + i), &FAT_value);
+
+                    /* Check for a successful status.  */
+                    if (status != FX_SUCCESS)
+                    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                        /* Release media protection.  */
+                        FX_UNPROTECT
+
+                        /* Return the error status.  */
+                        return(status);
+                    }
+
+                    /* Determine if the entry is free.  */
+                    if (FAT_value != FX_FREE_CLUSTER)
+                    {
+                        break;
+                    }
+
+                    /* Otherwise, increment the consecutive FAT indices.  */
+                    i++;
+                } while ((i < clusters) && ((FAT_index + i) < media_ptr -> fx_media_total_clusters + FX_FAT_ENTRY_START));
+#ifdef FX_ENABLE_EXFAT
+            }
+#endif /* FX_ENABLE_EXFAT */
+
+            /* Determine if a new maximum number of clusters has been found.  */
+            if (i > maximum_clusters)
+            {
+
+                /* Yes, remember the maximum number of clusters and the starting
+                   cluster.  */
+                maximum_clusters =      i;
+                start_FAT_index =       FAT_index;
+            }
+
+            /* Determine if we found enough FAT entries.  */
+            if (i >= clusters)
+            {
+
+                /* Yes, we have found enough FAT entries - set the found
+                   flag and get out of this loop.  */
+                found =  FX_TRUE;
+                break;
+            }
+            else
+            {
+#ifdef FX_ENABLE_EXFAT
+                if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+                {
+
+                    /* Find free cluster from exFAT media.  */
+                    status = _fx_utility_exFAT_bitmap_free_cluster_find(media_ptr,
+                                                                        FAT_index + i + 1,
+                                                                        &FAT_value);
+                    if (status != FX_SUCCESS)
+                    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                        /* Release media protection.  */
+                        FX_UNPROTECT
+
+                        /* Return the error status.  */
+                        return(status);
+                    }
+
+                    if (FAT_value < FAT_index + i + 1)
+                    {
+
+                        /* If we wrapped.  */
+                        FAT_index = media_ptr -> fx_media_total_clusters  + FX_FAT_ENTRY_START;
+                    }
+                    else
+                    {
+                        FAT_index = FAT_value;
+                    }
+                }
+                else
+                {
+#endif /* FX_ENABLE_EXFAT */
+
+                    /* Position to the next possibly free FAT entry.  */
+                    FAT_index =  FAT_index + i + 1;
+#ifdef FX_ENABLE_EXFAT
+                }
+#endif /* FX_ENABLE_EXFAT */
+            }
+        }
+
+        /* Determine if the total request could not be satisfied, but a partial allocation
+           could be satisfied.  */
+        if (maximum_clusters)
+        {
+
+            /* Yes, there was at least one cluster.  Prepare to return this
+               to the caller.  */
+            FAT_index =  start_FAT_index;
+            clusters =   maximum_clusters;
+            found =      FX_TRUE;
+        }
+#ifdef FX_ENABLE_EXFAT
+    }
+#endif
+
+    /* Determine if we found enough consecutive clusters to satisfy the
+       request.  */
+    if (found)
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        if (media_ptr -> fx_media_fault_tolerant_enabled)
+        {
+
+            /* Record the FAT chain being applied to the file system. This information aids
+               recovery effort if fault happens. */
+            media_ptr -> fx_media_fault_tolerant_state |= FX_FAULT_TOLERANT_STATE_SET_FAT_CHAIN;
+            _fx_fault_tolerant_set_FAT_chain(media_ptr, FX_FALSE, file_ptr -> fx_file_last_physical_cluster,
+                                             FAT_index, media_ptr -> fx_media_fat_last, media_ptr -> fx_media_fat_last);
+        }
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+#ifdef FX_ENABLE_EXFAT
+        if (file_ptr -> fx_file_dir_entry.fx_dir_entry_dont_use_fat & 1)
+        {
+            if ((file_ptr -> fx_file_total_clusters) &&
+                (FAT_index != file_ptr -> fx_file_last_physical_cluster + 1))
+            {
+
+                /* Clusters are not consecutive.  */
+                file_ptr -> fx_file_dir_entry.fx_dir_entry_dont_use_fat &= (CHAR)0xfe; /* Set 0bit to 0.  */
+
+                /* Rebuild FAT.  */
+                FAT_value = file_ptr -> fx_file_dir_entry.fx_dir_entry_cluster +
+                            file_ptr -> fx_file_total_clusters - 1; /* Last cluster */
+
+                for (i = file_ptr -> fx_file_dir_entry.fx_dir_entry_cluster; i < FAT_value; ++i)
+                {
+                    status = _fx_utility_FAT_entry_write(media_ptr, i, i + 1);
+                    if (status != FX_SUCCESS)
+                    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                        /* Release media protection.  */
+                        FX_UNPROTECT
+
+                        /* Return the bad status.  */
+                        return(status);
+                    }
+                }
+
+                /* Close chain.  */
+                status = _fx_utility_FAT_entry_write(media_ptr, FAT_value, media_ptr -> fx_media_fat_last);
+                if (status != FX_SUCCESS)
+                {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                    FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                    /* Release media protection.  */
+                    FX_UNPROTECT
+
+                    /* Return the bad status.  */
+                    return(status);
+                }
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                if (media_ptr -> fx_media_fault_tolerant_enabled)
+                {
+
+                    /* Clear the Fault Tolerant Set FAT Chain flag. */
+                    media_ptr -> fx_media_fault_tolerant_state &= (UCHAR)(~FX_FAULT_TOLERANT_STATE_SET_FAT_CHAIN & 0xff);
+                }
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                /* Update stream.  */
+                status = _fx_directory_exFAT_entry_write(
+                        media_ptr, &(file_ptr -> fx_file_dir_entry), UPDATE_STREAM);
+
+                if (status != FX_SUCCESS)
+                {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                    FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                    /* Release media protection.  */
+                    FX_UNPROTECT
+
+                    /* Return the bad status.  */
+                    return(status);
+                }
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                if (media_ptr -> fx_media_fault_tolerant_enabled)
+                {
+
+                    /* Set undo phase. */
+                    media_ptr -> fx_media_fault_tolerant_state |= FX_FAULT_TOLERANT_STATE_SET_FAT_CHAIN;
+                }
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+            }
+        }
+#endif /* FX_ENABLE_EXFAT */
+
+        /* Update the link pointers in the new clusters.  */
+        for (i = 0; i < (clusters - 1); i++)
+        {
+#ifdef FX_ENABLE_EXFAT
+            if (!(file_ptr -> fx_file_dir_entry.fx_dir_entry_dont_use_fat & 1)
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                || (media_ptr -> fx_media_fault_tolerant_enabled == FX_TRUE)
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+               )
+            {
+#endif /* FX_ENABLE_EXFAT */
+
+                /* Update the cluster links.  Since the allocation is
+                   sequential, we just have to link each FAT entry to the
+                   next one.  */
+                status =  _fx_utility_FAT_entry_write(media_ptr, FAT_index + i, FAT_index + i + 1);
+
+                /* Check for a bad status.  */
+                if (status != FX_SUCCESS)
+                {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                    FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                    /* Release media protection.  */
+                    FX_UNPROTECT
+
+                    /* Return the error status.  */
+                    return(status);
+                }
+#ifdef FX_ENABLE_EXFAT
+            }
+
+            if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+            {
+
+                /* Mark the cluster as used.  */
+                status = _fx_utility_exFAT_cluster_state_set(media_ptr, FAT_index + i, FX_EXFAT_BITMAP_CLUSTER_OCCUPIED);
+
+                /* Check for a bad status.  */
+                if (status != FX_SUCCESS)
+                {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                    FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                    /* Release media protection.  */
+                    FX_UNPROTECT
+
+                    /* Return the error status.  */
+                    return(status);
+                }
+            }
+#endif /* FX_ENABLE_EXFAT */
+        }
+
+#ifdef FX_ENABLE_EXFAT
+        if (!(file_ptr -> fx_file_dir_entry.fx_dir_entry_dont_use_fat & 1))
+        {
+#endif /* FX_ENABLE_EXFAT */
+
+            /* Now place an EOF in the last cluster entry.  */
+            status =  _fx_utility_FAT_entry_write(media_ptr, FAT_index + clusters - 1, media_ptr -> fx_media_fat_last);
+
+            /* Check for a bad status.  */
+            if (status != FX_SUCCESS)
+            {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* Return the error status.  */
+                return(status);
+            }
+#ifdef FX_ENABLE_EXFAT
+        }
+
+        if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+        {
+
+            /* Mark the cluster as used.  */
+            status = _fx_utility_exFAT_cluster_state_set(media_ptr, FAT_index + clusters - 1, FX_EXFAT_BITMAP_CLUSTER_OCCUPIED);
+
+            /* Check for a bad status.  */
+            if (status != FX_SUCCESS)
+            {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* Return the error status.  */
+                return(status);
+            }
+        }
+#endif /* FX_ENABLE_EXFAT */
+
+#ifdef FX_FAULT_TOLERANT
+
+        /* Flush the cached individual FAT entries */
+        _fx_utility_FAT_flush(media_ptr);
+#ifdef FX_ENABLE_EXFAT
+        if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+        {
+            _fx_utility_exFAT_bitmap_flush(media_ptr);
+        }
+#endif /* FX_ENABLE_EXFAT */
+#endif
+
+        /* Actually link up the new clusters to the file.  */
+
+        /* Determine if there are already clusters allocated for this file.  */
+        if (file_ptr -> fx_file_total_clusters)
+        {
+
+#ifdef FX_ENABLE_EXFAT
+            if (!(file_ptr -> fx_file_dir_entry.fx_dir_entry_dont_use_fat & 1))
+            {
+#endif /* FX_ENABLE_EXFAT */
+
+                /* Linkup the last cluster.  */
+                status =  _fx_utility_FAT_entry_write(media_ptr,
+                                                      file_ptr -> fx_file_last_physical_cluster, FAT_index);
+
+                /* Check for a bad status.  */
+                if (status != FX_SUCCESS)
+                {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                    FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                    /* Release media protection.  */
+                    FX_UNPROTECT
+
+                    /* Return the error status.  */
+                    return(status);
+                }
+#ifdef FX_ENABLE_EXFAT
+            }
+#endif /* FX_ENABLE_EXFAT */
+
+            /* Determine if we are adding a sector after a write filled the previously
+               allocated cluster exactly.  */
+            if ((file_ptr -> fx_file_current_relative_sector >=
+                 (media_ptr -> fx_media_sectors_per_cluster - 1)) &&            
+                (file_ptr -> fx_file_current_logical_offset >=
+                    media_ptr -> fx_media_bytes_per_sector))
+            {
+
+                /* Yes, we need to adjust all of the pertinent file parameters for
+                   access into this newly allocated cluster.  */
+                file_ptr -> fx_file_current_physical_cluster =  FAT_index;
+                file_ptr -> fx_file_current_relative_cluster++;
+                file_ptr -> fx_file_current_relative_sector =   0;
+                file_ptr -> fx_file_current_logical_sector =    ((ULONG)media_ptr -> fx_media_data_sector_start) +
+                    (((ULONG64)(FAT_index - FX_FAT_ENTRY_START)) *
+                     ((ULONG)media_ptr -> fx_media_sectors_per_cluster));
+                file_ptr -> fx_file_current_logical_offset =    0;
+            }
+        }
+        else
+        {
+
+            /* These new clusters are also the first!  Setup the initial
+               file parameters.  */
+            file_ptr -> fx_file_first_physical_cluster =    FAT_index;
+            file_ptr -> fx_file_current_physical_cluster =  file_ptr -> fx_file_first_physical_cluster;
+            file_ptr -> fx_file_current_relative_cluster =  0;
+            file_ptr -> fx_file_current_logical_sector =    ((ULONG)media_ptr -> fx_media_data_sector_start) +
+                (((ULONG64)(file_ptr -> fx_file_first_physical_cluster - FX_FAT_ENTRY_START)) *
+                 ((ULONG)media_ptr -> fx_media_sectors_per_cluster));
+            file_ptr -> fx_file_current_logical_offset =    0;
+            file_ptr -> fx_file_current_file_offset =       0;
+
+            /* Setup the consecutive clusters at the beginning of the file.  */
+            file_ptr -> fx_file_consecutive_cluster =       clusters;
+
+            /* Update the first cluster in the directory entry.  */
+            file_ptr -> fx_file_dir_entry.fx_dir_entry_cluster =  FAT_index;
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+            if (media_ptr -> fx_media_fault_tolerant_enabled)
+            {
+
+                /* Clear undo phase. */
+                media_ptr -> fx_media_fault_tolerant_state &= (UCHAR)(~FX_FAULT_TOLERANT_STATE_SET_FAT_CHAIN & 0xff);
+            }
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+        }
+
+        /* Remember the last physical cluster.  */
+        file_ptr -> fx_file_last_physical_cluster =     FAT_index + clusters - 1;
+
+        /* Update the available size.  */
+#ifdef FX_ENABLE_EXFAT
+        if (file_ptr -> fx_file_current_available_size > (file_ptr -> fx_file_current_available_size + (bytes_per_cluster * clusters)))
+        {
+            /* 64-bit wrap around condition is present.  Just set the available file size to all ones, which is
+               the maximum file size.  */
+            file_ptr -> fx_file_current_available_size =  0xFFFFFFFFFFFFFFFFULL;
+        }
+
+        /* Check for wrap-around when updating the available size.  */
+        if ((media_ptr -> fx_media_FAT_type != FX_exFAT) &&
+            (file_ptr -> fx_file_current_available_size + (bytes_per_cluster * clusters) > 0xFFFFFFFFUL))
+        {
+
+            /* 32-bit wrap around condition is present.  Just set the available file size to all ones, which is
+               the maximum file size.  */
+            file_ptr -> fx_file_current_available_size =  0xFFFFFFFFUL;
+        }
+        else
+        {
+#endif /* FX_ENABLE_EXFAT */
+
+            /* Normal condition, update the available size.  */
+            file_ptr -> fx_file_current_available_size =
+                file_ptr -> fx_file_current_available_size + bytes_per_cluster * clusters;
+#ifdef FX_ENABLE_EXFAT
+        }
+
+        if (file_ptr -> fx_file_dir_entry.fx_dir_entry_dont_use_fat & 1)
+        {
+            file_ptr -> fx_file_consecutive_cluster += clusters;
+        }
+#endif /* FX_ENABLE_EXFAT */
+
+        /* Increment the total clusters for this file.  */
+        file_ptr -> fx_file_total_clusters =
+            file_ptr -> fx_file_total_clusters + clusters;
+
+        /* Decrease the available clusters on the media.  */
+        media_ptr -> fx_media_available_clusters =
+            media_ptr -> fx_media_available_clusters - clusters;
+
+        /* Return the actual size allocated.  */
+        *actual_size_allocated =  ((ULONG64)clusters) * bytes_per_cluster;
+
+#if defined(FX_UPDATE_FILE_SIZE_ON_ALLOCATE) || defined(FX_ENABLE_FAULT_TOLERANT)
+
+        /* Set the file size the current size plus what what was added.  */
+        if (size < *actual_size_allocated)
+        {
+            file_ptr -> fx_file_current_file_size +=  size;
+        }
+        else
+        {
+            file_ptr -> fx_file_current_file_size +=  *actual_size_allocated;
+        }
+
+        /* Copy the new file size into the directory entry.  */
+        file_ptr -> fx_file_dir_entry.fx_dir_entry_file_size =  file_ptr -> fx_file_current_file_size;
+#endif
+
+        /* Update the trace event with the bytes allocated.  */
+        FX_TRACE_EVENT_UPDATE(trace_event, trace_timestamp, FX_TRACE_FILE_BEST_EFFORT_ALLOCATE, 0, 0, *actual_size_allocated, 0);
+
+        /* Write the directory entry to the media.  */
+#ifdef FX_ENABLE_EXFAT
+        if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+        {
+            status = _fx_directory_exFAT_entry_write(
+                    media_ptr, &(file_ptr -> fx_file_dir_entry), UPDATE_STREAM);
+        }
+        else
+        {
+#endif /* FX_ENABLE_EXFAT */
+            status = _fx_directory_entry_write(media_ptr, &(file_ptr -> fx_file_dir_entry));
+#ifdef FX_ENABLE_EXFAT
+        }
+#endif /* FX_ENABLE_EXFAT */
+
+        /* Check for a good status.  */
+        if (status != FX_SUCCESS)
+        {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+            FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* Return the error status.  */
+            return(status);
+        }
+    }
+    else
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return a size allocated of zero, since no clusters were available.  */
+        *actual_size_allocated =  0;
+
+        /* Not enough contiguous space on the media.  Return error status.  */
+        return(FX_NO_MORE_SPACE);
+    }
+
+#ifdef FX_FAULT_TOLERANT
+
+    /* Flush the cached individual FAT entries */
+    _fx_utility_FAT_flush(media_ptr);
+#endif
+
+    /* Flush the internal logical sector cache.  */
+    status =  _fx_utility_logical_sector_flush(media_ptr, ((ULONG64) 1), (ULONG64) (media_ptr -> fx_media_sectors_per_FAT), FX_FALSE);
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    /* Check for a bad status.  */
+    if (status != FX_SUCCESS)
+    {
+
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the bad status.  */
+        return(status);
+    }
+
+    /* End transaction. */
+    status = _fx_fault_tolerant_transaction_end(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_extended_relative_seek.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_extended_relative_seek.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_extended_relative_seek.c	(revision 30)
@@ -0,0 +1,163 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_directory.h"
+#include "fx_file.h"
+#include "fx_utility.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_file_extended_relative_seek                     PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function positions the internal file pointers to the specified */
+/*    byte relative offset such that the next read or write operation is  */
+/*    performed there.                                                    */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    file_ptr                              File control block pointer    */
+/*    byte_offset                           Byte offset of the seek       */
+/*    seek_from                             Direction for relative seek,  */
+/*                                          legal values are:             */
+/*                                                                        */
+/*                                              FX_SEEK_BEGIN             */
+/*                                              FX_SEEK_END               */
+/*                                              FX_SEEK_FORWARD           */
+/*                                              FX_SEEK_BACK              */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_file_extended_seek                Seek to specified position    */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_file_extended_relative_seek(FX_FILE *file_ptr, ULONG64 byte_offset, UINT seek_from)
+{
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+FX_MEDIA *media_ptr;
+
+    /* First, determine if the file is still open.  */
+    if (file_ptr -> fx_file_id != FX_FILE_ID)
+    {
+
+        /* Return the file not open error status.  */
+        return(FX_NOT_OPEN);
+    }
+
+    /* Setup pointer to media structure.  */
+    media_ptr =  file_ptr -> fx_file_media_ptr;
+
+    /* Increment the number of times this service has been called.  */
+    media_ptr -> fx_media_file_relative_seeks++;
+#endif
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_FILE_RELATIVE_SEEK, file_ptr, byte_offset, seek_from, file_ptr -> fx_file_current_file_offset, FX_TRACE_FILE_EVENTS, 0, 0)
+
+    /* Determine if seeking from the beginning is requested.  */
+    if (seek_from == FX_SEEK_BEGIN)
+    {
+
+        /* Yes, use the base file seek routine to seek from the beginning of
+           the file.  */
+        return(_fx_file_extended_seek(file_ptr, byte_offset));
+    }
+    /* Otherwise, determine if seeking from the end is requested.  */
+    else if (seek_from == FX_SEEK_END)
+    {
+
+        /* Yes, seek from the end of the file.  */
+
+        /* Determine if the requested seek offset is greater than
+           the file size.  */
+        if (byte_offset >= file_ptr -> fx_file_current_file_size)
+        {
+
+            /* Yes, just seek to the beginning of the file.  */
+            return(_fx_file_extended_seek(file_ptr, ((ULONG64) 0)));
+        }
+        else
+        {
+
+            /* Logically seek from the end of the file.  */
+            return(_fx_file_extended_seek(file_ptr, file_ptr -> fx_file_current_file_size - byte_offset));
+        }
+    }
+    /* Otherwise, determine if seeking from the current position is requested.  */
+    else if (seek_from == FX_SEEK_FORWARD)
+    {
+
+        /* Yes, just seek ahead from the current file position.  */
+        return(_fx_file_extended_seek(file_ptr, file_ptr -> fx_file_current_file_offset + byte_offset));
+    }
+    /* Otherwise, seeking backward from the current position is assumed.  */
+    else
+    {
+
+        /* Determine if the backward offset is greater than the current file offset.  */
+        if (byte_offset >= file_ptr -> fx_file_current_file_offset)
+        {
+
+            /* Yes, just position the file to the beginning.  */
+            return(_fx_file_extended_seek(file_ptr, ((ULONG64) 0)));
+        }
+        else
+        {
+
+            /* Seek backward relative to the current position.  */
+            return(_fx_file_extended_seek(file_ptr, file_ptr -> fx_file_current_file_offset - byte_offset));
+        }
+    }
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_extended_seek.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_extended_seek.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_extended_seek.c	(revision 30)
@@ -0,0 +1,328 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_directory.h"
+#include "fx_file.h"
+#include "fx_utility.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_file_extended_seek                              PORTABLE C      */
+/*                                                           6.1.7        */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function positions the internal file pointers to the specified */
+/*    byte offset such that the next read or write operation will be      */
+/*    performed there.  If the byte offset is greater than the size, the  */
+/*    file pointers will be positioned to the end of the file.            */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    file_ptr                              File control block pointer    */
+/*    byte_offset                           Byte offset into the file     */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_FAT_entry_read            Read a FAT entry              */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*  06-02-2021     Bhupendra Naphade        Modified comment(s), fixed    */
+/*                                            relative cluster logic,     */
+/*                                            resulting in version 6.1.7  */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_file_extended_seek(FX_FILE *file_ptr, ULONG64 byte_offset)
+{
+
+UINT      status;
+ULONG     cluster;
+ULONG     contents = 0;
+ULONG     bytes_per_cluster;
+ULONG     last_cluster;
+ULONG     cluster_count;
+ULONG64   bytes_remaining;
+FX_MEDIA *media_ptr;
+
+
+    /* First, determine if the file is still open.  */
+    if (file_ptr -> fx_file_id != FX_FILE_ID)
+    {
+
+        /* Return the file not open error status.  */
+        return(FX_NOT_OPEN);
+    }
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+    /* Setup pointer to media structure.  */
+    media_ptr =  file_ptr -> fx_file_media_ptr;
+
+    /* Increment the number of times this service has been called.  */
+    media_ptr -> fx_media_file_seeks++;
+#endif
+
+    /* Setup pointer to associated media control block.  */
+    media_ptr =  file_ptr -> fx_file_media_ptr;
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_FILE_SEEK, file_ptr, byte_offset, file_ptr -> fx_file_current_file_offset, 0, FX_TRACE_FILE_EVENTS, 0, 0)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+    /* Check if we actually have to do anything.  */
+    if (byte_offset == file_ptr -> fx_file_current_file_offset)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Seek is complete, return successful status.  */
+        return(FX_SUCCESS);
+    }
+
+    /* Calculate the number of bytes per cluster.  */
+    bytes_per_cluster =  ((ULONG)media_ptr -> fx_media_bytes_per_sector) *
+        ((ULONG)media_ptr -> fx_media_sectors_per_cluster);
+
+    /* Check for invalid value.  */
+    if (bytes_per_cluster == 0)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Invalid media, return error.  */
+        return(FX_MEDIA_INVALID);
+    }
+
+    /* See if we need to adjust the byte offset.  */
+    if (byte_offset > file_ptr -> fx_file_current_file_size)
+    {
+
+        /* Adjust the byte offset down to the file size. */
+        byte_offset =  file_ptr -> fx_file_current_file_size;
+    }
+
+    /* Check if the desired position within the leading consecutive clusters.  */
+    if (byte_offset >= (ULONG64)file_ptr -> fx_file_consecutive_cluster * (ULONG64)bytes_per_cluster)
+    {
+#ifdef FX_ENABLE_EXFAT
+        if (file_ptr -> fx_file_dir_entry.fx_dir_entry_dont_use_fat & 1)
+        {
+            if (byte_offset == (ULONG64)file_ptr -> fx_file_consecutive_cluster * (ULONG64)bytes_per_cluster)
+            {
+                /* If the file bytes exactly fits the cluster size */
+                bytes_remaining = bytes_per_cluster;
+
+                file_ptr -> fx_file_current_relative_cluster = (ULONG)(byte_offset / bytes_per_cluster - 1);
+
+                file_ptr -> fx_file_current_physical_cluster =
+                    file_ptr -> fx_file_first_physical_cluster + file_ptr -> fx_file_current_relative_cluster;
+            }
+            else
+            {
+
+                /* We shouldn't be here if don't using FAT!  */
+                FX_UNPROTECT
+
+                return(FX_FILE_CORRUPT);
+            }
+        }
+        else
+        {
+#endif /* FX_ENABLE_EXFAT */
+
+            /* At this point, we are ready to walk list of clusters to setup the
+               seek position of this file.  */
+
+            /* check if byte_offset is greater than where we were left off earlier */
+            if ((ULONG64)file_ptr -> fx_file_current_relative_cluster * (ULONG64)bytes_per_cluster < byte_offset)
+            {
+
+                cluster =    file_ptr -> fx_file_current_physical_cluster;
+
+                bytes_remaining =   byte_offset -
+                    file_ptr -> fx_file_current_relative_cluster * bytes_per_cluster;
+
+                cluster_count = file_ptr -> fx_file_current_relative_cluster;
+            }
+            else
+            {
+
+                cluster =    file_ptr -> fx_file_first_physical_cluster +
+                    (file_ptr -> fx_file_consecutive_cluster - 1);
+                bytes_remaining =   byte_offset -
+                    (file_ptr -> fx_file_consecutive_cluster - 1) * bytes_per_cluster;
+                cluster_count =     (file_ptr -> fx_file_consecutive_cluster - 1);
+            }
+
+
+            /* Follow the link of FAT entries.  */
+            while ((cluster >= FX_FAT_ENTRY_START) && (cluster < media_ptr -> fx_media_fat_reserved))
+            {
+
+                /* Increment the number of clusters.  */
+                cluster_count++;
+
+                /* Read the current cluster entry from the FAT.  */
+                status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &contents);
+
+                /* Check the return value.  */
+                if (status != FX_SUCCESS)
+                {
+
+                    /* Release media protection.  */
+                    FX_UNPROTECT
+
+                    /* Return the error status.  */
+                    return(status);
+                }
+
+                /* Save the last valid cluster.  */
+                last_cluster =  cluster;
+
+                /* Setup for the next cluster.  */
+                cluster =  contents;
+
+                /* Determine if this is the last written cluster.  */
+                if (bytes_remaining > bytes_per_cluster)
+                {
+
+                    /* Still more seeking, just decrement the working byte offset.  */
+                    bytes_remaining =  bytes_remaining - bytes_per_cluster;
+                }
+                else
+                {
+
+                    /* Remember this cluster number.  */
+                    file_ptr -> fx_file_current_physical_cluster =  last_cluster;
+
+                    /* Remember the relative cluster.  */
+                    file_ptr -> fx_file_current_relative_cluster =  cluster_count - 1;
+
+                    /* If the remaining bytes exactly fits the cluster size, check for
+                       a possible adjustment to the next cluster.  */
+                    if ((bytes_remaining == bytes_per_cluster) &&
+                        (cluster >= FX_FAT_ENTRY_START) && (cluster < media_ptr -> fx_media_fat_reserved))
+                    {
+
+                        /* We need to position to next allocated cluster.  */
+                        file_ptr -> fx_file_current_physical_cluster =  cluster;
+                        file_ptr -> fx_file_current_relative_cluster++;
+
+                        /* Clear the remaining bytes.  */
+                        bytes_remaining =  0;
+                    }
+
+                    /* This is the cluster that contains the seek position.  */
+                    break;
+                }
+            }
+        
+            /* Check for errors in traversal of the FAT chain.  */
+            if (byte_offset > (((ULONG64) bytes_per_cluster) * ((ULONG64) cluster_count)))
+            {
+    
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* This is an error that suggests a corrupt file.  */
+                return(FX_FILE_CORRUPT);
+            }
+#ifdef FX_ENABLE_EXFAT
+        }
+#endif /* FX_ENABLE_EXFAT */
+    }
+    else
+    {
+
+        /* we should directly access the desired cluster */
+        file_ptr -> fx_file_current_relative_cluster = (ULONG)(byte_offset / bytes_per_cluster);
+
+        file_ptr -> fx_file_current_physical_cluster =
+            file_ptr -> fx_file_first_physical_cluster + file_ptr -> fx_file_current_relative_cluster;
+
+        bytes_remaining =  byte_offset % bytes_per_cluster;
+    }
+
+
+    /* Determine if the remaining bytes fit exactly into the cluster size.  */
+    if (bytes_remaining == bytes_per_cluster)
+    {
+
+        /* Position to the end of the cluster.  */
+        file_ptr -> fx_file_current_logical_sector = (ULONG)(((ULONG)media_ptr -> fx_media_data_sector_start) +
+                                                             (((ULONG64)file_ptr -> fx_file_current_physical_cluster - FX_FAT_ENTRY_START) *
+                                                              ((ULONG)media_ptr -> fx_media_sectors_per_cluster)) +
+                                                             ((bytes_remaining - 1) / (ULONG)media_ptr -> fx_media_bytes_per_sector));
+        file_ptr -> fx_file_current_relative_sector =   (UINT)(((bytes_remaining - 1) / (ULONG)media_ptr -> fx_media_bytes_per_sector));
+        file_ptr -> fx_file_current_file_offset =       byte_offset;
+        file_ptr -> fx_file_current_logical_offset =    media_ptr -> fx_media_bytes_per_sector;
+    }
+    else
+    {
+
+        /* Position the pointers to the new offset.  */
+        file_ptr -> fx_file_current_logical_sector = (ULONG)(((ULONG)media_ptr -> fx_media_data_sector_start) +
+                                                             (((ULONG64)file_ptr -> fx_file_current_physical_cluster - FX_FAT_ENTRY_START) *
+                                                              ((ULONG)media_ptr -> fx_media_sectors_per_cluster)) +
+                                                             (bytes_remaining / (ULONG)media_ptr -> fx_media_bytes_per_sector));
+        file_ptr -> fx_file_current_relative_sector =   (UINT)((bytes_remaining / (ULONG)media_ptr -> fx_media_bytes_per_sector));
+        file_ptr -> fx_file_current_file_offset =       byte_offset;
+        file_ptr -> fx_file_current_logical_offset =    (ULONG)(bytes_remaining % ((ULONG)media_ptr -> fx_media_bytes_per_sector));
+    }
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* Seek is complete, return successful status.  */
+    return(FX_SUCCESS);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_extended_truncate.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_extended_truncate.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_extended_truncate.c	(revision 30)
@@ -0,0 +1,377 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_directory.h"
+#include "fx_file.h"
+#include "fx_utility.h"
+#ifdef FX_ENABLE_FAULT_TOLERANT
+#include "fx_fault_tolerant.h"
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_file_extended_truncate                          PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function sets the file to the specified size, if smaller than  */
+/*    the current file size.  If the new file size is less than the       */
+/*    current file read/write position, the internal file pointers will   */
+/*    also be modified.                                                   */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    file_ptr                              File control block pointer    */
+/*    size                                  New size of the file in bytes */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_FAT_entry_read            Read a FAT entry              */
+/*    _fx_fault_tolerant_transaction_start  Start fault tolerant          */
+/*                                            transaction                 */
+/*    _fx_fault_tolerant_transaction_end    End fault tolerant transaction*/
+/*    _fx_fault_tolerant_recover            Recover FAT chain             */
+/*    _fx_fault_tolerant_reset_log_file     Reset the log file            */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_file_extended_truncate(FX_FILE *file_ptr, ULONG64 size)
+{
+
+UINT                   status;
+ULONG                  cluster;
+ULONG                  contents = 0;
+ULONG                  bytes_per_cluster;
+ULONG                  last_cluster;
+ULONG                  cluster_count;
+ULONG64                bytes_remaining;
+FX_MEDIA              *media_ptr;
+
+#ifndef FX_DONT_UPDATE_OPEN_FILES
+ULONG                  open_count;
+FX_FILE               *search_ptr;
+#endif
+
+#ifdef TX_ENABLE_EVENT_TRACE
+TX_TRACE_BUFFER_ENTRY *trace_event;
+ULONG                  trace_timestamp;
+#endif
+
+
+    /* First, determine if the file is still open.  */
+    if (file_ptr -> fx_file_id != FX_FILE_ID)
+    {
+
+        /* Return the file not open error status.  */
+        return(FX_NOT_OPEN);
+    }
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+    /* Setup pointer to media structure.  */
+    media_ptr =  file_ptr -> fx_file_media_ptr;
+
+    /* Increment the number of times this service has been called.  */
+    media_ptr -> fx_media_file_truncates++;
+#endif
+
+    /* Setup pointer to associated media control block.  */
+    media_ptr =  file_ptr -> fx_file_media_ptr;
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_FILE_TRUNCATE, file_ptr, size, file_ptr -> fx_file_current_file_size, 0, FX_TRACE_FILE_EVENTS, &trace_event, &trace_timestamp)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+    /* Make sure this file is open for writing.  */
+    if (file_ptr -> fx_file_open_mode != FX_OPEN_FOR_WRITE)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the access error exception - a write was attempted from
+           a file opened for reading!  */
+        return(FX_ACCESS_ERROR);
+    }
+
+    /* Check for write protect at the media level (set by driver).  */
+    if (media_ptr -> fx_media_driver_write_protect)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return write protect error.  */
+        return(FX_WRITE_PROTECT);
+    }
+
+    /* Setup the new file size - if less than the current size.  */
+    if (size < file_ptr -> fx_file_current_file_size)
+    {
+
+        /* Setup the new size.  */
+        file_ptr -> fx_file_current_file_size =  size;
+
+        /* Set the modified flag as well.  */
+        file_ptr -> fx_file_modified =  FX_TRUE;
+
+        /* Update the trace event with the truncated size.  */
+        FX_TRACE_EVENT_UPDATE(trace_event, trace_timestamp, FX_TRACE_FILE_TRUNCATE, 0, 0, 0, size)
+    }
+    else
+    {
+
+        /* Update the trace event with the truncated size.  */
+        FX_TRACE_EVENT_UPDATE(trace_event, trace_timestamp, FX_TRACE_FILE_TRUNCATE, 0, 0, 0, file_ptr -> fx_file_current_file_size)
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Just return, the new size is larger than the current size.  */
+        return(FX_SUCCESS);
+    }
+
+#ifndef FX_DONT_UPDATE_OPEN_FILES
+
+    /* Search the opened files list to see if the same file is opened for reading.  */
+    open_count =  media_ptr -> fx_media_opened_file_count;
+    search_ptr =  media_ptr -> fx_media_opened_file_list;
+    while (open_count)
+    {
+
+        /* Is this file the same file opened for reading?  */
+        if ((search_ptr != file_ptr) &&
+            (search_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector ==
+             file_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector) &&
+            (search_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset ==
+             file_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset))
+        {
+
+            /* Yes, the same file is opened for reading.  */
+
+            /* Setup the new file size.  */
+            search_ptr -> fx_file_current_file_size =  size;
+            search_ptr -> fx_file_dir_entry.fx_dir_entry_file_size = size;
+        }
+
+        /* Adjust the pointer and decrement the search count.  */
+        search_ptr =  search_ptr -> fx_file_opened_next;
+        open_count--;
+    }
+#endif
+
+    /* Now check to see if the read/write internal file pointers need
+       to be adjusted.  */
+    if (file_ptr -> fx_file_current_file_offset > file_ptr -> fx_file_current_file_size)
+    {
+
+        /* Calculate the number of bytes per cluster.  */
+        bytes_per_cluster =  ((ULONG)media_ptr -> fx_media_bytes_per_sector) *
+            ((ULONG)media_ptr -> fx_media_sectors_per_cluster);
+
+        /* At this point, we are ready to walk list of clusters to setup the
+           seek position of this file.  */
+        cluster =           file_ptr -> fx_file_first_physical_cluster;
+        bytes_remaining =   size;
+        last_cluster =      0;
+        cluster_count =     0;
+
+        /* Follow the link of FAT entries.  */
+        while ((cluster >= FX_FAT_ENTRY_START) && (cluster < media_ptr -> fx_media_fat_reserved))
+        {
+
+            /* Increment the number of clusters.  */
+            cluster_count++;
+#ifdef FX_ENABLE_EXFAT
+            if (file_ptr -> fx_file_dir_entry.fx_dir_entry_dont_use_fat & 1)
+            {
+                if (cluster >= file_ptr -> fx_file_last_physical_cluster)
+                {
+                    contents = FX_LAST_CLUSTER_exFAT;
+                }
+                else
+                {
+                    contents = cluster + 1;
+                }
+            }
+            else
+            {
+#endif /* FX_ENABLE_EXFAT */
+
+                /* Read the current cluster entry from the FAT.  */
+                status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &contents);
+
+                /* Check the return value.  */
+                if (status != FX_SUCCESS)
+                {
+
+                    /* Release media protection.  */
+                    FX_UNPROTECT
+
+                    /* Return the error status.  */
+                    return(status);
+                }
+#ifdef FX_ENABLE_EXFAT
+            }
+#endif /* FX_ENABLE_EXFAT */
+
+            /* Save the last valid cluster.  */
+            last_cluster =  cluster;
+
+            /* Setup for the next cluster.  */
+            cluster =  contents;
+
+            /* Determine if this is the last written cluster.  */
+            if (bytes_remaining >= bytes_per_cluster)
+            {
+
+                /* Still more seeking, just decrement the working byte offset.  */
+                bytes_remaining =  bytes_remaining - bytes_per_cluster;
+            }
+            else
+            {
+
+                /* This is the cluster that contains the seek position.  */
+                break;
+            }
+        }
+
+        /* Check for errors in traversal of the FAT chain.  */
+        if (size > (((ULONG64) bytes_per_cluster) * ((ULONG64) cluster_count)))
+        {
+        
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* This is an error that suggests a corrupt file.  */
+            return(FX_FILE_CORRUPT);
+        }
+
+        /* Position the pointers to the new offset.  */
+        file_ptr -> fx_file_current_physical_cluster =  last_cluster;
+        file_ptr -> fx_file_current_relative_cluster =  cluster_count - 1;
+        file_ptr -> fx_file_current_logical_sector =    ((ULONG)media_ptr -> fx_media_data_sector_start) +
+            (((ULONG64)file_ptr -> fx_file_current_physical_cluster - FX_FAT_ENTRY_START) *
+             ((ULONG)media_ptr -> fx_media_sectors_per_cluster)) +
+            (bytes_remaining / (ULONG)media_ptr -> fx_media_bytes_per_sector);
+        file_ptr -> fx_file_current_relative_sector =   (UINT)((bytes_remaining / (ULONG)media_ptr -> fx_media_bytes_per_sector));
+        file_ptr -> fx_file_current_file_offset =       size;
+        file_ptr -> fx_file_current_logical_offset =    (ULONG)bytes_remaining % ((ULONG)media_ptr -> fx_media_bytes_per_sector);
+    }
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    if (media_ptr -> fx_media_fault_tolerant_enabled)
+    {
+
+        /* Start transaction. */
+        _fx_fault_tolerant_transaction_start(media_ptr);
+
+        /* Copy the new file size into the directory entry.  */
+        file_ptr -> fx_file_dir_entry.fx_dir_entry_file_size = file_ptr -> fx_file_current_file_size;
+
+        /* Write the directory entry to the media.  */
+#ifdef FX_ENABLE_EXFAT
+        if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+        {
+
+            status = _fx_directory_exFAT_entry_write(media_ptr, &(file_ptr -> fx_file_dir_entry), UPDATE_STREAM);
+        }
+        else
+        {
+#endif /* FX_ENABLE_EXFAT */
+            status =  _fx_directory_entry_write(media_ptr, &(file_ptr -> fx_file_dir_entry));
+#ifdef FX_ENABLE_EXFAT
+        }
+#endif /* FX_ENABLE_EXFAT */
+
+        /* Check for a good status.  */
+        if (status != FX_SUCCESS)
+        {
+
+            FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* Error writing the directory.  */
+            return(status);
+        }
+
+        /* End transaction. */
+        status = _fx_fault_tolerant_transaction_end(media_ptr);
+
+        /* Check for a good status.  */
+        if (status != FX_SUCCESS)
+        {
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* Error writing the directory.  */
+            return(status);
+        }
+
+        /* Update maximum size used if necessary. */
+        if (size < file_ptr -> fx_file_maximum_size_used)
+        {
+            file_ptr -> fx_file_maximum_size_used = size;
+        }
+    }
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* Truncate is complete, return successful status.  */
+    return(FX_SUCCESS);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_extended_truncate_release.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_extended_truncate_release.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_extended_truncate_release.c	(revision 30)
@@ -0,0 +1,973 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_directory.h"
+#include "fx_file.h"
+#include "fx_utility.h"
+#ifdef FX_ENABLE_FAULT_TOLERANT
+#include "fx_fault_tolerant.h"
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_file_extended_truncate_release                  PORTABLE C      */
+/*                                                           6.1.3        */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function sets the file to the specified size, if smaller than  */
+/*    the current file size.  If the new file size is less than the       */
+/*    current file read/write position, the internal file pointers will   */
+/*    also be modified.  Any unused clusters are released back to the     */
+/*    media.                                                              */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    file_ptr                              File control block pointer    */
+/*    size                                  New size of the file in bytes */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_entry_write             Write directory entry         */
+/*    _fx_utility_exFAT_bitmap_flush        Flush exFAT allocation bitmap */
+/*    _fx_utility_exFAT_cluster_state_set   Set cluster state             */
+/*    _fx_utility_FAT_entry_read            Read a FAT entry              */
+/*    _fx_utility_FAT_entry_write           Write a FAT entry             */
+/*    _fx_utility_FAT_flush                 Flush written FAT entries     */
+/*    _fx_fault_tolerant_transaction_start  Start fault tolerant          */
+/*                                            transaction                 */
+/*    _fx_fault_tolerant_transaction_end    End fault tolerant transaction*/
+/*    _fx_fault_tolerant_recover            Recover FAT chain             */
+/*    _fx_fault_tolerant_reset_log_file     Reset the log file            */
+/*    _fx_fault_tolerant_set_FAT_chain      Set data of FAT chain         */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*  12-31-2020     William E. Lamie         Modified comment(s), fixed    */
+/*                                            available cluster issue,    */
+/*                                            resulting in version 6.1.3  */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_file_extended_truncate_release(FX_FILE *file_ptr, ULONG64 size)
+{
+
+UINT                   status;
+ULONG                  cluster;
+ULONG                  contents;
+ULONG                  bytes_per_cluster;
+ULONG                  last_cluster;
+ULONG                  cluster_count;
+ULONG64                bytes_remaining;
+FX_MEDIA              *media_ptr;
+
+#ifdef FX_ENABLE_EXFAT
+ULONG                  original_last_physical_cluster;
+#endif /* FX_ENABLE_EXFAT */
+
+#ifndef FX_DONT_UPDATE_OPEN_FILES
+ULONG                  open_count;
+FX_FILE               *search_ptr;
+#endif
+
+#ifdef TX_ENABLE_EVENT_TRACE
+TX_TRACE_BUFFER_ENTRY *trace_event;
+ULONG                  trace_timestamp;
+#endif
+
+
+    /* First, determine if the file is still open.  */
+    if (file_ptr -> fx_file_id != FX_FILE_ID)
+    {
+
+        /* Return the file not open error status.  */
+        return(FX_NOT_OPEN);
+    }
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+    /* Setup pointer to media structure.  */
+    media_ptr =  file_ptr -> fx_file_media_ptr;
+
+    /* Increment the number of times this service has been called.  */
+    media_ptr -> fx_media_file_truncate_releases++;
+#endif
+
+    /* Setup pointer to associated media control block.  */
+    media_ptr =  file_ptr -> fx_file_media_ptr;
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_FILE_TRUNCATE_RELEASE, file_ptr, size, file_ptr -> fx_file_current_file_size, 0, FX_TRACE_FILE_EVENTS, &trace_event, &trace_timestamp)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    /* Start transaction. */
+    _fx_fault_tolerant_transaction_start(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Make sure this file is open for writing.  */
+    if (file_ptr -> fx_file_open_mode != FX_OPEN_FOR_WRITE)
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the access error exception - a write was attempted from
+           a file opened for reading!  */
+        return(FX_ACCESS_ERROR);
+    }
+
+    /* Check for write protect at the media level (set by driver).  */
+    if (media_ptr -> fx_media_driver_write_protect)
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return write protect error.  */
+        return(FX_WRITE_PROTECT);
+    }
+
+    /* Calculate the number of bytes per cluster.  */
+    bytes_per_cluster =  ((ULONG)media_ptr -> fx_media_bytes_per_sector) *
+        ((ULONG)media_ptr -> fx_media_sectors_per_cluster);
+
+    /* Check for invalid value.  */
+    if (bytes_per_cluster == 0)
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Invalid media, return error.  */
+        return(FX_MEDIA_INVALID);
+    }
+
+    /* Setup the new file available size - if less than the current available size.  */
+    if (size < file_ptr -> fx_file_current_available_size)
+    {
+
+        /* Yes, the file needs to be truncated.  */
+
+        /* Update the available file size.  */
+        file_ptr -> fx_file_current_available_size =  ((size + bytes_per_cluster - 1) / bytes_per_cluster) * bytes_per_cluster;
+
+        /* Is the new available size less than the actual file size?  */
+        if (size < file_ptr -> fx_file_current_file_size)
+        {
+
+            /* Setup the new file size.  */
+            file_ptr -> fx_file_current_file_size =  size;
+
+            /* Set the modified flag.  */
+            file_ptr -> fx_file_modified =  FX_TRUE;
+
+            /* Copy the new file size into the directory entry.  */
+            file_ptr -> fx_file_dir_entry.fx_dir_entry_file_size =  size;
+
+            /* Set the first cluster to NULL.  */
+            if (size == 0)
+            {
+
+                /* Yes, the first cluster needs to be cleared since the entire
+                   file is going to be truncated.  */
+                file_ptr -> fx_file_dir_entry.fx_dir_entry_cluster =  FX_NULL;
+            }
+
+            /* Write the directory entry to the media.  */
+#ifdef FX_ENABLE_EXFAT
+            if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+            {
+                status = _fx_directory_exFAT_entry_write(
+                        media_ptr, &(file_ptr -> fx_file_dir_entry), UPDATE_STREAM);
+            }
+            else
+            {
+#endif /* FX_ENABLE_EXFAT */
+                status = _fx_directory_entry_write(media_ptr, &(file_ptr -> fx_file_dir_entry));
+#ifdef FX_ENABLE_EXFAT
+            }
+#endif /* FX_ENABLE_EXFAT */
+
+            /* Check for a good status.  */
+            if (status != FX_SUCCESS)
+            {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* Error writing the directory.  */
+                return(status);
+            }
+        }
+
+        /* Update the trace event with the truncated size.  */
+        FX_TRACE_EVENT_UPDATE(trace_event, trace_timestamp, FX_TRACE_FILE_TRUNCATE_RELEASE, 0, 0, 0, file_ptr -> fx_file_current_file_size)
+    }
+    else
+    {
+
+        /* Update the trace event with the truncated size.  */
+        FX_TRACE_EVENT_UPDATE(trace_event, trace_timestamp, FX_TRACE_FILE_TRUNCATE_RELEASE, 0, 0, 0, file_ptr -> fx_file_current_file_size)
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Just return, the truncate size is larger than the available size.  */
+        return(FX_SUCCESS);
+    }
+
+    /* Calculate the number of bytes per cluster.  */
+    bytes_per_cluster =  ((ULONG)media_ptr -> fx_media_bytes_per_sector) *
+        ((ULONG)media_ptr -> fx_media_sectors_per_cluster);
+
+    /* Now check to see if the read/write internal file pointers need
+       to be adjusted.  */
+    if (file_ptr -> fx_file_current_file_offset > file_ptr -> fx_file_current_file_size)
+    {
+
+
+        /* At this point, we are ready to walk list of clusters to setup the
+           seek position of this file.  */
+        cluster =           file_ptr -> fx_file_first_physical_cluster;
+        bytes_remaining =   size;
+        last_cluster =      0;
+        cluster_count =     0;
+
+        /* Follow the link of FAT entries.  */
+        while ((cluster >= FX_FAT_ENTRY_START) && (cluster < media_ptr -> fx_media_fat_reserved))
+        {
+
+            /* Increment the number of clusters.  */
+            cluster_count++;
+
+#ifdef FX_ENABLE_EXFAT
+            if (file_ptr -> fx_file_dir_entry.fx_dir_entry_dont_use_fat & 1)
+            {
+                if (cluster >= file_ptr -> fx_file_last_physical_cluster)
+                {
+                    contents = FX_LAST_CLUSTER_exFAT;
+                }
+                else
+                {
+                    contents = cluster + 1;
+                }
+            }
+            else
+            {
+#endif /* FX_ENABLE_EXFAT */
+
+                /* Read the current cluster entry from the FAT.  */
+                status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &contents);
+
+                /* Check the return value.  */
+                if (status != FX_SUCCESS)
+                {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                    FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                    /* Release media protection.  */
+                    FX_UNPROTECT
+
+                    /* Return the error status.  */
+                    return(status);
+                }
+#ifdef FX_ENABLE_EXFAT
+            }
+#endif /* FX_ENABLE_EXFAT */
+
+            /* Save the last valid cluster.  */
+            last_cluster =  cluster;
+
+            /* Setup for the next cluster.  */
+            cluster =  contents;
+
+            /* Determine if this is the last written cluster.  */
+            if (bytes_remaining >= bytes_per_cluster)
+            {
+
+                /* Still more seeking, just decrement the working byte offset.  */
+                bytes_remaining =  bytes_remaining - bytes_per_cluster;
+            }
+            else
+            {
+
+                /* This is the cluster that contains the seek position.  */
+                break;
+            }
+        }
+        
+        /* Check for errors in traversal of the FAT chain.  */
+        if (size > (((ULONG64) bytes_per_cluster) * ((ULONG64) cluster_count)))
+        {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+            FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* This is an error that suggests a corrupt file.  */
+            return(FX_FILE_CORRUPT);
+        }
+
+        /* Position the pointers to the new offset.  */
+        file_ptr -> fx_file_current_physical_cluster =  last_cluster;
+        file_ptr -> fx_file_current_relative_cluster =  cluster_count - 1;
+        file_ptr -> fx_file_current_logical_sector =    ((ULONG)media_ptr -> fx_media_data_sector_start) +
+            (((ULONG64)file_ptr -> fx_file_current_physical_cluster - FX_FAT_ENTRY_START) *
+             ((ULONG)media_ptr -> fx_media_sectors_per_cluster)) +
+            (bytes_remaining / (ULONG)media_ptr -> fx_media_bytes_per_sector);
+        file_ptr -> fx_file_current_relative_sector =   (UINT)((bytes_remaining / (ULONG)media_ptr -> fx_media_bytes_per_sector));
+        file_ptr -> fx_file_current_file_offset =       size;
+        file_ptr -> fx_file_current_logical_offset =    (ULONG)bytes_remaining % ((ULONG)media_ptr -> fx_media_bytes_per_sector);
+    }
+
+    /* Determine how many clusters are actually in-use now.  */
+    cluster_count =  (ULONG) (file_ptr -> fx_file_current_available_size + (((ULONG64) bytes_per_cluster) - ((ULONG64) 1)))/bytes_per_cluster;
+
+    /* Save the number of clusters in-use.  */
+    file_ptr -> fx_file_total_clusters =  cluster_count;
+
+    /* At this point, we are ready to walk list of clusters to find the clusters
+       that can be released.  */
+    cluster =           file_ptr -> fx_file_first_physical_cluster;
+#ifdef FX_ENABLE_EXFAT
+    original_last_physical_cluster = file_ptr -> fx_file_last_physical_cluster;
+#endif /* FX_ENABLE_EXFAT */
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    /* Is this the last used cluster?  */
+    if ((cluster_count == 0) && (media_ptr -> fx_media_fault_tolerant_enabled))
+    {
+#ifdef FX_ENABLE_EXFAT
+        if (!(file_ptr -> fx_file_dir_entry.fx_dir_entry_dont_use_fat & 1))
+        {
+#endif /* FX_ENABLE_EXFAT */
+
+            /* Set undo log. */
+            status = _fx_fault_tolerant_set_FAT_chain(media_ptr, FX_FALSE, FX_FREE_CLUSTER,
+                                                      media_ptr -> fx_media_fat_last, cluster, media_ptr -> fx_media_fat_last);
+
+            /* Determine if the write was successful.  */
+            if (status != FX_SUCCESS)
+            {
+
+                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* Return the error code.  */
+                return(status);
+            }
+#ifdef FX_ENABLE_EXFAT
+        }
+        else
+        {
+
+            /* Set undo log. */
+            status = _fx_fault_tolerant_set_FAT_chain(media_ptr, FX_TRUE, FX_FREE_CLUSTER,
+                                                      media_ptr -> fx_media_fat_last, cluster, file_ptr -> fx_file_last_physical_cluster + 1);
+
+            /* Determine if the write was successful.  */
+            if (status != FX_SUCCESS)
+            {
+
+                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* Return the error code.  */
+                return(status);
+            }
+        }
+#endif /* FX_ENABLE_EXFAT && FX_ENABLE_FAULT_TOLERANT */
+
+        file_ptr -> fx_file_last_physical_cluster =  cluster;
+    }
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Follow the link of FAT entries.  */
+    while ((cluster >= FX_FAT_ENTRY_START) && (cluster < media_ptr -> fx_media_fat_reserved))
+    {
+#ifdef FX_ENABLE_EXFAT
+        if (file_ptr -> fx_file_dir_entry.fx_dir_entry_dont_use_fat & 1)
+        {
+            if (cluster >= original_last_physical_cluster)
+            {
+                contents = FX_LAST_CLUSTER_exFAT;
+            }
+            else
+            {
+                contents = cluster + 1;
+            }
+        }
+        else
+        {
+#endif /* FX_ENABLE_EXFAT */
+
+            /* Read the current cluster entry from the FAT.  */
+            status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &contents);
+
+            /* Check the return value.  */
+            if (status != FX_SUCCESS)
+            {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* Return the error status.  */
+                return(status);
+            }
+#ifdef FX_ENABLE_EXFAT
+        }
+#endif /* FX_ENABLE_EXFAT */
+
+        /* Determine if are more clusters to release.  */
+        if (cluster_count > 0)
+        {
+
+            /* Decrement the number of clusters.  */
+            cluster_count--;
+
+            /* Is this the last used cluster?  */
+            if (cluster_count == 0)
+            {
+#ifdef FX_ENABLE_EXFAT
+                if (!(file_ptr -> fx_file_dir_entry.fx_dir_entry_dont_use_fat & 1))
+#endif /* FX_ENABLE_EXFAT */
+                {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                    if (media_ptr -> fx_media_fault_tolerant_enabled)
+                    {
+
+                        /* Set undo phase. */
+                        media_ptr -> fx_media_fault_tolerant_state |= FX_FAULT_TOLERANT_STATE_SET_FAT_CHAIN;
+
+                        /* Read the current cluster entry from the FAT.  */
+                        status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &contents);
+
+                        /* Check the return value.  */
+                        if (status != FX_SUCCESS)
+                        {
+
+                            FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+
+                            /* Release media protection.  */
+                            FX_UNPROTECT
+
+                            /* Return the error status.  */
+                            return(status);
+                        }
+
+                        /* Set undo log. */
+                        status = _fx_fault_tolerant_set_FAT_chain(media_ptr, FX_FALSE, cluster,
+                                                                  media_ptr -> fx_media_fat_last, contents, media_ptr -> fx_media_fat_last);
+
+                        /* Determine if the write was successful.  */
+                        if (status != FX_SUCCESS)
+                        {
+
+                            FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+
+                            /* Release media protection.  */
+                            FX_UNPROTECT
+
+                            /* Return the error code.  */
+                            return(status);
+                        }
+                    }
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                    /* Yes, it should be designated as last cluster.  */
+                    status = _fx_utility_FAT_entry_write(media_ptr, cluster, media_ptr -> fx_media_fat_last);
+
+                    /* Check the return value.  */
+                    if (status)
+                    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                        /* Release media protection.  */
+                        FX_UNPROTECT
+
+                        /* Return the error status.  */
+                        return(status);
+                    }
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                    if (media_ptr -> fx_media_fault_tolerant_enabled)
+                    {
+
+                        /* Clear undo phase. */
+                        media_ptr -> fx_media_fault_tolerant_state &= (UCHAR)(~FX_FAULT_TOLERANT_STATE_SET_FAT_CHAIN & 0xff);
+                    }
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+                }
+#if defined(FX_ENABLE_EXFAT) && defined(FX_ENABLE_FAULT_TOLERANT)
+                else if (media_ptr -> fx_media_fault_tolerant_enabled)
+                {
+
+                    /* Set undo log. */
+                    status = _fx_fault_tolerant_set_FAT_chain(media_ptr, FX_TRUE, cluster,
+                                                              media_ptr -> fx_media_fat_last, contents, file_ptr -> fx_file_last_physical_cluster + 1);
+
+                    /* Determine if the write was successful.  */
+                    if (status != FX_SUCCESS)
+                    {
+
+                        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+
+                        /* Release media protection.  */
+                        FX_UNPROTECT
+
+                        /* Return the error code.  */
+                        return(status);
+                    }
+                }
+#endif /* FX_ENABLE_EXFAT && FX_ENABLE_FAULT_TOLERANT */
+
+                file_ptr -> fx_file_last_physical_cluster =  cluster;
+
+#ifdef FX_FAULT_TOLERANT
+
+                /* Flush the cached individual FAT entries.  */
+                status = _fx_utility_FAT_flush(media_ptr);
+
+                /* Check the return value.  */
+                if (status)
+                {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                    FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                    /* Release media protection.  */
+                    FX_UNPROTECT
+
+                    /* Return the error status.  */
+                    return(status);
+                }
+#endif
+            }
+        }
+        else
+        {
+
+            /* This is a cluster after the clusters used by the file, release
+               it back to the media.  */
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+            if (media_ptr -> fx_media_fault_tolerant_enabled == FX_FALSE)
+            {
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+#ifdef FX_ENABLE_EXFAT
+                if (!(file_ptr -> fx_file_dir_entry.fx_dir_entry_dont_use_fat & 1))
+                {
+#endif /* FX_ENABLE_EXFAT */
+                    status = _fx_utility_FAT_entry_write(media_ptr, cluster, FX_FREE_CLUSTER);
+
+                    /* Check the return value.  */
+                    if (status)
+                    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                        /* Release media protection.  */
+                        FX_UNPROTECT
+
+                        /* Return the error status.  */
+                        return(status);
+                    }
+#ifdef FX_ENABLE_EXFAT
+                }
+
+                if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+                {
+
+                    /* Mark the cluster as free.  */
+                    _fx_utility_exFAT_cluster_state_set(media_ptr, cluster, FX_EXFAT_BITMAP_CLUSTER_FREE);
+                }
+#endif /* FX_ENABLE_EXFAT */
+
+                /* Increment the number of available clusters.  */
+                media_ptr -> fx_media_available_clusters++;
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+            }
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+        }
+
+        /* Setup for the next cluster.  */
+        cluster =  contents;
+    }
+
+    /* Determine if we need to adjust the number of leading consecutive clusters.  */
+    if (file_ptr -> fx_file_consecutive_cluster > file_ptr -> fx_file_total_clusters)
+    {
+
+        /* Adjust the leading consecutive cluster count. */
+        file_ptr -> fx_file_consecutive_cluster =  file_ptr -> fx_file_total_clusters;
+    }
+
+    /* Determine if the file available size has been truncated to zero.  */
+    if (file_ptr -> fx_file_current_available_size == 0)
+    {
+
+        /* Yes, the first cluster has already been released.  Update the file info
+           to indicate the file has no clusters.  */
+        file_ptr -> fx_file_last_physical_cluster =     0;
+        file_ptr -> fx_file_first_physical_cluster =    0;
+        file_ptr -> fx_file_current_physical_cluster =  0;
+        file_ptr -> fx_file_current_logical_sector =    0;
+        file_ptr -> fx_file_current_relative_cluster =  0;
+        file_ptr -> fx_file_current_relative_sector =   0;
+        file_ptr -> fx_file_current_available_size =    0;
+        file_ptr -> fx_file_consecutive_cluster =       1;
+    }
+
+#ifndef FX_DONT_UPDATE_OPEN_FILES
+
+    /* Search the opened files list to see if the same file is opened for reading.  */
+    open_count =  media_ptr -> fx_media_opened_file_count;
+    search_ptr =  media_ptr -> fx_media_opened_file_list;
+    while (open_count)
+    {
+
+        /* Is this file the same file opened for reading?  */
+        if ((search_ptr != file_ptr) &&
+            (search_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector ==
+             file_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector) &&
+            (search_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset ==
+             file_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset))
+        {
+
+            /* Yes, the same file is opened for reading.  */
+
+            /* Setup the new file size.  */
+            search_ptr -> fx_file_current_file_size =  size;
+
+            /* Setup the new total clusters.  */
+            search_ptr -> fx_file_total_clusters =  file_ptr -> fx_file_total_clusters;
+
+            /* Copy the directory entry.  */
+            search_ptr -> fx_file_dir_entry.fx_dir_entry_cluster =      file_ptr -> fx_file_dir_entry.fx_dir_entry_cluster;
+            search_ptr -> fx_file_dir_entry.fx_dir_entry_file_size =    file_ptr -> fx_file_dir_entry.fx_dir_entry_file_size;
+            search_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector =   file_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector;
+            search_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset =  file_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset;
+
+            /* Setup the other file parameters.  */
+            search_ptr -> fx_file_last_physical_cluster =     file_ptr -> fx_file_last_physical_cluster;
+            search_ptr -> fx_file_first_physical_cluster =    file_ptr -> fx_file_first_physical_cluster;
+            search_ptr -> fx_file_current_available_size =    file_ptr -> fx_file_current_available_size;
+            search_ptr -> fx_file_consecutive_cluster =       file_ptr -> fx_file_consecutive_cluster;
+
+            /* Determine if the truncated file is smaller than the current file offset.  */
+            if (search_ptr -> fx_file_current_file_offset > size)
+            {
+
+                /* Yes, the current file parameters need to be changed since the file was
+                   truncated to a position prior to the current file position.  */
+
+                /* Calculate the number of bytes per cluster.  */
+                bytes_per_cluster =  ((ULONG)media_ptr -> fx_media_bytes_per_sector) *
+                    ((ULONG)media_ptr -> fx_media_sectors_per_cluster);
+
+                /* At this point, we are ready to walk list of clusters to setup the
+                   seek position of this file.  */
+                cluster =           search_ptr -> fx_file_first_physical_cluster;
+                bytes_remaining =   size;
+                last_cluster =      0;
+                cluster_count =     0;
+
+                /* Follow the link of FAT entries.  */
+                while ((cluster >= FX_FAT_ENTRY_START) && (cluster < media_ptr -> fx_media_fat_reserved))
+                {
+
+                    /* Increment the number of clusters.  */
+                    cluster_count++;
+
+#ifdef FX_ENABLE_EXFAT
+                    if (file_ptr -> fx_file_dir_entry.fx_dir_entry_dont_use_fat & 1)
+                    {
+                        if (cluster >= file_ptr -> fx_file_last_physical_cluster)
+                        {
+                            contents = FX_LAST_CLUSTER_exFAT;
+                        }
+                        else
+                        {
+                            contents = cluster + 1;
+                        }
+                    }
+                    else
+                    {
+#endif /* FX_ENABLE_EXFAT */
+
+                        /* Read the current cluster entry from the FAT.  */
+                        status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &contents);
+
+                        /* Check the return value.  */
+                        if (status != FX_SUCCESS)
+                        {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                            FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                            /* Release media protection.  */
+                            FX_UNPROTECT
+
+                            /* Return the error status.  */
+                            return(status);
+                        }
+#ifdef FX_ENABLE_EXFAT
+                    }
+#endif /* FX_ENABLE_EXFAT */
+
+                    /* Save the last valid cluster.  */
+                    last_cluster =  cluster;
+
+                    /* Setup for the next cluster.  */
+                    cluster =  contents;
+
+                    /* Determine if this is the last written cluster.  */
+                    if (bytes_remaining >= bytes_per_cluster)
+                    {
+
+                        /* Still more seeking, just decrement the working byte offset.  */
+                        bytes_remaining =  bytes_remaining - bytes_per_cluster;
+                    }
+                    else
+                    {
+
+                        /* This is the cluster that contains the seek position.  */
+                        break;
+                    }
+                }
+
+                /* Check for errors in traversal of the FAT chain.  */
+                if (size > (((ULONG64) bytes_per_cluster) * ((ULONG64) cluster_count)))
+                {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                    FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                    /* Release media protection.  */
+                    FX_UNPROTECT
+
+                    /* This is an error that suggests a corrupt file.  */
+                    return(FX_FILE_CORRUPT);
+                }
+
+                /* Position the pointers to the new offset.  */
+
+                /* Determine if there is at least one cluster.  */
+                if (cluster_count)
+                {
+
+                    /* Calculate real file parameters.  */
+                    search_ptr -> fx_file_current_physical_cluster =  last_cluster;
+                    search_ptr -> fx_file_current_relative_cluster =  cluster_count - 1;
+                    search_ptr -> fx_file_current_logical_sector =    ((ULONG)media_ptr -> fx_media_data_sector_start) +
+                        (((ULONG64)search_ptr -> fx_file_current_physical_cluster - FX_FAT_ENTRY_START) *
+                         ((ULONG)media_ptr -> fx_media_sectors_per_cluster)) +
+                        (bytes_remaining / (ULONG)media_ptr -> fx_media_bytes_per_sector);
+                    search_ptr -> fx_file_current_relative_sector =   (UINT)((bytes_remaining / (ULONG)media_ptr -> fx_media_bytes_per_sector));
+                    search_ptr -> fx_file_current_file_offset =       size;
+                    search_ptr -> fx_file_current_logical_offset =    (ULONG)bytes_remaining % ((ULONG)media_ptr -> fx_media_bytes_per_sector);
+                }
+                else
+                {
+
+                    /* Calculate zero-length file parameters.  */
+                    search_ptr -> fx_file_current_physical_cluster =  0;
+                    search_ptr -> fx_file_current_relative_cluster =  0;
+                    search_ptr -> fx_file_current_logical_sector =    0;
+                    search_ptr -> fx_file_current_relative_sector =   0;
+                    search_ptr -> fx_file_current_file_offset =       0;
+                    search_ptr -> fx_file_current_logical_offset =    0;
+                }
+            }
+        }
+
+        /* Adjust the pointer and decrement the search count.  */
+        search_ptr =  search_ptr -> fx_file_opened_next;
+        open_count--;
+    }
+#endif
+
+#ifdef FX_FAULT_TOLERANT
+
+    /* Flush the cached individual FAT entries */
+    status = _fx_utility_FAT_flush(media_ptr);
+
+    /* Check the return value.  */
+    if (status)
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the error status.  */
+        return(status);
+    }
+#ifdef FX_ENABLE_EXFAT
+    /* Flush Bit Map.  */
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+        _fx_utility_exFAT_bitmap_flush(media_ptr);
+    }
+#endif /* FX_ENABLE_EXFAT */
+
+#endif
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    if (media_ptr -> fx_media_fault_tolerant_enabled &&
+        (media_ptr -> fx_media_fault_tolerant_state & FX_FAULT_TOLERANT_STATE_STARTED))
+    {
+
+        /* Copy the new file size into the directory entry.  */
+        file_ptr -> fx_file_dir_entry.fx_dir_entry_file_size = file_ptr -> fx_file_current_file_size;
+    }
+
+    /* Write the directory entry to the media.  */
+#ifdef FX_ENABLE_EXFAT
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+
+        status = _fx_directory_exFAT_entry_write(media_ptr, &(file_ptr -> fx_file_dir_entry), UPDATE_STREAM);
+    }
+    else
+    {
+#endif /* FX_ENABLE_EXFAT */
+        status =  _fx_directory_entry_write(media_ptr, &(file_ptr -> fx_file_dir_entry));
+#ifdef FX_ENABLE_EXFAT
+    }
+#endif /* FX_ENABLE_EXFAT */
+
+    /* Check for a good status.  */
+    if (status != FX_SUCCESS)
+    {
+
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Error writing the directory.  */
+        return(status);
+    }
+
+    /* End transaction. */
+    status = _fx_fault_tolerant_transaction_end(media_ptr);
+
+    /* Check for a bad status.  */
+    if (status != FX_SUCCESS)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the bad status.  */
+        return(status);
+    }
+
+    /* Update maximum size used if necessary. */
+    if (size < file_ptr -> fx_file_maximum_size_used)
+    {
+        file_ptr -> fx_file_maximum_size_used = size;
+    }
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* Truncate is complete, return successful status.  */
+    return(FX_SUCCESS);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_open.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_open.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_open.c	(revision 30)
@@ -0,0 +1,606 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_directory.h"
+#include "fx_file.h"
+#include "fx_utility.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_file_open                                       PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function first attempts to find the specified file.  If found, */
+/*    the open request is validated and the file is opened.  During the   */
+/*    opening process, all of the FAT entries for this file are examined  */
+/*    for their integrity.                                                */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    file_ptr                              File control block pointer    */
+/*    file_name                             Name pointer                  */
+/*    open_type                             Type of open requested        */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_search                  Search for the file name in   */
+/*                                          the directory structure       */
+/*    _fx_utility_FAT_entry_read            Read a FAT entry              */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s), and      */
+/*                                            added conditional to        */
+/*                                            disable fast open and       */
+/*                                            consecutive detect,         */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_file_open(FX_MEDIA *media_ptr, FX_FILE *file_ptr, CHAR *file_name, UINT open_type)
+{
+
+UINT     status;
+#ifndef FX_DISABLE_CONSECUTIVE_DETECT
+UINT     leading_consecutive;
+#endif /* FX_DISABLE_CONSECUTIVE_DETECT */
+ULONG    cluster;
+ULONG    contents = 0;
+ULONG    open_count;
+FX_FILE *tail_ptr;
+FX_FILE *search_ptr;
+ULONG    bytes_per_cluster;
+UINT     last_cluster;
+ULONG    cluster_count;
+ULONG64  bytes_available;
+ULONG64  bytes_remaining;
+ULONG    fat_last;
+#ifndef FX_DISABLE_FAST_OPEN
+UINT     fast_open;
+#endif /* FX_DISABLE_FAST_OPEN */
+UCHAR    not_a_file_attr;
+
+
+    /* Check the media to make sure it is open.  */
+    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
+    {
+
+        /* Return the media not opened error.  */
+        return(FX_MEDIA_NOT_OPEN);
+    }
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of times this service has been called.  */
+    media_ptr -> fx_media_file_opens++;
+#endif
+
+    /* Clear the notify function. */
+    file_ptr -> fx_file_write_notify = FX_NULL;
+
+    /* Determine the type of FAT and setup variables accordingly.  */
+#ifdef FX_ENABLE_EXFAT
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+        fat_last        = FX_LAST_CLUSTER_exFAT;
+        not_a_file_attr = FX_DIRECTORY;
+    }
+    else if (media_ptr -> fx_media_FAT_type == FX_FAT32)
+#else
+    if (media_ptr -> fx_media_32_bit_FAT)
+#endif /* FX_ENABLE_EXFAT */
+    {
+        fat_last        = FX_LAST_CLUSTER_1_32;
+        not_a_file_attr = FX_DIRECTORY | FX_VOLUME;
+    }
+    else
+    {
+        fat_last        = FX_LAST_CLUSTER_1;
+        not_a_file_attr = FX_DIRECTORY | FX_VOLUME;
+    }
+
+#ifndef FX_DISABLE_FAST_OPEN
+    /* Determine if a fast open is selected.  */
+    if (open_type == FX_OPEN_FOR_READ_FAST)
+    {
+
+        /* Yes, convert the open type to a standard read.  */
+        open_type =  FX_OPEN_FOR_READ;
+
+        /* Set the open fast flag.  */
+        fast_open =  FX_TRUE;
+    }
+    else
+    {
+
+        /* A fast open is not selected, set the flag to false.  */
+        fast_open =  FX_FALSE;
+    }
+#endif /* FX_DISABLE_FAST_OPEN */
+
+    /* If trace is enabled, register this object.  */
+    FX_TRACE_OBJECT_REGISTER(FX_TRACE_OBJECT_TYPE_FILE, file_ptr, file_name, 0, 0)
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_FILE_OPEN, media_ptr, file_ptr, file_name, open_type, FX_TRACE_FILE_EVENTS, 0, 0)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+    /* Setup file name pointer.  */
+    file_ptr -> fx_file_dir_entry.fx_dir_entry_name =  file_ptr -> fx_file_name_buffer;
+    file_ptr -> fx_file_dir_entry.fx_dir_entry_short_name[0] =  0;
+
+    /* Search the system for the supplied file name.  */
+    status =  _fx_directory_search(media_ptr, file_name, &(file_ptr -> fx_file_dir_entry), FX_NULL, FX_NULL);
+
+    /* Determine if the search was successful.  */
+    if (status != FX_SUCCESS)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the error code.  */
+        return(status);
+    }
+
+    /* Check to make sure the found entry is a file.  */
+    if (file_ptr -> fx_file_dir_entry.fx_dir_entry_attributes & not_a_file_attr)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the not a file error code.  */
+        return(FX_NOT_A_FILE);
+    }
+
+#ifdef FX_SINGLE_OPEN_LEGACY
+    /* Check to make sure the access is okay.  */
+    if (open_type == FX_OPEN_FOR_READ)
+    {
+
+        /* Check the list of open files for others open for writing.  */
+        open_count =  media_ptr -> fx_media_opened_file_count;
+        search_ptr =  media_ptr -> fx_media_opened_file_list;
+        while (open_count)
+        {
+
+            /* Look at each opened file to see if the same file is opened
+               for writing.  */
+            if ((search_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector ==
+                 file_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector) &&
+                (search_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset ==
+                 file_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset) &&
+                (search_ptr -> fx_file_open_mode))
+            {
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* The file has been opened for writing by a previous call.  */
+                return(FX_ACCESS_ERROR);
+            }
+
+            /* Adjust the pointer and decrement the search count.  */
+            search_ptr =  search_ptr -> fx_file_opened_next;
+            open_count--;
+        }
+    }
+    else
+#else
+    if (open_type == FX_OPEN_FOR_WRITE)
+#endif
+    {
+
+        /* A open for write request is present, check the file attributes
+           and the list of open files for any other open instance of
+           this file.  */
+        if (media_ptr -> fx_media_driver_write_protect)
+        {
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* Return write protect error.  */
+            return(FX_WRITE_PROTECT);
+        }
+
+        if (file_ptr -> fx_file_dir_entry.fx_dir_entry_attributes & (UCHAR)(FX_READ_ONLY))
+        {
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* Return the not a file error code.  */
+            return(FX_ACCESS_ERROR);
+        }
+
+        /* Also search the opened files to see if this file is currently
+           opened.  */
+        open_count =  media_ptr -> fx_media_opened_file_count;
+        search_ptr =  media_ptr -> fx_media_opened_file_list;
+        while (open_count)
+        {
+
+            /* Look at each opened file to see if the same file is already opened.  */
+#ifdef FX_SINGLE_OPEN_LEGACY
+            if ((search_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector ==
+                 file_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector) &&
+                (search_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset ==
+                 file_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset))
+#else
+            /* Look at each opened file to see if the same file is already opened
+               for writing.  */
+            if ((search_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector ==
+                 file_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector) &&
+                (search_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset ==
+                 file_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset) &&
+                (search_ptr -> fx_file_open_mode == FX_OPEN_FOR_WRITE))
+#endif
+            {
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* The file is currently open.  */
+                return(FX_ACCESS_ERROR);
+            }
+
+            /* Adjust the pointer and decrement the search count.  */
+            search_ptr =  search_ptr -> fx_file_opened_next;
+            open_count--;
+        }
+    }
+
+    /* At this point, we are ready to walk list of clusters to setup the
+       initial condition of this file as well as to verify its integrity.  */
+    cluster =           file_ptr -> fx_file_dir_entry.fx_dir_entry_cluster;
+    bytes_remaining =   file_ptr -> fx_file_dir_entry.fx_dir_entry_file_size;
+    bytes_per_cluster = ((ULONG)media_ptr -> fx_media_bytes_per_sector) *
+        ((ULONG)media_ptr -> fx_media_sectors_per_cluster);
+    file_ptr -> fx_file_current_physical_cluster =  0;
+
+    /* Check for invalid value.  */
+    if (bytes_per_cluster == 0)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Invalid media, return error.  */
+        return(FX_MEDIA_INVALID);
+    }
+
+    last_cluster =      0;
+    cluster_count =     0;
+
+#ifndef FX_DISABLE_CONSECUTIVE_DETECT
+    leading_consecutive = 1;
+#endif /* FX_DISABLE_CONSECUTIVE_DETECT */
+    file_ptr -> fx_file_consecutive_cluster = 1;
+#ifndef FX_DISABLE_FAST_OPEN
+
+    /* Determine if the file is being open for reading with the fast option.  */
+    if (fast_open)
+    {
+
+        /* Calculate the bytes available.  */
+        bytes_available =  ((bytes_remaining + bytes_per_cluster - 1) / bytes_per_cluster) * bytes_per_cluster;
+
+#ifdef FX_ENABLE_EXFAT
+        if (bytes_remaining && (file_ptr -> fx_file_dir_entry.fx_dir_entry_dont_use_fat & 1))
+        {
+            cluster_count =
+                (ULONG)((file_ptr -> fx_file_dir_entry.fx_dir_entry_file_size + bytes_per_cluster - 1) /
+                        bytes_per_cluster);
+            file_ptr -> fx_file_consecutive_cluster = cluster_count;
+        }
+#endif /* FX_ENABLE_EXFAT */
+    }
+    else
+#endif /* FX_DISABLE_FAST_OPEN */
+    {
+#ifdef FX_ENABLE_EXFAT
+
+        /* File is open for writing... walk the FAT chain to position to the end.  */
+
+        if (bytes_remaining && (file_ptr -> fx_file_dir_entry.fx_dir_entry_dont_use_fat & 1))
+        {
+            cluster_count =
+                (ULONG)((file_ptr -> fx_file_dir_entry.fx_dir_entry_file_size + bytes_per_cluster - 1) /
+                        bytes_per_cluster);
+
+            last_cluster = cluster + cluster_count - 1;
+
+            file_ptr -> fx_file_consecutive_cluster = cluster_count;
+
+            file_ptr -> fx_file_current_physical_cluster = last_cluster;
+
+            file_ptr -> fx_file_current_relative_cluster = cluster_count - 1;
+
+            bytes_remaining %= bytes_per_cluster;
+
+            if (!bytes_remaining)
+            {
+                if (file_ptr -> fx_file_dir_entry.fx_dir_entry_available_file_size >
+                    file_ptr -> fx_file_dir_entry.fx_dir_entry_file_size)
+                {
+                    file_ptr -> fx_file_current_physical_cluster = last_cluster + 1;
+                    file_ptr -> fx_file_current_relative_cluster++;
+                }
+                else
+                {
+                    bytes_remaining = bytes_per_cluster;
+                }
+            }
+
+            bytes_available =
+                (ULONG)((file_ptr -> fx_file_dir_entry.fx_dir_entry_available_file_size + bytes_per_cluster - 1) /
+                        bytes_per_cluster);
+            bytes_available *= bytes_per_cluster;
+        }
+        else
+        {
+#endif /* FX_ENABLE_EXFAT */
+
+            /* Follow the link of FAT entries.  */
+            while ((cluster >= FX_FAT_ENTRY_START) && (cluster < media_ptr -> fx_media_fat_reserved))
+            {
+
+                /* Increment the number of clusters.  */
+                cluster_count++;
+
+                /* Read the current cluster entry from the FAT.  */
+                status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &contents);
+
+                /* Check the return value.  */
+                if (status != FX_SUCCESS)
+                {
+
+                    /* Release media protection.  */
+                    FX_UNPROTECT
+
+                    /* Return the error status.  */
+                    return(status);
+                }
+
+                /* Determine if the cluster is invalid (points to itself) or the count exceeds the total number of clusters.  */
+                if ((cluster == contents) || (cluster_count > media_ptr -> fx_media_total_clusters))
+                {
+
+                    /* Release media protection.  */
+                    FX_UNPROTECT
+
+                    /* Return the bad status.  */
+                    return(FX_FAT_READ_ERROR);
+                }
+
+#ifndef FX_DISABLE_CONSECUTIVE_DETECT
+
+                /* Check if present and next clusters are consecutive */
+                if (cluster + 1 == contents)
+                {
+            
+                    /* Determine if clusters are consecutive so far.  */
+                    if (leading_consecutive)
+                    {
+
+                        /* Yes, increment the number of leading consecutive clusters.  */
+                        file_ptr -> fx_file_consecutive_cluster++;
+                    }
+                }
+                else
+                {
+
+                    /* The clusters are no longer consecutive, clear the consecutive flag.  */
+                    leading_consecutive = 0;
+                }
+#endif /* FX_DISABLE_CONSECUTIVE_DETECT */
+
+                /* Save the last valid cluster.  */
+                last_cluster =  cluster;
+
+                /* Setup for the next cluster.  */
+                cluster =  contents;
+
+                /* Determine if this is the last written cluster.  We need to remember this
+                   for open for writing.  */
+                if (bytes_remaining > bytes_per_cluster)
+                {
+
+                    /* Still more written clusters, just decrement the counter.  */
+                    bytes_remaining =  bytes_remaining - bytes_per_cluster;
+                }
+                else if (!file_ptr -> fx_file_current_physical_cluster)
+                {
+
+                    /* Remember this cluster number.  */
+                    file_ptr -> fx_file_current_physical_cluster =  last_cluster;
+
+                    /* Remember the relative cluster.  */
+                    file_ptr -> fx_file_current_relative_cluster =  cluster_count - 1;
+
+                    /* If the remaining bytes exactly fits the cluster size, check for
+                       a possible adjustment to the next cluster.  */
+                    if ((bytes_remaining == bytes_per_cluster) &&
+                        (cluster >= FX_FAT_ENTRY_START) && (cluster < media_ptr -> fx_media_fat_reserved))
+                    {
+
+                        /* We need to position to next allocated cluster.  */
+                        file_ptr -> fx_file_current_physical_cluster =  cluster;
+                        file_ptr -> fx_file_current_relative_cluster++;
+
+                        /* Clear the remaining bytes.  */
+                        bytes_remaining =  0;
+                    }
+                }
+            }
+
+            /* Determine if the number of clusters is large enough to support the
+               specified file size.  */
+            bytes_available =  ((ULONG64)media_ptr -> fx_media_bytes_per_sector) *
+                ((ULONG64)media_ptr -> fx_media_sectors_per_cluster) *
+                ((ULONG64)cluster_count);
+
+            /* Check the bytes available in the cluster chain against the directory entry file size.  */
+            if ((bytes_available < file_ptr -> fx_file_dir_entry.fx_dir_entry_file_size) ||
+                ((cluster_count) && (contents < fat_last)))
+            {
+                /* File is corrupt, release media protection.  */
+                FX_UNPROTECT
+
+                /* Return a corrupt file error status.  */
+                return(FX_FILE_CORRUPT);
+            }
+#ifdef FX_ENABLE_EXFAT
+        }
+#endif /* FX_ENABLE_EXFAT */
+    }
+
+    /* The file is okay, populate the file control block and complete the
+       file open process.  */
+    file_ptr -> fx_file_id =                        FX_FILE_ID;
+    file_ptr -> fx_file_name =                      file_ptr -> fx_file_name_buffer;
+    file_ptr -> fx_file_media_ptr =                 media_ptr;
+    file_ptr -> fx_file_open_mode =                 open_type;
+    file_ptr -> fx_file_modified =                  FX_FALSE;
+    file_ptr -> fx_file_total_clusters =            cluster_count;
+    file_ptr -> fx_file_first_physical_cluster =    file_ptr -> fx_file_dir_entry.fx_dir_entry_cluster;
+    file_ptr -> fx_file_last_physical_cluster =     last_cluster;
+    file_ptr -> fx_file_current_file_size =         file_ptr -> fx_file_dir_entry.fx_dir_entry_file_size;
+    file_ptr -> fx_file_current_available_size =    bytes_available;
+    file_ptr -> fx_file_disable_burst_cache =       FX_FALSE;
+
+    /* Set the current settings based on how the file was opened.  */
+    if (open_type == FX_OPEN_FOR_READ)
+    {
+
+        /* Position the pointers to the beginning of the file.  */
+        file_ptr -> fx_file_current_physical_cluster =  file_ptr -> fx_file_first_physical_cluster;
+        file_ptr -> fx_file_current_relative_cluster =  0;
+        file_ptr -> fx_file_current_logical_sector =    ((ULONG)media_ptr -> fx_media_data_sector_start) +
+            (((ULONG64)(file_ptr -> fx_file_first_physical_cluster - FX_FAT_ENTRY_START)) *
+             ((ULONG)media_ptr -> fx_media_sectors_per_cluster));
+        file_ptr -> fx_file_current_relative_sector =   0;
+        file_ptr -> fx_file_current_logical_offset =    0;
+        file_ptr -> fx_file_current_file_offset =       0;
+    }
+    else
+    {
+
+        /* Open for writing - position the pointers to the end of the file.  */
+
+        /* Determine if the remaining bytes fit exactly into the cluster size.  */
+        if (bytes_remaining == bytes_per_cluster)
+        {
+
+            /* Position to the end of the cluster.  */
+            file_ptr -> fx_file_current_logical_sector =    ((ULONG)media_ptr -> fx_media_data_sector_start) +
+                (((ULONG64)file_ptr -> fx_file_current_physical_cluster - FX_FAT_ENTRY_START) *
+                 ((ULONG)media_ptr -> fx_media_sectors_per_cluster)) +
+                ((ULONG)(((bytes_remaining - 1) / (ULONG)media_ptr -> fx_media_bytes_per_sector)));
+            file_ptr -> fx_file_current_relative_sector =   (ULONG)(((bytes_remaining - 1) / (ULONG)media_ptr -> fx_media_bytes_per_sector));
+            file_ptr -> fx_file_current_file_offset =       file_ptr -> fx_file_current_file_size;
+            file_ptr -> fx_file_current_logical_offset =    media_ptr -> fx_media_bytes_per_sector;
+        }
+        else
+        {
+
+            /* Position file parameters at end of last cluster allocation.  */
+            file_ptr -> fx_file_current_logical_sector =    ((ULONG)media_ptr -> fx_media_data_sector_start) +
+                (((ULONG64)file_ptr -> fx_file_current_physical_cluster - FX_FAT_ENTRY_START) *
+                 ((ULONG)media_ptr -> fx_media_sectors_per_cluster)) +
+                ((ULONG)((bytes_remaining / (ULONG)media_ptr -> fx_media_bytes_per_sector)));
+            file_ptr -> fx_file_current_relative_sector =   (ULONG)((bytes_remaining / (ULONG)media_ptr -> fx_media_bytes_per_sector));
+            file_ptr -> fx_file_current_file_offset =       file_ptr -> fx_file_current_file_size;
+            file_ptr -> fx_file_current_logical_offset =    (ULONG)bytes_remaining % ((ULONG)media_ptr -> fx_media_bytes_per_sector);
+        }
+    }
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    /* By default, the whole file is used. */
+    file_ptr -> fx_file_maximum_size_used = file_ptr -> fx_file_current_file_size;
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Place newly opened file on the list of open files for
+       this media.  First, check for an empty list.  */
+    if (media_ptr -> fx_media_opened_file_list)
+    {
+
+        /* Pickup tail pointer.  */
+        tail_ptr =  (media_ptr -> fx_media_opened_file_list) -> fx_file_opened_previous;
+
+        /* Place the new file in the list.  */
+        (media_ptr -> fx_media_opened_file_list) -> fx_file_opened_previous =  file_ptr;
+        tail_ptr -> fx_file_opened_next =  file_ptr;
+
+        /* Setup this file's opened links.  */
+        file_ptr -> fx_file_opened_previous =  tail_ptr;
+        file_ptr -> fx_file_opened_next =      media_ptr -> fx_media_opened_file_list;
+    }
+    else
+    {
+
+        /* The opened media list is empty.  Add the media to empty list.  */
+        media_ptr -> fx_media_opened_file_list =   file_ptr;
+        file_ptr ->  fx_file_opened_next =         file_ptr;
+        file_ptr ->  fx_file_opened_previous =     file_ptr;
+    }
+
+    /* Increment the opened file counter.  */
+    media_ptr -> fx_media_opened_file_count++;
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* Open is complete, return successful status.  */
+    return(FX_SUCCESS);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_read.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_read.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_read.c	(revision 30)
@@ -0,0 +1,463 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_file.h"
+#include "fx_utility.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_file_read                                       PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function reads the specified number of bytes (or as many as    */
+/*    possible into the buffer supplied by the caller.  The actual number */
+/*    of bytes and the status of the read operation is returned to the    */
+/*    caller.  In addition, various internal file pointers in the file    */
+/*    control block are also updated.                                     */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    file_ptr                              File control block pointer    */
+/*    buffer_ptr                            Buffer pointer                */
+/*    request_size                          Number of bytes requested     */
+/*    actual_size                           Pointer to variable for the   */
+/*                                            number of bytes read        */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_FAT_entry_read            Read a FAT entry              */
+/*    _fx_utility_logical_sector_read       Read a logical sector         */
+/*    _fx_utility_memory_copy               Fast memory copy routine      */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s), verified */
+/*                                            memcpy usage,               */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_file_read(FX_FILE *file_ptr, VOID *buffer_ptr, ULONG request_size, ULONG *actual_size)
+{
+
+UINT                   status;
+ULONG                  bytes_remaining, i;
+ULONG                  copy_bytes;
+UCHAR                 *destination_ptr;
+ULONG                  cluster, next_cluster;
+UINT                   sectors;
+FX_MEDIA              *media_ptr;
+
+#ifdef TX_ENABLE_EVENT_TRACE
+TX_TRACE_BUFFER_ENTRY *trace_event;
+ULONG                  trace_timestamp;
+#endif
+
+
+    /* First, determine if the file is still open.  */
+    if (file_ptr -> fx_file_id != FX_FILE_ID)
+    {
+
+        /* Return the file not open error status.  */
+        return(FX_NOT_OPEN);
+    }
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+    /* Setup pointer to media structure.  */
+    media_ptr =  file_ptr -> fx_file_media_ptr;
+
+    /* Increment the number of times this service has been called.  */
+    media_ptr -> fx_media_file_reads++;
+#endif
+
+    /* Setup pointer to associated media control block.  */
+    media_ptr =  file_ptr -> fx_file_media_ptr;
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_FILE_READ, file_ptr, buffer_ptr, request_size, 0, FX_TRACE_FILE_EVENTS, &trace_event, &trace_timestamp)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+    /* Next, determine if there is any more bytes to read in the file.  */
+    if (file_ptr -> fx_file_current_file_offset >=
+        file_ptr -> fx_file_current_file_size)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* The file is at the end, return the proper status and set the
+           actual size to 0.  */
+        *actual_size =  0;
+        return(FX_END_OF_FILE);
+    }
+
+    /* At this point there is something to read.  */
+
+    /* Setup local buffer pointer.  */
+    destination_ptr =  (UCHAR *)buffer_ptr;
+
+    /* Determine if there are less bytes left in the file than that specified
+       by the request.  If so, adjust the requested size.  */
+    if ((ULONG64)request_size >
+        (file_ptr -> fx_file_current_file_size - file_ptr -> fx_file_current_file_offset))
+    {
+
+        /* Adjust the bytes remaining to what's available.  */
+        request_size =  (ULONG)(file_ptr -> fx_file_current_file_size - file_ptr -> fx_file_current_file_offset);
+    }
+
+    /* Setup the remaining number of bytes to read.  */
+    bytes_remaining =  request_size;
+
+    /* Loop to read all of the bytes.  */
+    while (bytes_remaining)
+    {
+
+        /* Determine if a beginning or ending partial read is required.  */
+        if ((file_ptr -> fx_file_current_logical_offset) ||
+            (bytes_remaining < media_ptr -> fx_media_bytes_per_sector))
+        {
+
+            /* A partial sector read is required.  */
+
+            /* Read the current logical sector.  */
+            status =  _fx_utility_logical_sector_read(media_ptr,
+                                                      file_ptr -> fx_file_current_logical_sector,
+                                                      media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DATA_SECTOR);
+
+            /* Check for good completion status.  */
+            if (status !=  FX_SUCCESS)
+            {
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* Return the error status.  */
+                return(status);
+            }
+
+            /* Copy the appropriate number of bytes into the destination buffer.  */
+            copy_bytes =  media_ptr -> fx_media_bytes_per_sector -
+                file_ptr -> fx_file_current_logical_offset;
+
+            /* Check to see if only a portion of the read sector needs to be
+               copied.  */
+            if (copy_bytes > bytes_remaining)
+            {
+
+                /* Adjust the number of bytes to copy.  */
+                copy_bytes =  bytes_remaining;
+            }
+
+            /* Actually perform the memory copy.  */
+            _fx_utility_memory_copy(((UCHAR *)media_ptr -> fx_media_memory_buffer) + /* Use case of memcpy is verified. */
+                                    file_ptr -> fx_file_current_logical_offset,
+                                    destination_ptr, copy_bytes);
+
+            /* Increment the logical sector byte offset.  */
+            file_ptr -> fx_file_current_logical_offset =
+                file_ptr -> fx_file_current_logical_offset + copy_bytes;
+
+            /* Adjust the remaining bytes to read.  */
+            bytes_remaining =  bytes_remaining - copy_bytes;
+
+            /* Adjust the pointer to the destination buffer.  */
+            destination_ptr =  destination_ptr + copy_bytes;
+        }
+        else
+        {
+
+            /* Attempt to read multiple sectors directly into the destination
+               buffer.  */
+
+            /* Calculate the number of whole sectors to read directly into
+               the destination buffer.  */
+            sectors =  (UINT)(bytes_remaining / media_ptr -> fx_media_bytes_per_sector);
+
+
+            next_cluster = cluster = file_ptr -> fx_file_current_physical_cluster;
+            for (i = (media_ptr -> fx_media_sectors_per_cluster -
+                      file_ptr -> fx_file_current_relative_sector); i < sectors; i += media_ptr -> fx_media_sectors_per_cluster)
+            {
+#ifdef FX_ENABLE_EXFAT
+                if (file_ptr -> fx_file_dir_entry.fx_dir_entry_dont_use_fat & 1)
+                {
+                    cluster++;
+                }
+                else
+                {
+#endif /* FX_ENABLE_EXFAT */
+                    status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
+
+                    /* Determine if an error is present.  */
+                    if ((status != FX_SUCCESS) || (next_cluster < FX_FAT_ENTRY_START) ||
+                        (next_cluster > media_ptr -> fx_media_fat_reserved))
+                    {
+
+                        /* Release media protection.  */
+                        FX_UNPROTECT
+
+                        /* Send error message back to caller.  */
+                        if (status != FX_SUCCESS)
+                        {
+                            return(status);
+                        }
+                        else
+                        {
+                            return(FX_FILE_CORRUPT);
+                        }
+                    }
+
+                    if (next_cluster != cluster + 1)
+                    {
+                        break;
+                    }
+                    else
+                    {
+                        cluster = next_cluster;
+                    }
+#ifdef FX_ENABLE_EXFAT
+                }
+#endif /* FX_ENABLE_EXFAT */
+            }
+
+            if (i < sectors)
+            {
+                sectors = i;
+            }
+
+            /* Determine if this is a single sector read request.  If so, read the sector so it will
+               come from the internal cache.  */
+            if (sectors == 1)
+            {
+
+                /* Read the current logical sector.  */
+                status =  _fx_utility_logical_sector_read(media_ptr,
+                                                          file_ptr -> fx_file_current_logical_sector,
+                                                          media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DATA_SECTOR);
+
+                /* Check for good completion status.  */
+                if (status !=  FX_SUCCESS)
+                {
+
+                    /* Release media protection.  */
+                    FX_UNPROTECT
+
+                    /* Return the error status.  */
+                    return(status);
+                }
+
+                /* Actually perform the memory copy.  */
+                _fx_utility_memory_copy((UCHAR *)media_ptr -> fx_media_memory_buffer, destination_ptr, media_ptr -> fx_media_bytes_per_sector); /* Use case of memcpy is verified. */
+            }
+            else
+            {
+
+                /* Multiple sector read request.  Read all the sectors at once.  */
+
+                /* Perform the data read directly into the user's buffer of
+                   the appropriate number of sectors.  */
+                media_ptr -> fx_media_disable_burst_cache = file_ptr -> fx_file_disable_burst_cache;
+                status =  _fx_utility_logical_sector_read(media_ptr, file_ptr -> fx_file_current_logical_sector,
+                                                          destination_ptr, (ULONG) sectors, FX_DATA_SECTOR);
+                media_ptr -> fx_media_disable_burst_cache = FX_FALSE;
+
+                /* Check for good completion status.  */
+                if (status !=  FX_SUCCESS)
+                {
+
+                    /* Release media protection.  */
+                    FX_UNPROTECT
+
+                    /* Return the error status.  */
+                    return(status);
+                }
+            }
+
+            /* Now adjust the various file pointers.  */
+
+            /* Increment the current logical sector.  Subtract one from
+               the sector count because we are going to use the logical
+               offset to do additional sector/cluster arithmetic below.  */
+            file_ptr -> fx_file_current_logical_sector =
+                file_ptr -> fx_file_current_logical_sector +
+                (sectors - 1);
+
+            /* Move the relative sector and cluster as well.  */
+            file_ptr -> fx_file_current_relative_cluster = file_ptr -> fx_file_current_relative_cluster +
+                (file_ptr -> fx_file_current_relative_sector + (sectors - 1)) /
+                media_ptr -> fx_media_sectors_per_cluster;
+
+            file_ptr -> fx_file_current_relative_sector =
+                (file_ptr -> fx_file_current_relative_sector +
+                 (sectors - 1)) % media_ptr -> fx_media_sectors_per_cluster;
+
+            /* Increment the logical sector byte offset.  */
+            file_ptr -> fx_file_current_logical_offset =
+                media_ptr -> fx_media_bytes_per_sector;
+
+            file_ptr -> fx_file_current_physical_cluster = cluster;
+
+            /* Adjust the remaining bytes.  */
+            bytes_remaining =  bytes_remaining -
+                (((ULONG)media_ptr -> fx_media_bytes_per_sector) * sectors);
+
+            /* Adjust the pointer to the destination buffer.  */
+            destination_ptr =  destination_ptr +
+                (((ULONG)media_ptr -> fx_media_bytes_per_sector) * sectors);
+        }
+
+        /* At this point, we have either read a partial sector or have successfully
+           read one or more whole sectors.  Determine if we are at the end of
+           the current logical sector.  */
+        if (file_ptr -> fx_file_current_logical_offset >=
+            media_ptr -> fx_media_bytes_per_sector)
+        {
+
+            /* Determine if we are at the exact physical end of the file at the end of reading.  */
+            if ((bytes_remaining == 0) && ((file_ptr -> fx_file_current_file_offset + (ULONG64)request_size) >=
+                                           file_ptr -> fx_file_current_available_size))
+            {
+
+                /* Skip the following file parameter adjustments.  The next write will
+                   detect the logical offset out of the range of the sector and reset
+                   all of the pertinent information.  */
+                break;
+            }
+
+            /* We need to move to the next logical sector, but first
+               determine if the next logical sector is within the same
+               cluster.  */
+
+            /* Increment the current relative sector in the cluster.  */
+            file_ptr -> fx_file_current_relative_sector++;
+
+            /* Determine if this is in a new cluster.  */
+            if (file_ptr -> fx_file_current_relative_sector >=
+                media_ptr -> fx_media_sectors_per_cluster)
+            {
+#ifdef FX_ENABLE_EXFAT
+                if (file_ptr -> fx_file_dir_entry.fx_dir_entry_dont_use_fat & 1)
+                {
+                    next_cluster = file_ptr -> fx_file_current_physical_cluster + 1;
+                }
+                else
+                {
+#endif /* FX_ENABLE_EXFAT */
+
+                    /* Read the FAT entry of the current cluster to find
+                       the next cluster.  */
+                    status =  _fx_utility_FAT_entry_read(media_ptr,
+                                                         file_ptr -> fx_file_current_physical_cluster, &next_cluster);
+
+                    /* Determine if an error is present.  */
+                    if ((status != FX_SUCCESS) || (next_cluster < FX_FAT_ENTRY_START) ||
+                        (next_cluster > media_ptr -> fx_media_fat_reserved))
+                    {
+
+                        /* Release media protection.  */
+                        FX_UNPROTECT
+
+                        /* Send error message back to caller.  */
+                        if (status != FX_SUCCESS)
+                        {
+                            return(status);
+                        }
+                        else
+                        {
+                            return(FX_FILE_CORRUPT);
+                        }
+                    }
+#ifdef FX_ENABLE_EXFAT
+                }
+#endif /* FX_ENABLE_EXFAT */
+
+                /* Otherwise, we have a new cluster.  Save it in the file
+                   control block and calculate a new logical sector value.  */
+                file_ptr -> fx_file_current_physical_cluster =  next_cluster;
+                file_ptr -> fx_file_current_relative_cluster++;
+                file_ptr -> fx_file_current_logical_sector = ((ULONG)media_ptr -> fx_media_data_sector_start) +
+                    ((((ULONG64)next_cluster) - FX_FAT_ENTRY_START) *
+                     ((ULONG)media_ptr -> fx_media_sectors_per_cluster));
+                file_ptr -> fx_file_current_relative_sector =  0;
+            }
+            else
+            {
+
+                /* Still within the same cluster so just increment the
+                   logical sector.  */
+                file_ptr -> fx_file_current_logical_sector++;
+            }
+
+            /* In either case, we are now positioned at a new sector so
+               clear the logical sector offset.  */
+            file_ptr -> fx_file_current_logical_offset =  0;
+        }
+    }
+
+    /* Adjust the current file offset accordingly.  */
+    file_ptr -> fx_file_current_file_offset =
+        file_ptr -> fx_file_current_file_offset + (ULONG64)request_size;
+
+    /* Store the number of bytes actually read.  */
+    *actual_size =  request_size;
+
+    /* Update the trace event with the bytes read.  */
+    FX_TRACE_EVENT_UPDATE(trace_event, trace_timestamp, FX_TRACE_FILE_READ, 0, 0, 0, request_size)
+
+    /* Update the last accessed date.  */
+    file_ptr -> fx_file_dir_entry.fx_dir_entry_last_accessed_date =  _fx_system_date;
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* Return a successful status to the caller.  */
+    return(FX_SUCCESS);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_relative_seek.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_relative_seek.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_relative_seek.c	(revision 30)
@@ -0,0 +1,90 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_file.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_file_relative_seek                              PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function positions the internal file pointers to the specified */
+/*    byte relative offset such that the next read or write operation is  */
+/*    performed there.                                                    */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    file_ptr                              File control block pointer    */
+/*    byte_offset                           Byte offset of the seek       */
+/*    seek_from                             Direction for relative seek,  */
+/*                                          legal values are:             */
+/*                                                                        */
+/*                                              FX_SEEK_BEGIN             */
+/*                                              FX_SEEK_END               */
+/*                                              FX_SEEK_FORWARD           */
+/*                                              FX_SEEK_BACK              */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_file_extended_relative_seek       Seek to specified position    */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s), and      */
+/*                                            Added conditional to        */
+/*                                            disable one line function,  */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+#ifndef FX_DISABLE_ONE_LINE_FUNCTION
+UINT  _fx_file_relative_seek(FX_FILE *file_ptr, ULONG byte_offset, UINT seek_from)
+{
+
+    return(_fx_file_extended_relative_seek(file_ptr, (ULONG64)byte_offset, seek_from));
+}
+#endif /* FX_DISABLE_ONE_LINE_FUNCTION */
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_rename.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_rename.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_rename.c	(revision 30)
@@ -0,0 +1,598 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_directory.h"
+#include "fx_file.h"
+#include "fx_utility.h"
+#ifdef FX_ENABLE_EXFAT
+#include "fx_directory_exFAT.h"
+#endif /* FX_ENABLE_EXFAT */
+#ifdef FX_ENABLE_FAULT_TOLERANT
+#include "fx_fault_tolerant.h"
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_file_rename                                     PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function first attempts to find the specified file.  If found, */
+/*    the rename request is valid and the directory entry will be changed */
+/*    to the new file name.  Otherwise, if the file is not found, the     */
+/*    appropriate error code is returned to the caller.                   */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    old_file_name                         Old file name pointer         */
+/*    new_file_name                         New file name pointer         */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_entry_write             Write the new directory entry */
+/*    _fx_directory_free_search             Search for a free directory   */
+/*                                            entry in target directory   */
+/*    _fx_directory_name_extract            Extract the new filename      */
+/*    _fx_directory_search                  Search for the file name in   */
+/*                                          the directory structure       */
+/*    _fx_fault_tolerant_transaction_start  Start fault tolerant          */
+/*                                            transaction                 */
+/*    _fx_fault_tolerant_transaction_end    End fault tolerant transaction*/
+/*    _fx_fault_tolerant_recover            Recover FAT chain             */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_file_rename(FX_MEDIA *media_ptr, CHAR *old_file_name, CHAR *new_file_name)
+{
+
+ULONG        i;
+CHAR        *work_ptr;
+CHAR         alpha, beta;
+UINT         status;
+
+#ifndef FX_DONT_UPDATE_OPEN_FILES
+ULONG        open_count;
+FX_FILE     *search_ptr;
+#endif
+CHAR        *new_name_ptr;
+FX_DIR_ENTRY old_dir_entry, new_dir_entry;
+FX_DIR_ENTRY search_directory;
+#ifdef FX_RENAME_PATH_INHERIT
+UINT         j;
+#endif
+UCHAR        not_a_file_attr;
+
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of times this service has been called.  */
+    media_ptr -> fx_media_file_renames++;
+#endif
+
+    /* Setup pointers to media name buffers.  */
+    old_dir_entry.fx_dir_entry_name =     media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
+    new_dir_entry.fx_dir_entry_name =     media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN * 2;
+    search_directory.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN * 3;
+
+    /* Clear the short name strings.  */
+    old_dir_entry.fx_dir_entry_short_name[0] =     0;
+    new_dir_entry.fx_dir_entry_short_name[0] =     0;
+    search_directory.fx_dir_entry_short_name[0] =  0;
+
+    /* Determine if the supplied name is less than the maximum supported name size. The
+       maximum name (FX_MAX_LONG_NAME_LEN) is defined in fx_api.h.  */
+    i =  0;
+    work_ptr =  (CHAR *)new_file_name;
+    while (*work_ptr)
+    {
+
+        /* Determine if the character designates a new path.  */
+        if ((*work_ptr == '\\') || (*work_ptr == '/'))
+        {
+            /* Yes, reset the name size.  */
+            i =  0;
+        }
+        /* Check for leading spaces.  */
+        else if ((*work_ptr != ' ') || (i != 0))
+        {
+
+            /* No leading spaces, increment the name size.  */
+            i++;
+        }
+
+        /* Move to the next character.  */
+        work_ptr++;
+    }
+
+    /* Determine if the supplied name is valid.  */
+    if ((i == 0) || (i >= FX_MAX_LONG_NAME_LEN))
+    {
+
+        /* Return an invalid name value.  */
+        return(FX_INVALID_NAME);
+    }
+
+    /* Check the media to make sure it is open.  */
+    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
+    {
+
+        /* Return the media not opened error.  */
+        return(FX_MEDIA_NOT_OPEN);
+    }
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_FILE_RENAME, media_ptr, old_file_name, new_file_name, 0, FX_TRACE_FILE_EVENTS, 0, 0)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    /* Start transaction. */
+    _fx_fault_tolerant_transaction_start(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Check for write protect at the media level (set by driver).  */
+    if (media_ptr -> fx_media_driver_write_protect)
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return write protect error.  */
+        return(FX_WRITE_PROTECT);
+    }
+
+    /* Search the system for the supplied file name.  */
+    status =  _fx_directory_search(media_ptr, old_file_name, &old_dir_entry, &search_directory, FX_NULL);
+
+    /* Determine if the search was successful.  */
+    if (status != FX_SUCCESS)
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the error code.  */
+        return(status);
+    }
+
+#ifdef FX_ENABLE_EXFAT
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+        not_a_file_attr = FX_DIRECTORY;
+    }
+    else
+    {
+#endif /* FX_ENABLE_EXFAT */
+        not_a_file_attr = FX_DIRECTORY | FX_VOLUME;
+#ifdef FX_ENABLE_EXFAT
+    }
+#endif /* FX_ENABLE_EXFAT */
+
+    /* Check to make sure the found entry is a file.  */
+    if (old_dir_entry.fx_dir_entry_attributes & not_a_file_attr)
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the not a file error code.  */
+        return(FX_NOT_A_FILE);
+    }
+
+#ifdef FX_RENAME_PATH_INHERIT
+
+    /* Determine if the source file name has a path and the target file name does not.  */
+    if (((old_file_name[0] == '/') || (old_file_name[0] == '\\')) && (new_file_name[0] != '/') && (new_file_name[0] != '\\'))
+    {
+
+        /* In this case, we need to prepend the path of the old file name to that of the new file name.  */
+
+        /* Setup pointer to the rename buffer.  */
+        work_ptr =  (CHAR *)media_ptr -> fx_media_rename_buffer;
+
+        /* First, copy the path of the old file name.  */
+        i =  0;
+        j =  0;
+        while ((old_file_name[i]) && (i < FX_MAXIMUM_PATH))
+        {
+
+            /* Copy a character into the rename buffer.  */
+            *work_ptr++ =  old_file_name[i];
+
+            /* Determine if this character is directory separator.  */
+            if ((old_file_name[i] == '/') || (old_file_name[i] == '\\'))
+            {
+
+                /* Yes, directory separator has been found - remember the index.  */
+                j =  i;
+            }
+
+            /* Move to next position in the old file name.  */
+            i++;
+        }
+
+        /* At this point, we have the path stored in the rename buffer.  */
+
+        /* Position past the last slash or backslash.  */
+        j++;
+
+        /* Reset the working pointer to the position after the last directory separator.  */
+        work_ptr =  (CHAR *)&(media_ptr -> fx_media_rename_buffer[j]);
+
+        /* Now copy the new file name into the rename buffer.  */
+        i =  0;
+        while ((new_file_name[i]) && (j < FX_MAXIMUM_PATH))
+        {
+
+            /* Copy a character into the rename buffer.  */
+            *work_ptr++ =  new_file_name[i];
+
+            /* Move to next character.  */
+            i++;
+            j++;
+        }
+
+        /* Determine if the path was successfully prepended.  */
+        if (new_file_name[i])
+        {
+
+            /* No, there was not enough room in the destination buffer.  */
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+            FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* Return the invalid path error code.  */
+            return(FX_INVALID_PATH);
+        }
+
+        /* Place a NULL at the end of the string.  */
+        *work_ptr =  (CHAR)FX_NULL;
+
+        /* At this point, we have successfully prepended the path in the new file name, override
+           the new file name so it is used from now on.  */
+        new_file_name =  (CHAR *)media_ptr -> fx_media_rename_buffer;
+    }
+#endif
+
+    /* Search the target directory for the same file name.  */
+    status = _fx_directory_search(media_ptr, new_file_name, &new_dir_entry, &search_directory, &new_name_ptr);
+
+    /* Determine if the name already exists.  */
+    if (status == FX_SUCCESS)
+    {
+
+        /* Determine if the new name simply has an ASCII case change. If so, simply let the processing
+           continue.  */
+        i =  0;
+        do
+        {
+
+            /* Pickup an old name and new name character and convert to upper case if necessary.  */
+            alpha =  old_file_name[i];
+            if ((alpha >= 'a') && (alpha <= 'z'))
+            {
+
+                /* Lower case, convert to upper case!  */
+                alpha =  (CHAR)((INT)alpha - 0x20);
+            }
+            beta =   new_file_name[i];
+            if ((beta >= 'a') && (beta <= 'z'))
+            {
+
+                /* Lower case, convert to upper case!  */
+                beta = (CHAR)((INT)beta - 0x20);
+            }
+
+            /* Now compare the characters.  */
+            if ((alpha != beta) || (alpha == 0))
+            {
+
+                /* Get out of this loop!  */
+                break;
+            }
+
+            /* Move to next character.  */
+            i++;
+        } while (i < (FX_MAXIMUM_PATH-1));
+
+        /* Now determine if the names match.  */
+        if (alpha != beta)
+        {
+
+            /* No, the names do not match so simply return an error
+               to the caller.  */
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+            FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* Return the not a file error code.  */
+            return(FX_ALREADY_CREATED);
+        }
+    }
+
+    /* Change the file name and look for extra stuff at the end.  */
+    if (_fx_directory_name_extract(new_name_ptr, &new_dir_entry.fx_dir_entry_name[0]))
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Invalid name, return error status.  */
+        return(FX_INVALID_NAME);
+    }
+
+    /* Search for a free spot in the target directory.  */
+    status = _fx_directory_free_search(media_ptr, &search_directory, &new_dir_entry);
+
+    /* Determine if a free spot was found.  */
+    if (status != FX_SUCCESS)
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the error code.  */
+        return(status);
+    }
+
+    /* Extract the new file name.  */
+    _fx_directory_name_extract(new_name_ptr, &new_dir_entry.fx_dir_entry_name[0]);
+
+    /* Determine if a long name is present.  */
+    if (new_dir_entry.fx_dir_entry_long_name_present)
+    {
+
+        /* Yes, clear the short file name.  */
+        new_dir_entry.fx_dir_entry_short_name[0] =  0;
+    }
+
+    /* Save the updated directory parameters.  */
+    new_dir_entry.fx_dir_entry_attributes =          old_dir_entry.fx_dir_entry_attributes;
+    new_dir_entry.fx_dir_entry_cluster    =          old_dir_entry.fx_dir_entry_cluster;
+    new_dir_entry.fx_dir_entry_file_size  =          old_dir_entry.fx_dir_entry_file_size;
+
+    /* Save the reserved field.  */
+    new_dir_entry.fx_dir_entry_reserved =            old_dir_entry.fx_dir_entry_reserved;
+
+    /* Set time and date stamps.  */
+    new_dir_entry.fx_dir_entry_created_time_ms =     old_dir_entry.fx_dir_entry_created_time_ms;
+    new_dir_entry.fx_dir_entry_created_time =        old_dir_entry.fx_dir_entry_created_time;
+    new_dir_entry.fx_dir_entry_created_date =        old_dir_entry.fx_dir_entry_created_date;
+    new_dir_entry.fx_dir_entry_last_accessed_date =  old_dir_entry.fx_dir_entry_last_accessed_date;
+    new_dir_entry.fx_dir_entry_time =                old_dir_entry.fx_dir_entry_time;
+    new_dir_entry.fx_dir_entry_date =                old_dir_entry.fx_dir_entry_date;
+
+#ifdef FX_ENABLE_EXFAT
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+
+        new_dir_entry.fx_dir_entry_dont_use_fat =              old_dir_entry.fx_dir_entry_dont_use_fat;
+        new_dir_entry.fx_dir_entry_type =                  old_dir_entry.fx_dir_entry_type;
+        new_dir_entry.fx_dir_entry_available_file_size =   old_dir_entry.fx_dir_entry_available_file_size;
+        new_dir_entry.fx_dir_entry_secondary_count =       old_dir_entry.fx_dir_entry_secondary_count;
+    }
+#endif /* FX_ENABLE_EXFAT */
+
+    /* Is there a leading dot?  */
+    if (new_dir_entry.fx_dir_entry_name[0] == '.')
+    {
+
+        /* Yes, toggle the hidden attribute bit.  */
+        new_dir_entry.fx_dir_entry_attributes |=  FX_HIDDEN;
+    }
+
+#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
+
+    /* Invalidate the directory cache.  */
+    media_ptr -> fx_media_last_found_name[0] =  FX_NULL;
+#endif
+
+    /* Now write out the directory entry.  */
+#ifdef FX_ENABLE_EXFAT
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+
+        status = _fx_directory_exFAT_entry_write(media_ptr, &new_dir_entry, UPDATE_FULL);
+    }
+    else
+    {
+#endif /* FX_ENABLE_EXFAT */
+        status =  _fx_directory_entry_write(media_ptr, &new_dir_entry);
+#ifdef FX_ENABLE_EXFAT
+    }
+#endif /* FX_ENABLE_EXFAT */
+
+    /* Determine if the write was successful.  */
+    if (status != FX_SUCCESS)
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the error code.  */
+        return(status);
+    }
+
+#ifndef FX_DONT_UPDATE_OPEN_FILES
+
+    /* Search the opened files to update any currently opened files.  */
+    open_count =  media_ptr -> fx_media_opened_file_count;
+    search_ptr =  media_ptr -> fx_media_opened_file_list;
+    while (open_count)
+    {
+
+        /* Look at each opened file to see if it matches the file being renamed.  */
+        if ((search_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector ==
+             old_dir_entry.fx_dir_entry_log_sector) &&
+            (search_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset ==
+             old_dir_entry.fx_dir_entry_byte_offset))
+        {
+
+            /* Yes, the file being renamed is already open.  Update the file's
+               information so that it is kept current.  */
+            search_ptr -> fx_file_dir_entry.fx_dir_entry_cluster =      new_dir_entry.fx_dir_entry_cluster;
+            search_ptr -> fx_file_dir_entry.fx_dir_entry_file_size =    new_dir_entry.fx_dir_entry_file_size;
+            search_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector =   new_dir_entry.fx_dir_entry_log_sector;
+            search_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset =  new_dir_entry.fx_dir_entry_byte_offset;
+
+            /* Copy the new name into the file's name buffer.  */
+            i =  0;
+            while (i < (FX_MAX_LONG_NAME_LEN - 1))
+            {
+
+                /* Copy byte of the new name.  */
+                search_ptr -> fx_file_dir_entry.fx_dir_entry_name[i] =  new_dir_entry.fx_dir_entry_name[i];
+
+                /* Move to the next character.  */
+                i++;
+
+                /* Determine if we are at the end of the name.  */
+                if (new_dir_entry.fx_dir_entry_name[i] == FX_NULL)
+                {
+                
+                    /* Determine if we are not at the maximum name size.  */
+                    if (i < (FX_MAX_LONG_NAME_LEN - 1))
+                    {
+                    
+                        /* Get out of the loop.   */
+                        break;
+                    }
+                }
+            }
+
+            /* Set the NULL termination in the copy of the new name.  */
+            search_ptr -> fx_file_dir_entry.fx_dir_entry_name[i] =  FX_NULL;
+        }
+
+        /* Adjust the pointer and decrement the search count.  */
+        search_ptr =  search_ptr -> fx_file_opened_next;
+        open_count--;
+    }
+#endif
+
+    /* Now we are ready to remove the old directory entry.  */
+    old_dir_entry.fx_dir_entry_name[0] =        (CHAR)FX_DIR_ENTRY_FREE;
+    old_dir_entry.fx_dir_entry_short_name[0] =  (CHAR)FX_DIR_ENTRY_FREE;
+
+    /* Now wipe out the old directory entry.  */
+#ifdef FX_ENABLE_EXFAT
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+
+        status = _fx_directory_exFAT_entry_write(media_ptr, &old_dir_entry, UPDATE_DELETE);
+    }
+    else
+    {
+#endif /* FX_ENABLE_EXFAT */
+        status =  _fx_directory_entry_write(media_ptr, &old_dir_entry);
+#ifdef FX_ENABLE_EXFAT
+    }
+#endif /* FX_ENABLE_EXFAT */
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    /* Check for a bad status.  */
+    if (status != FX_SUCCESS)
+    {
+
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the bad status.  */
+        return(status);
+    }
+
+    /* End transaction. */
+    status = _fx_fault_tolerant_transaction_end(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* File rename is complete, return status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_seek.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_seek.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_seek.c	(revision 30)
@@ -0,0 +1,83 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_file.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_file_seek                                       PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function positions the internal file pointers to the specified */
+/*    byte offset such that the next read or write operation will be      */
+/*    performed there.  If the byte offset is greater than the size, the  */
+/*    file pointers will be positioned to the end of the file.            */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    file_ptr                              File control block pointer    */
+/*    byte_offset                           Byte offset into the file     */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_file_extended_seek                Seek to specified position    */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s), and      */
+/*                                            Added conditional to        */
+/*                                            disable one line function,  */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+#ifndef FX_DISABLE_ONE_LINE_FUNCTION
+UINT  _fx_file_seek(FX_FILE *file_ptr, ULONG byte_offset)
+{
+
+    return(_fx_file_extended_seek(file_ptr, (ULONG64) byte_offset));
+}
+#endif /* FX_DISABLE_ONE_LINE_FUNCTION */
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_truncate.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_truncate.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_truncate.c	(revision 30)
@@ -0,0 +1,83 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_file.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_file_truncate                                   PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function sets the file to the specified size, if smaller than  */
+/*    the current file size.  If the new file size is less than the       */
+/*    current file read/write position, the internal file pointers will   */
+/*    also be modified.                                                   */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    file_ptr                              File control block pointer    */
+/*    size                                  New size of the file in bytes */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_file_extended_truncate            Truncate the file size        */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s), and      */
+/*                                            Added conditional to        */
+/*                                            disable one line function,  */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+#ifndef FX_DISABLE_ONE_LINE_FUNCTION
+UINT  _fx_file_truncate(FX_FILE *file_ptr, ULONG size)
+{
+
+    return(_fx_file_extended_truncate(file_ptr, (ULONG64)size));
+}
+#endif /* FX_DISABLE_ONE_LINE_FUNCTION */
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_truncate_release.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_truncate_release.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_truncate_release.c	(revision 30)
@@ -0,0 +1,86 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_file.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_file_truncate_release                           PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function sets the file to the specified size, if smaller than  */
+/*    the current file size.  If the new file size is less than the       */
+/*    current file read/write position, the internal file pointers will   */
+/*    also be modified.  Any unused clusters are released back to the     */
+/*    media.                                                              */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    file_ptr                              File control block pointer    */
+/*    size                                  New size of the file in bytes */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_file_extended_truncate_release    Truncate the file size and    */
+/*                                            released unused clusters    */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s), and      */
+/*                                            Added conditional to        */
+/*                                            disable one line function,  */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+#ifndef FX_DISABLE_ONE_LINE_FUNCTION
+UINT  _fx_file_truncate_release(FX_FILE *file_ptr, ULONG size)
+{
+
+    return(_fx_file_extended_truncate_release(file_ptr, (ULONG64)size));
+}
+#endif /* FX_DISABLE_ONE_LINE_FUNCTION */
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_write.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_write.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_write.c	(revision 30)
@@ -0,0 +1,1770 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_file.h"
+#include "fx_directory.h"
+#include "fx_utility.h"
+#ifdef FX_ENABLE_FAULT_TOLERANT
+#include "fx_fault_tolerant.h"
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_file_write                                      PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function writes the specified number of bytes into the file's  */
+/*    data area.  The status of the write operation is returned to the    */
+/*    caller.  In addition, various internal file pointers in the file    */
+/*    control block are also updated.                                     */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    file_ptr                              File control block pointer    */
+/*    buffer_ptr                            Buffer pointer                */
+/*    size                                  Number of bytes to write      */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_entry_write             Update the file's size        */
+/*    _fx_utility_exFAT_bitmap_flush        Flush exFAT allocation bitmap */
+/*    _fx_utility_exFAT_bitmap_free_cluster_find                          */
+/*                                          Find exFAT free cluster       */
+/*    _fx_utility_exFAT_cluster_state_get   Get cluster state             */
+/*    _fx_utility_exFAT_cluster_state_set   Set cluster state             */
+/*    _fx_utility_FAT_entry_read            Read a FAT entry              */
+/*    _fx_utility_FAT_entry_write           Write a FAT entry             */
+/*    _fx_utility_FAT_flush                 Flush written FAT entries     */
+/*    _fx_utility_logical_sector_flush      Flush written logical sectors */
+/*    _fx_utility_logical_sector_read       Read a logical sector         */
+/*    _fx_utility_logical_sector_write      Write a logical sector        */
+/*    _fx_utility_memory_copy               Fast memory copy routine      */
+/*    _fx_fault_tolerant_transaction_start  Start fault tolerant          */
+/*                                            transaction                 */
+/*    _fx_fault_tolerant_transaction_end    End fault tolerant transaction*/
+/*    _fx_fault_tolerant_recover            Recover FAT chain             */
+/*    _fx_fault_tolerant_reset_log_file     Reset the log file            */
+/*    _fx_fault_tolerant_set_FAT_chain      Set data of FAT chain         */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s), verified */
+/*                                            memcpy usage,               */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_file_write(FX_FILE *file_ptr, VOID *buffer_ptr, ULONG size)
+{
+
+UINT                   status;
+ULONG64                bytes_remaining;
+ULONG                  i;
+ULONG                  copy_bytes;
+ULONG                  bytes_per_cluster;
+UCHAR                 *source_ptr;
+ULONG                  first_new_cluster;
+ULONG                  last_cluster;
+ULONG                  cluster, next_cluster;
+ULONG                  FAT_index;
+ULONG                  FAT_value;
+ULONG                  clusters;
+ULONG                  total_clusters;
+UINT                   sectors;
+FX_MEDIA              *media_ptr;
+
+#ifdef FX_ENABLE_EXFAT
+UCHAR                  cluster_state;
+#endif /* FX_ENABLE_EXFAT */
+
+#ifdef FX_FAULT_TOLERANT_DATA
+FX_INT_SAVE_AREA
+#endif
+
+#ifndef FX_DONT_UPDATE_OPEN_FILES
+ULONG                  open_count;
+FX_FILE               *search_ptr;
+#endif
+
+#ifdef TX_ENABLE_EVENT_TRACE
+TX_TRACE_BUFFER_ENTRY *trace_event;
+ULONG                  trace_timestamp;
+#endif
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+UCHAR                  data_append = FX_FALSE;      /* Whether or not new data would extend beyond the size of the original file.
+                                                      Operations such as append or overwrite could cause the new file to exceed its
+                                                      original size, resulting in data-appending operation. */
+ULONG                  copy_head_cluster = 0;       /* The first cluster of the original chain that needs to be replaced. */
+ULONG                  copy_tail_cluster = 0;       /* The last cluster of the original chain that needs to be replaced. */
+ULONG                  insertion_back;              /* The insertion point (back) */
+ULONG                  insertion_front = 0;         /* The insertion point (front) */
+ULONG                  replace_clusters = 0;        /* The number of clusters to be replaced. */
+UCHAR                  dont_use_fat_old = FX_FALSE; /* Used by exFAT logic to indicate whether or not the FAT table should be used. */
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+
+    /* First, determine if the file is still open.  */
+    if (file_ptr -> fx_file_id != FX_FILE_ID)
+    {
+
+        /* Return the file not open error status.  */
+        return(FX_NOT_OPEN);
+    }
+
+    /* Setup pointer to media structure.  */
+    media_ptr =  file_ptr -> fx_file_media_ptr;
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of times this service has been called.  */
+    media_ptr -> fx_media_file_writes++;
+#endif
+
+
+#ifdef FX_ENABLE_EXFAT
+    if ((media_ptr -> fx_media_FAT_type != FX_exFAT) &&
+        (file_ptr -> fx_file_current_file_offset + size > 0xFFFFFFFFULL))
+#else
+    if (file_ptr -> fx_file_current_file_offset + size > 0xFFFFFFFFULL)
+#endif /* FX_ENABLE_EXFAT */
+    {
+
+        /* Return the no more space error, since the new file size would be larger than
+           the 32-bit field to represent it in the file's directory entry.  */
+        return(FX_NO_MORE_SPACE);
+    }
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    /* Initialize next cluster of tail. */
+    insertion_back = media_ptr -> fx_media_fat_last;
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_FILE_WRITE, file_ptr, buffer_ptr, size, 0, FX_TRACE_FILE_EVENTS, &trace_event, &trace_timestamp)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+    /* Check for write protect at the media level (set by driver).  */
+    if (media_ptr -> fx_media_driver_write_protect)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return write protect error.  */
+        return(FX_WRITE_PROTECT);
+    }
+
+    /* Make sure this file is open for writing.  */
+    if (file_ptr -> fx_file_open_mode != FX_OPEN_FOR_WRITE)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the access error exception - a write was attempted from
+           a file opened for reading!  */
+        return(FX_ACCESS_ERROR);
+    }
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+
+    /* Start transaction. */
+    _fx_fault_tolerant_transaction_start(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Calculate the number of bytes per cluster.  */
+    bytes_per_cluster =  ((ULONG)media_ptr -> fx_media_bytes_per_sector) *
+        ((ULONG)media_ptr -> fx_media_sectors_per_cluster);
+
+    /* Check for invalid value.  */
+    if (bytes_per_cluster == 0)
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Invalid media, return error.  */
+        return(FX_MEDIA_INVALID);
+    }
+
+    /* Initialized first new cluster. */
+    first_new_cluster =  0;
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    /* Calculate clusters need to be replaced when fault tolerant is enabled. */
+    if (media_ptr -> fx_media_fault_tolerant_enabled)
+    {
+
+        if (file_ptr -> fx_file_current_file_offset == file_ptr -> fx_file_current_file_size)
+        {
+
+            /* Appending data. No need to replace existing clusters. */
+            replace_clusters = 0;
+        }
+        else if (file_ptr -> fx_file_current_file_offset == file_ptr -> fx_file_maximum_size_used)
+        {
+
+            /* Similar to append data. No actual data after fx_file_maximum_size_used.
+             * No need to replace existing clusters. */
+            replace_clusters = 0;
+        }
+        else if (((file_ptr -> fx_file_current_file_offset / media_ptr -> fx_media_bytes_per_sector) ==
+                 ((file_ptr -> fx_file_current_file_offset + size - 1) / media_ptr -> fx_media_bytes_per_sector)) &&
+                 ((file_ptr -> fx_file_current_file_offset + size) <= file_ptr -> fx_file_current_file_size))
+        {
+
+            /* Overwriting data in one sector. No need to replace existing clusters. */
+            replace_clusters = 0;
+        }
+        else if ((file_ptr -> fx_file_current_available_size - file_ptr -> fx_file_current_file_offset) < size)
+        {
+
+            /* Replace all clusters from current_cluster. */
+            replace_clusters = (UINT)(file_ptr -> fx_file_total_clusters - file_ptr -> fx_file_current_relative_cluster);
+            copy_head_cluster = file_ptr -> fx_file_current_physical_cluster;
+
+            data_append = FX_TRUE;
+        }
+        else
+        {
+
+            /* Replace clusters from current_cluster to the end of written cluster. */
+            replace_clusters = (UINT)((file_ptr -> fx_file_current_file_offset + size + bytes_per_cluster - 1) / bytes_per_cluster -
+                                      file_ptr -> fx_file_current_relative_cluster);
+            copy_head_cluster = file_ptr -> fx_file_current_physical_cluster;
+            data_append = FX_FALSE;
+        }
+    }
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Next, determine if there is enough room to write the specified number of
+       bytes to the clusters already allocated to this file.  */
+    if (((file_ptr -> fx_file_current_available_size - file_ptr -> fx_file_current_file_offset) < size)
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        || (replace_clusters)
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+       )
+    {
+
+        /* The new request will not fit within the currently allocated clusters.  */
+
+        /* Calculate the number of additional clusters that must be allocated for this
+           write request.  */
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        /* Find the number of clusters that need to be replaced. */
+        if (media_ptr -> fx_media_fault_tolerant_enabled)
+        {
+
+            /* Mark the recovery phase. */
+            media_ptr -> fx_media_fault_tolerant_state |= FX_FAULT_TOLERANT_STATE_SET_FAT_CHAIN;
+
+            bytes_remaining = file_ptr -> fx_file_current_file_offset + size;
+
+            if (replace_clusters > 0)
+            {
+
+#ifdef FX_ENABLE_EXFAT
+                if ((media_ptr -> fx_media_FAT_type == FX_exFAT) && (file_ptr -> fx_file_dir_entry.fx_dir_entry_dont_use_fat & 1))
+                {
+                    /* Find the insertion points in the exFAT with bitmap case.. this is a simple case.. */
+                    /* The previous cluster is not initialized. Find it. */
+                    if (copy_head_cluster != file_ptr -> fx_file_first_physical_cluster)
+                    {
+                        insertion_front = copy_head_cluster - 1;
+                    }
+
+                    /* Find copy tail cluster. */
+                    if (data_append == FX_FALSE)
+                    {
+                        copy_tail_cluster = file_ptr -> fx_file_first_physical_cluster + (ULONG)((bytes_remaining - 1) / bytes_per_cluster);
+                        if (copy_tail_cluster != file_ptr -> fx_file_last_physical_cluster)
+                        {
+                            insertion_back = copy_tail_cluster + 1;
+                        }
+                    }
+                }
+                else
+                {
+#endif /* FX_ENABLE_EXFAT */
+
+                    /* Find previous cluster of copy head cluster. */
+                    /* The previous cluster is not initialized. Find it. */
+                    if (copy_head_cluster != file_ptr -> fx_file_first_physical_cluster)
+                    {
+
+                        /* The copy head cluster is not the first cluster of file. */
+                        /* Copy head is not the first cluster of file. */
+                        if (file_ptr -> fx_file_current_relative_cluster < file_ptr -> fx_file_consecutive_cluster)
+                        {
+
+                            /* Clusters before current cluster are consecutive. */
+                            insertion_front = copy_head_cluster - 1;
+                            bytes_remaining -= file_ptr -> fx_file_current_relative_cluster * bytes_per_cluster;
+                        }
+                        else
+                        {
+
+                            /* Skip consecutive clusters first. */
+                            cluster = file_ptr -> fx_file_first_physical_cluster;
+
+                            /* Loop the link of FAT to find the previous cluster. */
+                            while ((cluster >= FX_FAT_ENTRY_START) && (cluster < media_ptr -> fx_media_fat_reserved))
+                            {
+
+                                /* Reduce remaining bytes. */
+                                bytes_remaining -= bytes_per_cluster;
+
+                                /* Read the current cluster entry from the FAT.  */
+                                status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &FAT_value);
+
+                                /* Check the return value.  */
+                                if (status != FX_SUCCESS)
+                                {
+
+                                    FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+
+                                    /* Release media protection.  */
+                                    FX_UNPROTECT
+
+                                    /* Return the error status.  */
+                                    return(status);
+                                }
+
+                                if (FAT_value == copy_head_cluster)
+                                {
+                                    break;
+                                }
+
+                                /* Move to next cluster. */
+                                cluster = FAT_value;
+                            }
+
+                            if ((cluster >= FX_FAT_ENTRY_START) && (cluster < media_ptr -> fx_media_fat_reserved))
+                            {
+
+                                /* Find the previous cluster. */
+                                insertion_front = cluster;
+                            }
+                            else
+                            {
+
+                                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+
+                                /* Release media protection.  */
+                                FX_UNPROTECT
+
+                                /* Return the error status.  */
+                                return(FX_NOT_FOUND);
+                            }
+                        }
+                    }
+
+                    /* Find copy tail cluster. */
+                    if (bytes_remaining <= bytes_per_cluster)
+                    {
+
+                        /* Only one cluster is modified. */
+                        copy_tail_cluster = copy_head_cluster;
+                    }
+                    else if (data_append == FX_FALSE)
+                    {
+
+                        /* Search from copy head cluster. */
+                        cluster = copy_head_cluster;
+                        FAT_value = FX_FAT_ENTRY_START;
+
+                        /* Loop the link of FAT to find the previous cluster. */
+                        while ((cluster >= FX_FAT_ENTRY_START) && (cluster < media_ptr -> fx_media_fat_reserved))
+                        {
+
+                            if (bytes_remaining <= bytes_per_cluster)
+                            {
+                                break;
+                            }
+
+                            /* Reduce remaining bytes. */
+                            bytes_remaining -= bytes_per_cluster;
+
+                            /* Read the current cluster entry from the FAT.  */
+                            status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &FAT_value);
+
+                            /* Check the return value.  */
+                            if (status != FX_SUCCESS)
+                            {
+
+                                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+
+                                /* Release media protection.  */
+                                FX_UNPROTECT
+
+                                /* Return the error status.  */
+                                return(status);
+                            }
+
+                            /* Move to next cluster. */
+                            cluster = FAT_value;
+                        }
+
+                        /* Find the previous cluster. */
+                        copy_tail_cluster = FAT_value;
+                    }
+
+                    /* Get the cluster next to copy tail. */
+                    if (data_append == FX_FALSE)
+                    {
+
+                        /* Read FAT entry.  */
+                        status =  _fx_utility_FAT_entry_read(media_ptr, copy_tail_cluster, &insertion_back);
+
+                        /* Check for a bad status.  */
+                        if (status != FX_SUCCESS)
+                        {
+
+                            FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+
+                            /* Release media protection.  */
+                            FX_UNPROTECT
+
+                            /* Return the bad status.  */
+                            return(status);
+                        }
+                    }
+                    else
+                    {
+                        insertion_back = media_ptr -> fx_media_fat_last;
+                    }
+#ifdef FX_ENABLE_EXFAT
+                }
+#endif /* FX_ENABLE_EXFAT */
+            }
+            else
+            {
+                insertion_back = media_ptr -> fx_media_fat_last;
+            }
+        }
+
+        if (file_ptr -> fx_file_current_available_size - file_ptr -> fx_file_current_file_offset < size)
+        {
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+            /* Calculate clusters that are needed for data append except ones overwritten. */
+            clusters =  (UINT)((size + (bytes_per_cluster - 1) -
+                                (file_ptr -> fx_file_current_available_size - file_ptr -> fx_file_current_file_offset)) /
+                               bytes_per_cluster);
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        }
+        else
+        {
+            clusters = 0;
+        }
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Determine if we have enough space left.  */
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        if (clusters + replace_clusters > media_ptr -> fx_media_available_clusters)
+#else
+        if (clusters > media_ptr -> fx_media_available_clusters)
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+        {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+            FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* Out of disk space.  */
+            return(FX_NO_MORE_SPACE);
+        }
+
+        /* Update the file total cluster count.  */
+        file_ptr -> fx_file_total_clusters =  file_ptr -> fx_file_total_clusters + clusters;
+
+        /* Check for wrap-around when updating the available size.  */
+#ifdef FX_ENABLE_EXFAT
+        if ((media_ptr -> fx_media_FAT_type != FX_exFAT) &&
+            (file_ptr -> fx_file_current_available_size + (ULONG64)bytes_per_cluster * (ULONG64)clusters > 0xFFFFFFFFULL))
+#else
+        if (file_ptr -> fx_file_current_available_size + (ULONG64)bytes_per_cluster * (ULONG64)clusters > 0xFFFFFFFFULL)
+#endif /* FX_ENABLE_EXFAT */
+        {
+
+            /* 32-bit wrap around condition is present.  Just set the available file size to all ones, which is
+               the maximum file size.  */
+            file_ptr -> fx_file_current_available_size =  0xFFFFFFFFULL;
+        }
+        else
+        {
+
+            /* Normal condition, update the available size.  */
+            file_ptr -> fx_file_current_available_size =
+                file_ptr -> fx_file_current_available_size + (ULONG64)bytes_per_cluster * (ULONG64)clusters;
+        }
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        /* Account for newly allocated clusters. */
+        clusters += replace_clusters;
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Decrease the available clusters in the media control block. */
+        media_ptr -> fx_media_available_clusters =  media_ptr -> fx_media_available_clusters - clusters;
+
+#if defined(FX_ENABLE_EXFAT) && defined(FX_ENABLE_FAULT_TOLERANT)
+        /* Get dont_use_fat value. */
+        if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+        {
+            dont_use_fat_old = (UCHAR)file_ptr -> fx_file_dir_entry.fx_dir_entry_dont_use_fat;
+        }
+#endif /* FX_ENABLE_EXFAT && FX_ENABLE_FAULT_TOLERANT */
+
+        /* Search for the additional clusters we need.  */
+        total_clusters =     media_ptr -> fx_media_total_clusters;
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        if (replace_clusters > 0)
+        {
+
+            /* Reset consecutive cluster. */
+            file_ptr -> fx_file_consecutive_cluster = 1;
+
+            last_cluster =   insertion_front;
+
+#ifdef FX_ENABLE_EXFAT
+            if ((file_ptr -> fx_file_dir_entry.fx_dir_entry_dont_use_fat & 1) &&
+                (file_ptr -> fx_file_total_clusters > replace_clusters))
+            {
+
+                /* Now we should use FAT.  */
+                file_ptr -> fx_file_dir_entry.fx_dir_entry_dont_use_fat &= (CHAR)0xfe; /* Clear bit 0.  */
+
+                /* Build FAT chain.  */
+                for (i = file_ptr -> fx_file_dir_entry.fx_dir_entry_cluster; i < file_ptr -> fx_file_last_physical_cluster; ++i)
+                {
+
+                    status = _fx_utility_FAT_entry_write(media_ptr, i, i + 1);
+
+                    if (status != FX_SUCCESS)
+                    {
+
+                        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+
+                        /* Release media protection.  */
+                        FX_UNPROTECT
+
+                        /* Return the bad status.  */
+                        return(status);
+                    }
+                }
+
+                /* Write the last cluster FAT entry.  */
+                status = _fx_utility_FAT_entry_write(media_ptr, i, FX_LAST_CLUSTER_exFAT);
+                if (status != FX_SUCCESS)
+                {
+
+                    FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+
+                    /* Release media protection.  */
+                    FX_UNPROTECT
+
+                    /* Return the bad status.  */
+                    return(status);
+                }
+            }
+#endif /* FX_ENABLE_EXFAT */
+        }
+        else
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+        {
+            last_cluster =   file_ptr -> fx_file_last_physical_cluster;
+        }
+
+        FAT_index    =       media_ptr -> fx_media_cluster_search_start;
+
+        /* Loop to find the needed clusters.  */
+        while (clusters)
+        {
+
+            /* Decrease the cluster count.  */
+            clusters--;
+#ifdef FX_ENABLE_EXFAT
+            if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+            {
+
+                /* Find a free cluster.  */
+                if (file_ptr -> fx_file_dir_entry.fx_dir_entry_dont_use_fat & 1)
+                {
+
+                    if (last_cluster)
+                    {
+
+                        cluster_state = FX_EXFAT_BITMAP_CLUSTER_OCCUPIED;
+                        FAT_index = last_cluster + 1;
+
+                        if (FAT_index < media_ptr -> fx_media_total_clusters + FX_FAT_ENTRY_START)
+                        {
+
+                            /* Get the state of the cluster.  */
+                            status = _fx_utility_exFAT_cluster_state_get(media_ptr, FAT_index, &cluster_state);
+
+                            if (status != FX_SUCCESS)
+                            {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                                /* Release media protection.  */
+                                FX_UNPROTECT
+
+                                /* Return the bad status.  */
+                                return(status);
+                            }
+                        }
+
+                        /* Check if we still can do not use FAT.  */
+                        if (cluster_state == FX_EXFAT_BITMAP_CLUSTER_FREE)
+                        {
+
+                            /* Clusters are still consecutive.  */
+                            file_ptr -> fx_file_consecutive_cluster++;
+                        }
+                        else
+                        {
+
+                            /* Now we should use FAT.  */
+                            file_ptr -> fx_file_dir_entry.fx_dir_entry_dont_use_fat &= (CHAR)0xfe; /* Clear bit 0.  */
+
+                            /* Build FAT chain.  */
+                            for (i = file_ptr -> fx_file_dir_entry.fx_dir_entry_cluster; i < last_cluster; ++i)
+                            {
+
+                                status = _fx_utility_FAT_entry_write(media_ptr, i, i + 1);
+
+                                if (status != FX_SUCCESS)
+                                {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                                    FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                                    /* Release media protection.  */
+                                    FX_UNPROTECT
+
+                                    /* Return the bad status.  */
+                                    return(status);
+                                }
+                            }
+
+                            /* Write the last cluster FAT entry.  */
+                            status = _fx_utility_FAT_entry_write(media_ptr, last_cluster, FX_LAST_CLUSTER_exFAT);
+                            if (status != FX_SUCCESS)
+                            {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                                /* Release media protection.  */
+                                FX_UNPROTECT
+
+                                /* Return the bad status.  */
+                                return(status);
+                            }
+
+                            /* Find free cluster from exFAT media.  */
+                            status = _fx_utility_exFAT_bitmap_free_cluster_find(media_ptr,
+                                                                                media_ptr -> fx_media_cluster_search_start,
+                                                                                &FAT_index);
+                        }
+                    }
+                    else
+                    {
+
+                        /* Find the first cluster for file.  */
+                        status = _fx_utility_exFAT_bitmap_free_cluster_find(media_ptr,
+                                                                            media_ptr -> fx_media_cluster_search_start,
+                                                                            &FAT_index);
+                    }
+                }
+                else
+                {
+
+                    /* Find free cluster from exFAT media.  */
+                    status = _fx_utility_exFAT_bitmap_free_cluster_find(media_ptr,
+                                                                        media_ptr -> fx_media_cluster_search_start,
+                                                                        &FAT_index);
+                }
+
+                if (status != FX_SUCCESS)
+                {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                    FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                    /* Release media protection.  */
+                    FX_UNPROTECT
+
+                    /* Return the bad status.  */
+                    return(status);
+                }
+            }
+            else
+            {
+#endif /* FX_ENABLE_EXFAT */
+
+                /* Loop to find the first available cluster.  */
+                do
+                {
+
+                    /* Make sure we stop looking after one pass through the FAT table.  */
+                    if (!total_clusters)
+                    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                        /* Release media protection.  */
+                        FX_UNPROTECT
+
+                        /* Something is wrong with the media - the desired clusters were
+                           not found in the FAT table.  */
+                        return(FX_NO_MORE_SPACE);
+                    }
+
+                    /* Read FAT entry.  */
+                    status =  _fx_utility_FAT_entry_read(media_ptr, FAT_index, &FAT_value);
+
+                    /* Check for a bad status.  */
+                    if (status != FX_SUCCESS)
+                    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                        /* Release media protection.  */
+                        FX_UNPROTECT
+
+                        /* Return the bad status.  */
+                        return(status);
+                    }
+
+                    /* Decrement the total cluster count.  */
+                    total_clusters--;
+
+                    /* Determine if the FAT entry is free.  */
+                    if (FAT_value == FX_FREE_CLUSTER)
+                    {
+
+                        /* Move cluster search pointer forward.  */
+                        media_ptr -> fx_media_cluster_search_start =  FAT_index + 1;
+
+                        /* Determine if this needs to be wrapped.  */
+                        if (media_ptr -> fx_media_cluster_search_start >= (media_ptr -> fx_media_total_clusters + FX_FAT_ENTRY_START))
+                        {
+
+                            /* Wrap the search to the beginning FAT entry.  */
+                            media_ptr -> fx_media_cluster_search_start =  FX_FAT_ENTRY_START;
+                        }
+
+                        /* Break this loop.  */
+                        break;
+                    }
+                    else
+                    {
+
+                        /* FAT entry is not free... Advance the FAT index.  */
+                        FAT_index++;
+
+                        /* Determine if we need to wrap the FAT index around.  */
+                        if (FAT_index >= (media_ptr -> fx_media_total_clusters + FX_FAT_ENTRY_START))
+                        {
+
+                            /* Wrap the search to the beginning FAT entry.  */
+                            FAT_index =  FX_FAT_ENTRY_START;
+                        }
+                    }
+                } while (FX_TRUE);
+#ifdef FX_ENABLE_EXFAT
+            }
+#endif /* FX_ENABLE_EXFAT */
+
+            /* Determine if we have found the first new cluster yet.  */
+            if (first_new_cluster == 0)
+            {
+
+                /* Remember the first new cluster. */
+                first_new_cluster =  FAT_index;
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                if (media_ptr -> fx_media_fault_tolerant_enabled)
+                {
+
+                    /* Set the undo log now. */
+                    if (copy_head_cluster == 0)
+                    {
+                        status = _fx_fault_tolerant_set_FAT_chain(media_ptr, dont_use_fat_old, file_ptr -> fx_file_current_physical_cluster,
+                                                                  first_new_cluster, media_ptr -> fx_media_fat_last, media_ptr -> fx_media_fat_last);
+                    }
+#ifdef FX_ENABLE_EXFAT
+                    else if (dont_use_fat_old && (insertion_back == media_ptr -> fx_media_fat_last))
+                    {
+                        status = _fx_fault_tolerant_set_FAT_chain(media_ptr, dont_use_fat_old, insertion_front, first_new_cluster,
+                                                                  copy_head_cluster, file_ptr -> fx_file_last_physical_cluster + 1);
+                    }
+#endif /* FX_ENABLE_EXFAT */
+                    else
+                    {
+
+                        status = _fx_fault_tolerant_set_FAT_chain(media_ptr, dont_use_fat_old, insertion_front, first_new_cluster,
+                                                                  copy_head_cluster, insertion_back);
+                    }
+
+                    /* Check for good completion status.  */
+                    if (status !=  FX_SUCCESS)
+                    {
+
+                        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+
+                        /* Release media protection.  */
+                        FX_UNPROTECT
+
+                        /* Return the error status.  */
+                        return(status);
+                    }
+                }
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+            }
+
+            /* Make a quick check to see if an empty, cluster-less file
+               is being written to for the first time.  */
+            if (last_cluster)
+            {
+
+                /* Check for the file's cluster.  We won't perform this link until the
+                   entire FAT chain is built.  */
+                if (last_cluster != file_ptr -> fx_file_last_physical_cluster)
+                {
+#ifdef FX_ENABLE_EXFAT
+                    if (!(file_ptr -> fx_file_dir_entry.fx_dir_entry_dont_use_fat & 1)
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                        || (media_ptr -> fx_media_fault_tolerant_enabled == FX_TRUE)
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+                       )
+                    {
+#endif /* FX_ENABLE_EXFAT */
+
+                        /* Normal condition - link the last cluster with the new
+                           found cluster.  */
+                        status = _fx_utility_FAT_entry_write(media_ptr, last_cluster, FAT_index);
+#ifdef FX_ENABLE_EXFAT
+                    }
+#endif /* FX_ENABLE_EXFAT */
+                }
+
+                /* Check for a bad FAT write status.  */
+                if (status !=  FX_SUCCESS)
+                {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                    FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                    /* Release media protection.  */
+                    FX_UNPROTECT
+
+                    /* Return the bad status.  */
+                    return(status);
+                }
+
+                /* Determine if we are adding a sector after a write filled the previously
+                   allocated cluster exactly.  */
+                if ((file_ptr -> fx_file_current_relative_sector >=
+                     (media_ptr -> fx_media_sectors_per_cluster - 1)) &&
+                    (file_ptr -> fx_file_current_logical_offset >=
+                     media_ptr -> fx_media_bytes_per_sector))
+                {
+
+                    /* Yes, we need to adjust all of the pertinent file parameters for
+                       writing into this newly allocated cluster.  */
+                    file_ptr -> fx_file_current_physical_cluster =  FAT_index;
+                    file_ptr -> fx_file_current_relative_cluster++;
+                    file_ptr -> fx_file_current_relative_sector =   0;
+                    file_ptr -> fx_file_current_logical_sector =    ((ULONG)media_ptr -> fx_media_data_sector_start) +
+                        (((ULONG64)(FAT_index - FX_FAT_ENTRY_START)) *
+                         ((ULONG)media_ptr -> fx_media_sectors_per_cluster));
+                    file_ptr -> fx_file_current_logical_offset =    0;
+                }
+            }
+            else
+            {
+
+                /* This is the first cluster allocated for the file.  Just
+                   remember it as being the first and setup the other file
+                   pointers accordingly.  */
+                file_ptr -> fx_file_first_physical_cluster =    FAT_index;
+                file_ptr -> fx_file_current_physical_cluster =  FAT_index;
+                file_ptr -> fx_file_current_relative_cluster =  0;
+                file_ptr -> fx_file_current_logical_sector =    ((ULONG)media_ptr -> fx_media_data_sector_start) +
+                    (((ULONG64)(FAT_index - FX_FAT_ENTRY_START)) *
+                     ((ULONG)media_ptr -> fx_media_sectors_per_cluster));
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                if (file_ptr -> fx_file_last_physical_cluster == 0)
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+                {
+                    file_ptr -> fx_file_current_logical_offset =    0;
+                    file_ptr -> fx_file_current_file_offset =       0;
+                }
+
+                /* Also remember this as the first cluster in the directory
+                   entry.  */
+                file_ptr -> fx_file_dir_entry.fx_dir_entry_cluster =  FAT_index;
+            }
+#ifdef FX_ENABLE_EXFAT
+            if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+            {
+
+                /* Update Bitmap */
+                status = _fx_utility_exFAT_cluster_state_set(media_ptr, FAT_index, FX_EXFAT_BITMAP_CLUSTER_OCCUPIED);
+
+                if (status !=  FX_SUCCESS)
+                {
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                    FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                    /* Release media protection.  */
+                    FX_UNPROTECT
+
+                    /* Return the bad status.  */
+                    return(status);
+                }
+
+                /* Move cluster search pointer forward. */
+                media_ptr -> fx_media_cluster_search_start = FAT_index + 1;
+
+                /* Determine if this needs to be wrapped. */
+                if (media_ptr -> fx_media_cluster_search_start >= media_ptr -> fx_media_total_clusters + FX_FAT_ENTRY_START)
+                {
+
+                    /* Wrap the search to the beginning FAT entry. */
+                    media_ptr -> fx_media_cluster_search_start = FX_FAT_ENTRY_START;
+                }
+            }
+#endif /* FX_ENABLE_EXFAT */
+
+            /* Otherwise, remember the new FAT index as the last.  */
+            last_cluster =  FAT_index;
+
+            /* Move to the next FAT entry.  */
+            FAT_index =  media_ptr -> fx_media_cluster_search_start;
+        }
+#ifdef FX_ENABLE_EXFAT
+        if (!(file_ptr -> fx_file_dir_entry.fx_dir_entry_dont_use_fat & 1)
+#ifdef FX_ENABLE_FAULT_TOLERANT
+            || (media_ptr -> fx_media_fault_tolerant_enabled == FX_TRUE)
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+           )
+        {
+#endif /* FX_ENABLE_EXFAT */
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+            if (media_ptr -> fx_media_fault_tolerant_enabled)
+            {
+
+                /* Link the last cluster back to original FAT.  */
+                status = _fx_utility_FAT_entry_write(media_ptr, last_cluster, insertion_back);
+            }
+            else
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+            {
+
+                /* Place an end-of-file marker on the last cluster.  */
+                status = _fx_utility_FAT_entry_write(media_ptr, last_cluster, media_ptr -> fx_media_fat_last);
+            }
+
+            /* Check for a bad FAT write status.  */
+            if (status !=  FX_SUCCESS)
+            {
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* Return the bad status.  */
+                return(status);
+            }
+
+#ifdef FX_ENABLE_EXFAT
+        }
+#endif /* FX_ENABLE_EXFAT */
+
+        /* Determine if the file already had clusters.  */
+        if (file_ptr -> fx_file_last_physical_cluster)
+        {
+#ifdef FX_ENABLE_EXFAT
+            if (!(file_ptr -> fx_file_dir_entry.fx_dir_entry_dont_use_fat & 1))
+            {
+#endif /* FX_ENABLE_EXFAT */
+
+                /* Now, link the file's old last cluster to the first cluster of the new chain.  */
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                if (insertion_front)
+                {
+                    status = _fx_utility_FAT_entry_write(media_ptr, insertion_front, first_new_cluster);
+                }
+                else if ((media_ptr -> fx_media_fault_tolerant_enabled == FX_FALSE) ||
+                         ((replace_clusters == 0) && (first_new_cluster)))
+                {
+                    status = _fx_utility_FAT_entry_write(media_ptr, file_ptr -> fx_file_last_physical_cluster, first_new_cluster);
+                }
+#else
+                status = _fx_utility_FAT_entry_write(media_ptr, file_ptr -> fx_file_last_physical_cluster, first_new_cluster);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                /* Check for a bad FAT write status.  */
+                if (status !=  FX_SUCCESS)
+                {
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                    FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                    /* Release media protection.  */
+                    FX_UNPROTECT
+
+                    /* Return the bad status.  */
+                    return(status);
+                }
+#ifdef FX_ENABLE_EXFAT
+            }
+#endif /* FX_ENABLE_EXFAT */
+        }
+
+#ifdef FX_FAULT_TOLERANT
+
+#ifdef FX_ENABLE_EXFAT
+        if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+        {
+
+            /* Flush exFAT bitmap.  */
+            _fx_utility_exFAT_bitmap_flush(media_ptr);
+        }
+#endif /* FX_ENABLE_EXFAT */
+
+        /* Ensure the new FAT chain is properly written to the media.  */
+
+        /* Flush the cached individual FAT entries */
+        _fx_utility_FAT_flush(media_ptr);
+#endif
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        if (media_ptr -> fx_media_fault_tolerant_enabled)
+        {
+
+            /* Clear undo phase. */
+            media_ptr -> fx_media_fault_tolerant_state &= (UCHAR)(~FX_FAULT_TOLERANT_STATE_SET_FAT_CHAIN & 0xff);
+
+            /* Update the last cluster? */
+            if (insertion_back == media_ptr -> fx_media_fat_last)
+            {
+
+                /* Yes. Update the file control block with the last physical cluster.  */
+                file_ptr -> fx_file_last_physical_cluster =  last_cluster;
+            }
+        }
+        else
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+        {
+
+            /* Update the file control block with the last physical cluster.  */
+            file_ptr -> fx_file_last_physical_cluster =  last_cluster;
+        }
+    }
+
+    /* Check for a need to increment to the next sector within a previously
+       allocated cluster.  */
+    if (file_ptr -> fx_file_current_logical_offset >=
+        media_ptr -> fx_media_bytes_per_sector)
+    {
+
+        /* Update the sector specific file parameters to start at the
+           next logical sector.  */
+        file_ptr -> fx_file_current_logical_sector++;
+        file_ptr -> fx_file_current_relative_sector++;
+        file_ptr -> fx_file_current_logical_offset =  0;
+    }
+
+    /* At this point there is enough room to perform the file write operation.  */
+
+    /* Setup local buffer pointer.  */
+    source_ptr =  (UCHAR *)buffer_ptr;
+
+    /* Setup the remaining number of bytes to write.  */
+    bytes_remaining =  size;
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    if (replace_clusters > 0)
+    {
+
+        /* Force update current cluster and sector. */
+        file_ptr -> fx_file_current_physical_cluster = first_new_cluster;
+        file_ptr -> fx_file_current_logical_sector =    ((ULONG)media_ptr -> fx_media_data_sector_start) +
+            (((ULONG64)(first_new_cluster - FX_FAT_ENTRY_START)) *
+             ((ULONG)media_ptr -> fx_media_sectors_per_cluster)) +
+            file_ptr -> fx_file_current_relative_sector;
+
+        /* Copy sectors in replaced cluster but not overwritten at the front. */
+        for (i = 0; i < file_ptr -> fx_file_current_relative_sector; i++)
+        {
+            status =  _fx_utility_logical_sector_read(media_ptr,
+                                                      ((ULONG)media_ptr -> fx_media_data_sector_start) +
+                                                      (((ULONG)(copy_head_cluster - FX_FAT_ENTRY_START)) *
+                                                       ((ULONG)media_ptr -> fx_media_sectors_per_cluster)) + i,
+                                                      media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DATA_SECTOR);
+
+            /* Check for good completion status.  */
+            if (status !=  FX_SUCCESS)
+            {
+
+                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* Return the error status.  */
+                return(status);
+            }
+
+            /* Write back the current logical sector.  */
+            status =  _fx_utility_logical_sector_write(media_ptr,
+                                                       ((ULONG)media_ptr -> fx_media_data_sector_start) +
+                                                       (((ULONG)(file_ptr -> fx_file_current_physical_cluster - FX_FAT_ENTRY_START)) *
+                                                        ((ULONG)media_ptr -> fx_media_sectors_per_cluster)) + i,
+                                                       media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DATA_SECTOR);
+
+            /* Check for good completion status.  */
+            if (status !=  FX_SUCCESS)
+            {
+
+                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* Return the error status.  */
+                return(status);
+            }
+        }
+    }
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Loop to write all of the bytes.  */
+    while (bytes_remaining)
+    {
+
+        /* Determine if a beginning or ending partial write is required.  */
+        if ((file_ptr -> fx_file_current_logical_offset) ||
+            (bytes_remaining < media_ptr -> fx_media_bytes_per_sector))
+        {
+
+            /* A partial sector write is required.  */
+
+            /* Read the current logical sector.  */
+#ifdef FX_ENABLE_FAULT_TOLERANT
+            if (replace_clusters > 0)
+            {
+                if (file_ptr -> fx_file_current_physical_cluster == first_new_cluster)
+                {
+
+                    /* It's at beginning. */
+                    status =  _fx_utility_logical_sector_read(media_ptr,
+                                                              ((ULONG)media_ptr -> fx_media_data_sector_start) +
+                                                              (((ULONG)(copy_head_cluster - FX_FAT_ENTRY_START)) *
+                                                               ((ULONG)media_ptr -> fx_media_sectors_per_cluster)) +
+                                                              file_ptr -> fx_file_current_relative_sector,
+                                                              media_ptr -> fx_media_memory_buffer, (ULONG)1, FX_DATA_SECTOR);
+                }
+                else if (data_append == FX_FALSE)
+                {
+
+                    /* It's at ending. */
+                    status =  _fx_utility_logical_sector_read(media_ptr,
+                                                              ((ULONG)media_ptr -> fx_media_data_sector_start) +
+                                                              (((ULONG)(copy_tail_cluster - FX_FAT_ENTRY_START)) *
+                                                               ((ULONG)media_ptr -> fx_media_sectors_per_cluster)) +
+                                                              file_ptr -> fx_file_current_relative_sector,
+                                                              media_ptr -> fx_media_memory_buffer, (ULONG)1, FX_DATA_SECTOR);
+                }
+                else
+                {
+
+                    /* It's at ending. */
+                    status =  _fx_utility_logical_sector_read(media_ptr,
+                                                              file_ptr -> fx_file_current_logical_sector,
+                                                              media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DATA_SECTOR);
+                }
+            }
+            else
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+            {
+                status =  _fx_utility_logical_sector_read(media_ptr,
+                                                          file_ptr -> fx_file_current_logical_sector,
+                                                          media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DATA_SECTOR);
+            }
+
+            /* Check for good completion status.  */
+            if (status !=  FX_SUCCESS)
+            {
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* Return the error status.  */
+                return(status);
+            }
+
+            /* Copy the appropriate number of bytes into the destination buffer.  */
+            copy_bytes =  media_ptr -> fx_media_bytes_per_sector -
+                file_ptr -> fx_file_current_logical_offset;
+
+            /* Check to see if only a portion of the sector needs to be
+               copied.  */
+            if (copy_bytes > bytes_remaining)
+            {
+
+                /* Adjust the number of bytes to copy.  */
+                copy_bytes =  (ULONG)bytes_remaining;
+            }
+
+            /* Actually perform the memory copy.  */
+            _fx_utility_memory_copy(source_ptr, ((UCHAR *)media_ptr -> fx_media_memory_buffer) +  /* Use case of memcpy is verified. */
+                                    file_ptr -> fx_file_current_logical_offset,
+                                    copy_bytes);
+
+            /* Write back the current logical sector.  */
+            status =  _fx_utility_logical_sector_write(media_ptr, file_ptr -> fx_file_current_logical_sector,
+                                                       media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DATA_SECTOR);
+
+            /* Check for good completion status.  */
+            if (status !=  FX_SUCCESS)
+            {
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* Return the error status.  */
+                return(status);
+            }
+
+
+            /* Increment the logical sector byte offset.  */
+            file_ptr -> fx_file_current_logical_offset =
+                file_ptr -> fx_file_current_logical_offset + copy_bytes;
+
+            /* Adjust the remaining bytes to read.  */
+            bytes_remaining =  bytes_remaining - copy_bytes;
+
+            /* Adjust the pointer to the source buffer.  */
+            source_ptr =  source_ptr + copy_bytes;
+        }
+        else
+        {
+
+            /* Attempt to write multiple sectors directly to the media.  */
+
+            /* Calculate the number of whole sectors to write.  */
+            sectors =  (UINT)(bytes_remaining / media_ptr -> fx_media_bytes_per_sector);
+
+            next_cluster = cluster = file_ptr -> fx_file_current_physical_cluster;
+
+            for (i = (media_ptr -> fx_media_sectors_per_cluster -
+                      file_ptr -> fx_file_current_relative_sector); i < sectors; i += media_ptr -> fx_media_sectors_per_cluster)
+            {
+#ifdef FX_ENABLE_EXFAT
+                if (file_ptr -> fx_file_dir_entry.fx_dir_entry_dont_use_fat & 1)
+                {
+                    cluster++;
+                }
+                else
+                {
+#endif /* FX_ENABLE_EXFAT */
+                    status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
+
+                    /* Determine if an error is present.  */
+                    if ((status != FX_SUCCESS) || (next_cluster < FX_FAT_ENTRY_START) ||
+                        (next_cluster > media_ptr -> fx_media_fat_reserved))
+                    {
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                        /* Release media protection.  */
+                        FX_UNPROTECT
+
+                        /* Send error message back to caller.  */
+                        if (status != FX_SUCCESS)
+                        {
+                            return(status);
+                        }
+                        else
+                        {
+                            return(FX_FILE_CORRUPT);
+                        }
+                    }
+
+                    if (next_cluster != cluster + 1)
+                    {
+                        break;
+                    }
+                    else
+                    {
+                        cluster = next_cluster;
+                    }
+#ifdef FX_ENABLE_EXFAT
+                }
+#endif /* FX_ENABLE_EXFAT */
+            }
+
+            if (i < sectors)
+            {
+                sectors = i;
+            }
+
+            /* Perform the data write directly from the user's buffer of
+               the appropriate number of sectors.  */
+            status =  _fx_utility_logical_sector_write(media_ptr, file_ptr -> fx_file_current_logical_sector,
+                                                       source_ptr, (ULONG) sectors, FX_DATA_SECTOR);
+
+            /* Check for good completion status.  */
+            if (status !=  FX_SUCCESS)
+            {
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* Return the error status.  */
+                return(status);
+            }
+
+            /* Now adjust the various file pointers.  */
+
+            /* Increment the current logical sector.  Subtract one from
+               the sector count because we are going to use the logical
+               offset to do additional sector/cluster arithmetic below.  */
+            file_ptr -> fx_file_current_logical_sector =
+                file_ptr -> fx_file_current_logical_sector +
+                (sectors - 1);
+
+            /* Move the relative cluster and sector as well.  */
+            file_ptr -> fx_file_current_relative_cluster = file_ptr -> fx_file_current_relative_cluster +
+                (file_ptr -> fx_file_current_relative_sector + (sectors - 1)) /
+                media_ptr -> fx_media_sectors_per_cluster;
+
+            file_ptr -> fx_file_current_relative_sector =
+                (file_ptr -> fx_file_current_relative_sector + (sectors - 1)) %
+                media_ptr -> fx_media_sectors_per_cluster;
+
+            /* Increment the logical sector byte offset.  */
+            file_ptr -> fx_file_current_logical_offset =
+                media_ptr -> fx_media_bytes_per_sector;
+
+            file_ptr -> fx_file_current_physical_cluster = cluster;
+
+            /* Adjust the remaining bytes.  */
+            bytes_remaining =  bytes_remaining -
+                (((ULONG)media_ptr -> fx_media_bytes_per_sector) * sectors);
+
+            /* Adjust the pointer to the source buffer.  */
+            source_ptr =  source_ptr +
+                (((ULONG)media_ptr -> fx_media_bytes_per_sector) * sectors);
+        }
+
+        /* At this point, we have either written a partial sector or have successfully
+           written one or more whole sectors.  Determine if we are at the end of
+           the current logical sector.  */
+        if (file_ptr -> fx_file_current_logical_offset >=
+            media_ptr -> fx_media_bytes_per_sector)
+        {
+
+            /* Determine if we are at the exact physical end of the file.  */
+            if ((bytes_remaining == 0) &&
+                ((file_ptr -> fx_file_current_file_offset + size) >=
+                 file_ptr -> fx_file_current_available_size))
+            {
+
+                /* Skip the following file parameter adjustments.  The next write will
+                   detect the logical offset out of the range of the sector and reset
+                   all of the pertinent information.  */
+                break;
+            }
+
+            /* We need to move to the next logical sector, but first
+               determine if the next logical sector is within the same
+               cluster.  */
+
+            /* Increment the current relative sector in the cluster.  */
+            file_ptr -> fx_file_current_relative_sector++;
+
+            /* Determine if this is in a new cluster.  */
+            if (file_ptr -> fx_file_current_relative_sector >=
+                media_ptr -> fx_media_sectors_per_cluster)
+            {
+
+                /* Yes, we need to move to the next cluster.  */
+#ifdef FX_ENABLE_EXFAT
+                if (file_ptr -> fx_file_dir_entry.fx_dir_entry_dont_use_fat & 1)
+                {
+
+                    next_cluster = file_ptr -> fx_file_current_physical_cluster + 1;
+                }
+                else
+                {
+#endif /* FX_ENABLE_EXFAT */
+
+                    /* Read the FAT entry of the current cluster to find
+                       the next cluster.  */
+                    status =  _fx_utility_FAT_entry_read(media_ptr,
+                                                         file_ptr -> fx_file_current_physical_cluster, &next_cluster);
+
+                    /* Determine if an error is present.  */
+                    if ((status != FX_SUCCESS) || (next_cluster < FX_FAT_ENTRY_START) ||
+                        (next_cluster > media_ptr -> fx_media_fat_reserved))
+                    {
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                        /* Release media protection.  */
+                        FX_UNPROTECT
+
+                        /* Send error message back to caller.  */
+                        if (status != FX_SUCCESS)
+                        {
+                            return(status);
+                        }
+                        else
+                        {
+                            return(FX_FILE_CORRUPT);
+                        }
+                    }
+#ifdef FX_ENABLE_EXFAT
+                }
+#endif /* FX_ENABLE_EXFAT */
+
+                /* Otherwise, we have a new cluster.  Save it in the file
+                   control block and calculate a new logical sector value.  */
+                file_ptr -> fx_file_current_physical_cluster =  next_cluster;
+                file_ptr -> fx_file_current_relative_cluster++;
+                file_ptr -> fx_file_current_logical_sector = ((ULONG)media_ptr -> fx_media_data_sector_start) +
+                    ((((ULONG64)next_cluster) - FX_FAT_ENTRY_START) *
+                     ((ULONG)media_ptr -> fx_media_sectors_per_cluster));
+                file_ptr -> fx_file_current_relative_sector =  0;
+            }
+            else
+            {
+
+                /* Still within the same cluster so just increment the
+                   logical sector.  */
+                file_ptr -> fx_file_current_logical_sector++;
+            }
+
+            /* In either case, we are now positioned at a new sector so
+               clear the logical sector offset.  */
+            file_ptr -> fx_file_current_logical_offset =  0;
+        }
+    }
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    if (((replace_clusters > 0) && (data_append == FX_FALSE)) &&
+        (file_ptr -> fx_file_current_logical_offset || file_ptr -> fx_file_current_relative_sector))
+    {
+
+        /* Copy sectors in replaced cluster but not overwritten at the end. */
+        if (file_ptr -> fx_file_current_logical_offset == 0)
+        {
+            i = file_ptr -> fx_file_current_relative_sector;
+        }
+        else
+        {
+            i = file_ptr -> fx_file_current_relative_sector + 1;
+        }
+        for (; i < media_ptr -> fx_media_sectors_per_cluster; i++)
+        {
+            status =  _fx_utility_logical_sector_read(media_ptr,
+                                                      ((ULONG)media_ptr -> fx_media_data_sector_start) +
+                                                      (((ULONG)(copy_tail_cluster - FX_FAT_ENTRY_START)) *
+                                                       ((ULONG)media_ptr -> fx_media_sectors_per_cluster)) + i,
+                                                      media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DATA_SECTOR);
+
+            /* Check for good completion status.  */
+            if (status !=  FX_SUCCESS)
+            {
+
+                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* Return the error status.  */
+                return(status);
+            }
+
+            /* Write back the current logical sector.  */
+            status =  _fx_utility_logical_sector_write(media_ptr,
+                                                       ((ULONG)media_ptr -> fx_media_data_sector_start) +
+                                                       (((ULONG)(file_ptr -> fx_file_current_physical_cluster - FX_FAT_ENTRY_START)) *
+                                                        ((ULONG)media_ptr -> fx_media_sectors_per_cluster)) + i,
+                                                       media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DATA_SECTOR);
+
+            /* Check for good completion status.  */
+            if (status !=  FX_SUCCESS)
+            {
+
+                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* Return the error status.  */
+                return(status);
+            }
+        }
+    }
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Adjust the current file offset accordingly.  */
+    file_ptr -> fx_file_current_file_offset =
+        file_ptr -> fx_file_current_file_offset + size;
+
+    /* Copy the new file size into the directory entry.  */
+    file_ptr -> fx_file_dir_entry.fx_dir_entry_file_size =
+        file_ptr -> fx_file_current_file_size;
+
+    /* Determine if this write was done past the previous file size.  */
+    if (file_ptr -> fx_file_current_file_offset >
+        file_ptr -> fx_file_current_file_size)
+    {
+
+        /* Yes, we have written past the previous end of the file.  Update
+           the file size.  */
+        file_ptr -> fx_file_current_file_size =  file_ptr -> fx_file_current_file_offset;
+
+#ifndef FX_DONT_UPDATE_OPEN_FILES
+
+        /* Search the opened files list to see if the same file is opened for reading.  */
+        open_count =  media_ptr -> fx_media_opened_file_count;
+        search_ptr =  media_ptr -> fx_media_opened_file_list;
+        while (open_count)
+        {
+
+            /* Is this file the same file opened for reading?  */
+            if ((search_ptr != file_ptr) &&
+                (search_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector ==
+                 file_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector) &&
+                (search_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset ==
+                 file_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset))
+            {
+
+                /* Yes, the same file is opened for reading.  */
+
+                /* Setup the new size.  */
+                search_ptr -> fx_file_current_file_size =  file_ptr -> fx_file_current_file_offset;
+
+                /* Setup the new directory entry.  */
+                search_ptr -> fx_file_dir_entry.fx_dir_entry_cluster =      file_ptr -> fx_file_dir_entry.fx_dir_entry_cluster;
+                search_ptr -> fx_file_dir_entry.fx_dir_entry_file_size =    file_ptr -> fx_file_dir_entry.fx_dir_entry_file_size;
+                search_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector =   file_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector;
+                search_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset =  file_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset;
+
+                /* Setup the last cluster. This really isn't used during reading, but it is nice to keep things
+                   consistent.  */
+                search_ptr -> fx_file_last_physical_cluster =  file_ptr -> fx_file_last_physical_cluster;
+
+                /* Update the available clusters as well.  */
+                search_ptr -> fx_file_current_available_size =  file_ptr -> fx_file_current_available_size;
+
+                /* Determine if an empty file was previously opened.  */
+                if (search_ptr -> fx_file_total_clusters == 0)
+                {
+
+                    /* Setup initial parameters.  */
+                    search_ptr -> fx_file_total_clusters =            file_ptr -> fx_file_total_clusters;
+                    search_ptr -> fx_file_current_physical_cluster =  file_ptr -> fx_file_first_physical_cluster;
+                    search_ptr -> fx_file_current_relative_cluster =  0;
+                    search_ptr -> fx_file_current_logical_sector =    ((ULONG)media_ptr -> fx_media_data_sector_start) +
+                        (((ULONG64)(file_ptr -> fx_file_first_physical_cluster - FX_FAT_ENTRY_START)) *
+                         ((ULONG)media_ptr -> fx_media_sectors_per_cluster));
+                    search_ptr -> fx_file_current_relative_sector =   0;
+                    search_ptr -> fx_file_current_logical_offset =    0;
+                    search_ptr -> fx_file_current_file_offset =       0;
+                }
+            }
+
+            /* Adjust the pointer and decrement the search count.  */
+            search_ptr =  search_ptr -> fx_file_opened_next;
+            open_count--;
+        }
+#endif
+    }
+
+    /* Finally, mark this file as modified.  */
+    file_ptr -> fx_file_modified =  FX_TRUE;
+
+#ifdef FX_FAULT_TOLERANT_DATA
+
+    /* Ensure that all file data is flushed out.  */
+
+    /* Flush the internal logical sector cache.  */
+    _fx_utility_logical_sector_flush(media_ptr, 1, media_ptr -> fx_media_total_sectors, FX_FALSE);
+
+    /* Lockout interrupts for time/date access.  */
+    FX_DISABLE_INTS
+
+    /* Set the new time and date.  */
+    file_ptr -> fx_file_dir_entry.fx_dir_entry_time =  _fx_system_time;
+    file_ptr -> fx_file_dir_entry.fx_dir_entry_date =  _fx_system_date;
+
+    /* Restore interrupts.  */
+    FX_RESTORE_INTS
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    if (media_ptr -> fx_media_fault_tolerant_enabled)
+    {
+
+        /* Copy the new file size into the directory entry.  */
+        file_ptr -> fx_file_dir_entry.fx_dir_entry_file_size = file_ptr -> fx_file_current_file_size;
+    }
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Write the directory entry to the media.  */
+#ifdef FX_ENABLE_EXFAT
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+
+        status = _fx_directory_exFAT_entry_write(
+                media_ptr, &(file_ptr -> fx_file_dir_entry), UPDATE_STREAM);
+    }
+    else
+    {
+#endif /* FX_ENABLE_EXFAT */
+        status =  _fx_directory_entry_write(media_ptr, &(file_ptr -> fx_file_dir_entry));
+#ifdef FX_ENABLE_EXFAT
+    }
+#endif /* FX_ENABLE_EXFAT */
+
+    /* Check for a good status.  */
+    if (status != FX_SUCCESS)
+    {
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Error writing the directory.  */
+        return(status);
+    }
+#endif
+
+    /* Update the trace event with the bytes written.  */
+    FX_TRACE_EVENT_UPDATE(trace_event, trace_timestamp, FX_TRACE_FILE_WRITE, 0, 0, 0, size)
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    /* End transaction. */
+    status = _fx_fault_tolerant_transaction_end(media_ptr);
+
+    /* Check for a bad status.  */
+    if (status != FX_SUCCESS)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the bad status.  */
+        return(status);
+    }
+
+    /* Update maximum size used if necessary. */
+    if (file_ptr -> fx_file_current_file_offset > file_ptr -> fx_file_maximum_size_used)
+    {
+        file_ptr -> fx_file_maximum_size_used = file_ptr -> fx_file_current_file_offset;
+    }
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Invoke file write callback. */
+    if (file_ptr -> fx_file_write_notify)
+    {
+        file_ptr -> fx_file_write_notify(file_ptr);
+    }
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* Return a successful status to the caller.  */
+    return(FX_SUCCESS);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_write_notify_set.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_write_notify_set.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_file_write_notify_set.c	(revision 30)
@@ -0,0 +1,83 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_file.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_file_write_notify_set                           PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function sets the notify function called whenever file is      */
+/*    is written to.                                                      */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    file_ptr                              File control block pointer    */
+/*    file_write_notify                     Notify function called when   */
+/*                                            file is written to          */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    FX_SUCCESS                                                          */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_file_write_notify_set(FX_FILE *file_ptr, VOID (*file_write_notify)(FX_FILE *file))
+{
+
+    /* Set the notify function. */
+    file_ptr -> fx_file_write_notify = file_write_notify;
+
+    /* Return successful status.  */
+    return(FX_SUCCESS);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_abort.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_abort.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_abort.c	(revision 30)
@@ -0,0 +1,189 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_media.h"
+#include "fx_file.h"
+#include "fx_utility.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_media_abort                                     PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function marks all open files for the specified media as       */
+/*    aborted and then removes the media control block from the open      */
+/*    media list and marks it as aborted as well.                         */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    tx_mutex_delete                       Delete the mutex              */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_media_abort(FX_MEDIA  *media_ptr)
+{
+
+FX_INT_SAVE_AREA
+ULONG    open_count;
+FX_FILE *file_ptr;
+
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of times this service has been called.  */
+    media_ptr -> fx_media_aborts++;
+#endif
+
+    /* Check the media to make sure it is open.  */
+    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
+    {
+
+        /* Return the media not opened error.  */
+        return(FX_MEDIA_NOT_OPEN);
+    }
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_MEDIA_ABORT, media_ptr, 0, 0, 0, FX_TRACE_MEDIA_EVENTS, 0, 0)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+    /* Loop through the media's open files.  */
+    open_count =  media_ptr -> fx_media_opened_file_count;
+    file_ptr =    media_ptr -> fx_media_opened_file_list;
+    while (open_count)
+    {
+
+        /* Mark the file as aborted.  */
+        file_ptr -> fx_file_id =  FX_FILE_ABORTED_ID;
+
+        /* Adjust the pointer and decrement the file opened count.  */
+        file_ptr =  file_ptr -> fx_file_opened_next;
+        open_count--;
+    }
+
+    /* Build the "abort" I/O driver request.  */
+    media_ptr -> fx_media_driver_request =      FX_DRIVER_ABORT;
+    media_ptr -> fx_media_driver_status =       FX_IO_ERROR;
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_ABORT, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+    /* Call the specified I/O driver with the abort request.  */
+    (media_ptr -> fx_media_driver_entry) (media_ptr);
+
+    /* Now remove this media from the open list.  */
+
+    /* Lockout interrupts for media removal.  */
+    FX_DISABLE_INTS
+
+    /* See if the media is the only one on the media opened list.  */
+    if (_fx_system_media_opened_count == ((ULONG) 1))
+    {
+
+        /* Only opened media, just set the opened list to NULL.  */
+        _fx_system_media_opened_ptr =  FX_NULL;
+    }
+    else
+    {
+
+        /* Otherwise, not the only opened media, link-up the neighbors.  */
+        (media_ptr -> fx_media_opened_next) -> fx_media_opened_previous =
+            media_ptr -> fx_media_opened_previous;
+        (media_ptr -> fx_media_opened_previous) -> fx_media_opened_next =
+            media_ptr -> fx_media_opened_next;
+
+        /* See if we have to update the opened list head pointer.  */
+        if (_fx_system_media_opened_ptr == media_ptr)
+        {
+
+            /* Yes, move the head pointer to the next opened media. */
+            _fx_system_media_opened_ptr =  media_ptr -> fx_media_opened_next;
+        }
+    }
+
+    /* Decrement the opened media counter.  */
+    _fx_system_media_opened_count--;
+
+    /* Finally, Indicate that this media is aborted.  */
+    media_ptr -> fx_media_id =  FX_MEDIA_ABORTED_ID;
+
+    /* Restore interrupt posture.  */
+    FX_RESTORE_INTS
+
+    /* Delete the media protection structure if FX_SINGLE_THREAD is not
+       defined.  */
+#ifndef FX_SINGLE_THREAD
+
+#ifndef FX_DONT_CREATE_MUTEX
+
+    /* Note that the protection is never released. The mutex delete
+       service will handle all threads waiting access to this media
+       control block.  */
+    tx_mutex_delete(& (media_ptr -> fx_media_protect));
+#endif
+#endif
+
+#ifdef FX_DONT_CREATE_MUTEX
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+#endif
+
+    /* Return status to the caller.  */
+    return(FX_SUCCESS);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_boot_info_extract.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_boot_info_extract.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_boot_info_extract.c	(revision 30)
@@ -0,0 +1,331 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_media.h"
+#include "fx_utility.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_media_boot_info_extract                         PORTABLE C      */
+/*                                                           6.1.10       */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function extracts and validates the information from the boot  */
+/*    record found in the memory buffer.  If the boot record is invalid,  */
+/*    an FX_MEDIA_INVALID status is returned to the caller.               */
+/*                                                                        */
+/*    The FAT boot sector (512 bytes) that is operated on by this         */
+/*    function must look like the following:                              */
+/*                                                                        */
+/*          Byte Offset         Meaning             Size                  */
+/*                                                                        */
+/*            0x000         Jump Instructions        3                    */
+/*            0x003         OEM Name                 8                    */
+/*            0x00B        *Bytes per Sector         2                    */
+/*            0x00D        *Sectors per Cluster      1                    */
+/*            0x00E        *Reserved Sectors         2                    */
+/*            0x010        *Number of FATs           1                    */
+/*            0x011        *Max Root Dir Entries     2                    */
+/*            0x013        *Number of Sectors        2                    */
+/*            0x015         Media Type               1                    */
+/*            0x016        *Sectors per FAT          2                    */
+/*            0x018        *Sectors per Track        2                    */
+/*            0x01A        *Number of Heads          2                    */
+/*            0x01C        *Hidden Sectors           4                    */
+/*            0x020        *Huge Sectors             4                    */
+/*            0x024         Drive Number             1                    */
+/*            0x025         Reserved                 1                    */
+/*            0x026         Boot Signature           1                    */
+/*            0x027         Volume ID                4                    */
+/*            0x02B         Volume Label             11                   */
+/*            0x036         File System Type         8                    */
+/*             ...              ...                 ...                   */
+/*            0x1FE       **Signature (0x55aa)       2                    */
+/*                                                                        */
+/*            * Denotes which elements of the boot record                 */
+/*              FileX uses.                                               */
+/*                                                                        */
+/*            **Denotes the element is checked by the I/O                 */
+/*              driver.  This eliminates the need for a minimum           */
+/*              512-byte buffer for FileX.                                */
+/*                                                                        */
+/*  Note: All values above are in little endian format, i.e. the LSB is   */
+/*        in the lowest address.                                          */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_16_unsigned_read          Read a UINT from buffer       */
+/*    _fx_utility_32_unsigned_read          Read a ULONG from buffer      */
+/*    _fx_utility_64_unsigned_read          Read a ULONG64 from memory    */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    _fx_media_open                        Media open function           */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*  01-31-2022     Bhupendra Naphade        Modified comment(s), added    */
+/*                                            check for bimap cache size, */
+/*                                            resulting in version 6.1.10 */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_media_boot_info_extract(FX_MEDIA *media_ptr)
+{
+
+UCHAR *boot_sector;
+
+
+    /* Move the buffer pointer into a local copy.  */
+    boot_sector =  media_ptr -> fx_media_driver_buffer;
+
+    /* Extract the number of bytes per sector.  */
+    media_ptr -> fx_media_bytes_per_sector =    _fx_utility_16_unsigned_read(&boot_sector[FX_BYTES_SECTOR]);
+    if (media_ptr -> fx_media_bytes_per_sector == 0)
+#ifdef FX_ENABLE_EXFAT
+    {
+        /* Treat as exFAT volume.  */
+        /* Extract the number of bytes per sector.  */
+        media_ptr -> fx_media_exfat_bytes_per_sector_shift = boot_sector[FX_EF_BYTE_PER_SECTOR_SHIFT];
+
+        /* exFAT requires minimal value 9 (512 bytes) and maximum value 12(4096 bytes) for bytes_per_sector_shift */
+        if((media_ptr -> fx_media_exfat_bytes_per_sector_shift < 9) || (media_ptr -> fx_media_exfat_bytes_per_sector_shift > 12))
+        {
+            return(FX_MEDIA_INVALID);
+        }
+
+        media_ptr -> fx_media_bytes_per_sector = (UINT)(1 << media_ptr -> fx_media_exfat_bytes_per_sector_shift);
+
+        /* Validate bytes per sector value: no more than bitmap cache size */
+        if (media_ptr -> fx_media_bytes_per_sector > sizeof(media_ptr -> fx_media_exfat_bitmap_cache))
+        {
+            return(FX_NOT_ENOUGH_MEMORY);
+        }
+
+        media_ptr -> fx_media_total_sectors = _fx_utility_64_unsigned_read(&boot_sector[FX_EF_VOLUME_LENGTH]);
+        if (media_ptr -> fx_media_total_sectors == 0)
+        {
+            return(FX_MEDIA_INVALID);
+        }
+
+        media_ptr -> fx_media_reserved_sectors = _fx_utility_32_unsigned_read(&boot_sector[FX_EF_FAT_OFFSET]);
+        if (media_ptr -> fx_media_reserved_sectors == 0)
+        {
+            return(FX_MEDIA_INVALID);
+        }
+
+        media_ptr -> fx_media_sectors_per_FAT = _fx_utility_32_unsigned_read(&boot_sector[FX_EF_FAT_LENGTH]);
+        if (media_ptr -> fx_media_sectors_per_FAT == 0)
+        {
+            return(FX_MEDIA_INVALID);
+        }
+
+        media_ptr -> fx_media_data_sector_start = _fx_utility_32_unsigned_read(&boot_sector[FX_EF_CLUSTER_HEAP_OFFSET]);
+        if (media_ptr -> fx_media_data_sector_start == 0)
+        {
+            return(FX_MEDIA_INVALID);
+        }
+
+        media_ptr -> fx_media_total_clusters = _fx_utility_32_unsigned_read(&boot_sector[FX_EF_CLUSTER_COUNT]);
+        if (media_ptr -> fx_media_total_clusters == 0)
+        {
+            return(FX_MEDIA_INVALID);
+        }
+
+        media_ptr -> fx_media_exfat_sector_per_clusters_shift = boot_sector[FX_EF_SECTOR_PER_CLUSTER_SHIFT];
+        if (media_ptr -> fx_media_exfat_sector_per_clusters_shift > 25 - media_ptr -> fx_media_exfat_bytes_per_sector_shift)
+        {
+            return(FX_MEDIA_INVALID);
+        }
+        media_ptr -> fx_media_sectors_per_cluster = (UINT)(1 << media_ptr -> fx_media_exfat_sector_per_clusters_shift);
+
+        media_ptr -> fx_media_number_of_FATs = boot_sector[FX_EF_NUMBER_OF_FATS];
+        if (media_ptr -> fx_media_number_of_FATs == 0)
+        {
+            return(FX_MEDIA_INVALID);
+        }
+
+        media_ptr -> fx_media_root_cluster_32    = _fx_utility_32_unsigned_read(&boot_sector[FX_EF_FIRST_CLUSTER_OF_ROOT_DIR]);
+        /* Root cluster starts from at least FX_FAT_ENTRY_START (2), or higher. */
+        if (media_ptr -> fx_media_root_cluster_32 < FX_FAT_ENTRY_START)
+        {
+            return(FX_MEDIA_INVALID);
+        }
+
+        /* Overflow check. */
+        if (((ULONG64)media_ptr -> fx_media_data_sector_start +
+             (ULONG64)(media_ptr -> fx_media_root_cluster_32 - FX_FAT_ENTRY_START) *
+             media_ptr -> fx_media_sectors_per_cluster) > 0xFFFFFFFF)
+        {
+
+            /* Return the invalid media error status.  */
+            return(FX_MEDIA_INVALID);
+        }
+
+        /* Calculate logical number of root dir sector.  */
+        media_ptr -> fx_media_root_sector_start = media_ptr -> fx_media_data_sector_start +
+            (media_ptr -> fx_media_root_cluster_32 - FX_FAT_ENTRY_START) *
+            media_ptr -> fx_media_sectors_per_cluster;
+
+        media_ptr -> fx_media_exfat_volume_serial_number  = _fx_utility_32_unsigned_read(&boot_sector[FX_EF_VOLUME_SERIAL_NUMBER]);
+
+        media_ptr -> fx_media_exfat_file_system_revision  = _fx_utility_16_unsigned_read(&boot_sector[FX_EF_FILE_SYSTEM_REVISION]);
+
+        media_ptr -> fx_media_exfat_volume_flag          = _fx_utility_16_unsigned_read(&boot_sector[FX_EF_VOLUME_FLAGS]);
+
+        media_ptr -> fx_media_number_of_FATs = boot_sector[FX_EF_NUMBER_OF_FATS];
+
+        if (0 == media_ptr -> fx_media_number_of_FATs)
+        {
+            return(FX_MEDIA_INVALID);
+        }
+
+        /* Extract the number of hidden sectors.  */
+#ifdef FX_DRIVER_USE_64BIT_LBA
+        media_ptr -> fx_media_hidden_sectors =      _fx_utility_64_unsigned_read(&boot_sector[FX_EF_PARTITION_OFFSET]);
+#else
+        media_ptr -> fx_media_hidden_sectors =      _fx_utility_32_unsigned_read(&boot_sector[FX_EF_PARTITION_OFFSET]);
+#endif
+
+        media_ptr -> fx_media_exfat_drive_select       = boot_sector[FX_EF_DRIVE_SELECT];
+        media_ptr -> fx_media_exfat_percent_in_use       = boot_sector[FX_EF_PERCENT_IN_USE];
+
+        media_ptr -> fx_media_12_bit_FAT = FX_FALSE;
+        media_ptr -> fx_media_32_bit_FAT = FX_FALSE;
+
+        /* Legacy code support:
+           We will use fx_media_FAT_type for determine FAT type instead of
+           fx_media_12_bit_FAT and fx_media_32_bit_FAT.  */
+        media_ptr -> fx_media_12_bit_FAT = FX_FALSE;
+        media_ptr -> fx_media_32_bit_FAT = FX_FALSE;
+
+        media_ptr -> fx_media_FAT_type = FX_exFAT;
+
+        return(_fx_utility_exFAT_geometry_check(media_ptr, boot_sector));
+    }
+    else
+    {
+#else
+        return(FX_MEDIA_INVALID);
+#endif /* FX_ENABLE_EXFAT */
+
+
+        /* FAT12/16/32 volume.  */
+        /* Extract the number of sectors per track.  */
+        media_ptr -> fx_media_sectors_per_track =   _fx_utility_16_unsigned_read(&boot_sector[FX_SECTORS_PER_TRK]);
+
+        /* Extract the number of heads.  */
+        media_ptr -> fx_media_heads =               _fx_utility_16_unsigned_read(&boot_sector[FX_HEADS]);
+
+        /* Extract the total number of sectors.  */
+        media_ptr -> fx_media_total_sectors =       _fx_utility_16_unsigned_read(&boot_sector[FX_SECTORS]);
+        if (media_ptr -> fx_media_total_sectors == 0)
+        {
+            media_ptr -> fx_media_total_sectors = _fx_utility_32_unsigned_read(&boot_sector[FX_HUGE_SECTORS]);
+        }
+
+        if (media_ptr -> fx_media_total_sectors == 0)
+        {
+            return(FX_MEDIA_INVALID);
+        }
+
+        /* Extract the number of reserved sectors before the first FAT.  */
+        media_ptr -> fx_media_reserved_sectors =    _fx_utility_16_unsigned_read(&boot_sector[FX_RESERVED_SECTORS]);
+        if (media_ptr -> fx_media_reserved_sectors == 0)
+        {
+            return(FX_MEDIA_INVALID);
+        }
+
+        /* Extract the number of sectors per cluster.  */
+        media_ptr -> fx_media_sectors_per_cluster = ((UINT)boot_sector[FX_SECTORS_CLUSTER] & 0xFF);
+
+        /* There should always be at least one reserved sector, representing the boot record itself.  */
+        if (media_ptr -> fx_media_sectors_per_cluster == 0)
+        {
+            return(FX_MEDIA_INVALID);
+        }
+
+        /* Extract the number of sectors per FAT.  */
+        media_ptr -> fx_media_sectors_per_FAT =     _fx_utility_16_unsigned_read(&boot_sector[FX_SECTORS_PER_FAT]);
+        if (media_ptr -> fx_media_sectors_per_FAT == 0)
+        {
+            media_ptr -> fx_media_sectors_per_FAT = _fx_utility_32_unsigned_read(&boot_sector[FX_SECTORS_PER_FAT_32]);
+        }
+
+        if (media_ptr -> fx_media_sectors_per_FAT == 0)
+        {
+            return(FX_MEDIA_INVALID);
+        }
+
+        /* Extract the number of FATs.  */
+        media_ptr -> fx_media_number_of_FATs =      ((UINT)boot_sector[FX_NUMBER_OF_FATS] & 0xFF);
+        if (media_ptr -> fx_media_number_of_FATs == 0)
+        {
+            return(FX_BOOT_ERROR);
+        }
+
+        /* Extract the number of hidden sectors.  */
+#ifdef FX_DRIVER_USE_64BIT_LBA
+        media_ptr -> fx_media_hidden_sectors =      _fx_utility_64_unsigned_read(&boot_sector[FX_HIDDEN_SECTORS]);
+#else
+        media_ptr -> fx_media_hidden_sectors =      _fx_utility_32_unsigned_read(&boot_sector[FX_HIDDEN_SECTORS]);
+#endif
+        /* Extract the number of root directory entries.  */
+        media_ptr -> fx_media_root_directory_entries =  _fx_utility_16_unsigned_read(&boot_sector[FX_ROOT_DIR_ENTRIES]);
+
+        /* Extract root directory starting cluster (32 bit only) and compute start sector */
+        media_ptr -> fx_media_root_cluster_32 = _fx_utility_32_unsigned_read(&boot_sector[FX_ROOT_CLUSTER_32]);
+
+#ifdef FX_ENABLE_EXFAT
+    }
+#endif /* FX_ENABLE_EXFAT */
+
+    /* Return a successful status.  */
+    return(FX_SUCCESS);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_cache_invalidate.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_cache_invalidate.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_cache_invalidate.c	(revision 30)
@@ -0,0 +1,134 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_media.h"
+#include "fx_utility.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_media_cache_invalidate                          PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function examines the logical cache, flushing written sectors  */
+/*    out to the media and invalidating all sectors in the logical cache. */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_FAT_flush                 Flush cached FAT entries      */
+/*    _fx_utility_FAT_map_flush             Flush primary FAT changes to  */
+/*                                            secondary FAT(s)            */
+/*    _fx_utility_logical_sector_flush      Flush logical sector cache    */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_media_cache_invalidate(FX_MEDIA *media_ptr)
+{
+
+UINT status;
+UINT i;
+
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of times this service has been called.  */
+    media_ptr -> fx_media_flushes++;
+#endif
+
+    /* Check the media to make sure it is open.  */
+    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
+    {
+
+        /* Return the media not opened error.  */
+        return(FX_MEDIA_NOT_OPEN);
+    }
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_MEDIA_CACHE_INVALIDATE, media_ptr, 0, 0, 0, FX_TRACE_MEDIA_EVENTS, 0, 0)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+    /* Flush the cached individual FAT entries */
+    _fx_utility_FAT_flush(media_ptr);
+
+    /* Flush changed sector(s) in the primary FAT to secondary FATs.  */
+    _fx_utility_FAT_map_flush(media_ptr);
+
+    /* Clear the FAT cache entry array.  */
+    for (i = 0; i < FX_MAX_FAT_CACHE; i++)
+    {
+
+        /* Clear entry in the FAT cache.  */
+        media_ptr -> fx_media_fat_cache[i].fx_fat_cache_entry_cluster =   0;
+        media_ptr -> fx_media_fat_cache[i].fx_fat_cache_entry_value   =   0;
+    }
+
+    /* Clear the secondary FAT update map.  */
+    for (i = 0; i < FX_FAT_MAP_SIZE; i++)
+    {
+
+        /* Clear bit map entry for secondary FAT update.  */
+        media_ptr -> fx_media_fat_secondary_update_map[i] =  0;
+    }
+
+    /* Call the logical sector flush to invalidate the logical sector cache.  */
+    status =  _fx_utility_logical_sector_flush(media_ptr, ((ULONG64) 1), (ULONG64) (media_ptr -> fx_media_total_sectors), FX_TRUE);
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* If we get here, return successful status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_check.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_check.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_check.c	(revision 30)
@@ -0,0 +1,830 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_directory.h"
+#include "fx_media.h"
+#include "fx_utility.h"
+#ifdef FX_ENABLE_EXFAT
+#include "fx_directory_exFAT.h"
+#endif /* FX_ENABLE_EXFAT */
+
+
+/* Define parameters for FileX media check utility.  */
+
+#ifndef FX_MAX_DIRECTORY_NESTING
+#define FX_MAX_DIRECTORY_NESTING 20
+#endif
+
+
+/* Define data structures local to the FileX media check utility.  */
+
+typedef struct CURRENT_DIRECTORY_ENTRY_STRUCT
+{
+    ULONG current_directory_entry;
+    ULONG current_total_entries;
+    ULONG current_start_cluster;
+} CURRENT_DIRECTORY_ENTRY;
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_media_check                                     PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks the specified media for basic structural       */
+/*    errors, including cross linking, invalid FAT chains, and lost       */
+/*    clusters. The function also provides the capability to correct      */
+/*    errors.                                                             */
+/*                                                                        */
+/*    The algorithm is to follow all sub-directories immediately and      */
+/*    check their contents. The maximum depth of sub-directories is       */
+/*    determined by the constant FX_MAX_DIRECTORY_NESTING.                */
+/*    By default, this is set at 20. Basically, the FAT chain of every    */
+/*    file and sub-directory is traversed. If valid, clusters are marked  */
+/*    in a logical FAT bit map to signal they are already in-use. The     */
+/*    algorithm should detect any broken or cross linked FAT condition.   */
+/*                                                                        */
+/*    As for memory usage, the scratch memory supplied to the media check */
+/*    function is used to hold several directory entries, a data          */
+/*    structure to "stack" the current directory entry position before    */
+/*    diving into the sub-directory, and finally the logical FAT bit map. */
+/*    The basic data structures take from 512-1024 bytes and the logical  */
+/*    FAT bit map requires as many bits as there are clusters in your     */
+/*    device. For example, a device with 8000 clusters would require      */
+/*    1000 bytes to represent.                                            */
+/*                                                                        */
+/*    On the performance end of things, the traversal is reasonably fast  */
+/*    and is basically linear with the number of files and their sizes.   */
+/*    The lost cluster checking at the end of media check is a bit more   */
+/*    performance comprehensive. It basically checks that each unused     */
+/*    cluster is actually marked as free. You might decide to bypass this */
+/*    step if no other errors are found... or there might be ways to      */
+/*    optimize the search by reading whole FAT sectors. You probably just */
+/*    need to see how it behaves in your system.                          */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Pointer to a previously       */
+/*                                            opened media                */
+/*    scratch_memory_ptr                    Pointer to memory area for    */
+/*                                            media check to use (as      */
+/*                                            mentioned above)            */
+/*    scratch_memory_size                   Size of the scratch memory    */
+/*    error_correction_option               Specifies which - if any -    */
+/*                                            errors are corrected by     */
+/*                                            the media check function.   */
+/*                                            Setting the following bit   */
+/*                                            causes that error to be     */
+/*                                            corrected:                  */
+/*                                                                        */
+/*                                            0x01 -> Fix FAT Chain Errors*/
+/*                                            0x02 -> Fix Directory Entry */
+/*                                                      Errors            */
+/*                                            0x04 -> Fix Lost Clusters   */
+/*                                                                        */
+/*    errors_detected                       Specifies the destination     */
+/*                                            ULONG to place the error    */
+/*                                            report from media check.    */
+/*                                            This has a similar bit map  */
+/*                                            as before:                  */
+/*                                                                        */
+/*                                            0x01 -> FAT Chain Error(s)  */
+/*                                            0x02 -> Directory Entry     */
+/*                                                      Error(s)          */
+/*                                            0x04 -> Lost Cluster(s)     */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    FX_SUCCESS                            Media check performed its     */
+/*                                            operation successfully.     */
+/*                                            This does not mean that     */
+/*                                            there were no errors. The   */
+/*                                            errors_detected variable    */
+/*                                            needs to be examined.       */
+/*    FX_MEDIA_NOT_OPEN                     The media was not open.       */
+/*    FX_NOT_ENOUGH_MEMORY                  The scratch memory was not    */
+/*                                            large enough or the nesting */
+/*                                            depth was greater than the  */
+/*                                            maximum specified.          */
+/*    FX_IO_ERROR                           I/O Error reading/writing to  */
+/*                                            the media.                  */
+/*    FX_ERROR_NOT_FIXED                    Fundamental problem with      */
+/*                                            media that couldn't be fixed*/
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_media_cache_invalidate            Invalidate the cache          */
+/*    _fx_media_check_FAT_chain_check       Walk the supplied FAT chain   */
+/*    _fx_media_check_lost_cluster_check    Check for lost clusters       */
+/*    _fx_directory_entry_read              Directory entry read          */
+/*    _fx_directory_entry_write             Directory entry write         */
+/*    _fx_media_flush                       Flush changes to the media    */
+/*    _fx_utility_FAT_entry_write           Write value to FAT entry      */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_media_check(FX_MEDIA *media_ptr, UCHAR *scratch_memory_ptr, ULONG scratch_memory_size, ULONG error_correction_option, ULONG *errors_detected)
+{
+
+CURRENT_DIRECTORY_ENTRY *current_directory;
+ULONG                    total_entries, last_cluster, valid_clusters;
+ULONG                    bytes_per_cluster, i, current_errors;
+UINT                     status, long_name_size;
+UINT                     current_directory_index;
+UCHAR                   *logical_fat, *working_ptr;
+ALIGN_TYPE               address_mask;
+FX_DIR_ENTRY            *temp_dir_ptr, *source_dir_ptr, *dir_entry_ptr;
+
+#ifdef TX_ENABLE_EVENT_TRACE
+TX_TRACE_BUFFER_ENTRY   *trace_event;
+ULONG                    trace_timestamp;
+#endif
+
+#ifdef FX_ENABLE_EXFAT
+    current_errors = 0;
+#endif
+
+    /* Check the media to make sure it is open.  */
+    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
+    {
+
+        /* Return the media not opened error.  */
+        return(FX_MEDIA_NOT_OPEN);
+    }
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_MEDIA_CHECK, media_ptr, scratch_memory_ptr, scratch_memory_size, 0, FX_TRACE_MEDIA_EVENTS, &trace_event, &trace_timestamp)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+    /* Determine if there are any opened files.  */
+    if (media_ptr -> fx_media_opened_file_count)
+    {
+
+        /* There are opened files... this is an error!  */
+
+        /* Release protection.  */
+        FX_UNPROTECT
+
+        /* Return an error.  */
+        return(FX_ACCESS_ERROR);
+    }
+
+    /* Invalidate the cache.  */
+    _fx_media_cache_invalidate(media_ptr);
+
+    /* Initialize the reported error flag.  */
+    *errors_detected =  0;
+
+    /* Calculate the long name size, rounded up to something that is evenly divisible by 4.  */
+    long_name_size =  (((FX_MAX_LONG_NAME_LEN + 3) >> 2) << 2);
+
+    /* Calculate the number of bytes per cluster.  */
+    bytes_per_cluster =  media_ptr -> fx_media_sectors_per_cluster * media_ptr -> fx_media_bytes_per_sector;
+
+    /* Setup address mask.  */
+    address_mask =  sizeof(ULONG) - 1;
+    address_mask =  ~address_mask;
+
+    /* Setup working pointer.  */
+    working_ptr =  scratch_memory_ptr + (sizeof(ULONG) - 1);
+    working_ptr =  (UCHAR *)(((ALIGN_TYPE)working_ptr) & address_mask);
+
+    /* Memory is set aside for two FX_DIR_ENTRY structures */
+    dir_entry_ptr =  (FX_DIR_ENTRY *)working_ptr;
+
+    /* Adjust the scratch memory pointer forward.  */
+    working_ptr =  &working_ptr[sizeof(FX_DIR_ENTRY)];
+
+    /* Setup the name buffer for the first directory entry.  */
+    dir_entry_ptr -> fx_dir_entry_name =  (CHAR *)working_ptr;
+
+    /* Adjust the scratch memory pointer forward.  */
+    working_ptr =  working_ptr + long_name_size + (sizeof(ULONG) - 1);
+    working_ptr =  (UCHAR *)(((ALIGN_TYPE)working_ptr) & address_mask);
+
+    /* Setup the source directory entry.  */
+    source_dir_ptr =  (FX_DIR_ENTRY *)working_ptr;
+
+    /* Adjust the scratch memory pointer forward.  */
+    working_ptr =  &working_ptr[sizeof(FX_DIR_ENTRY)];
+
+    /* Setup the name buffer for the source directory entry.  */
+    source_dir_ptr -> fx_dir_entry_name =  (CHAR *)working_ptr;
+
+    /* Adjust the scratch memory pointer forward.  */
+    working_ptr =  working_ptr + long_name_size + (sizeof(ULONG) - 1);
+    working_ptr =  (UCHAR *)(((ALIGN_TYPE)working_ptr) & address_mask);
+
+    /* Setup the current directory stack memory.  */
+    current_directory =  (CURRENT_DIRECTORY_ENTRY *)working_ptr;
+
+    /* Allocate space for the size of the directory entry stack.  This basically
+       defines the maximum level of sub-directories supported.  */
+    working_ptr =  &working_ptr[(FX_MAX_DIRECTORY_NESTING * sizeof(CURRENT_DIRECTORY_ENTRY))];
+
+    /* Setup the initial current directory entry.  */
+    current_directory_index =  0;
+
+    /* Adjust the size to account for the header information.  */
+    if (scratch_memory_size < (ULONG)((working_ptr - scratch_memory_ptr)))
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the not enough memory error.  */
+        return(FX_NOT_ENOUGH_MEMORY);
+    }
+
+    /* Adjust the scratch memory size.  */
+    scratch_memory_size =  scratch_memory_size - (ULONG)(working_ptr - scratch_memory_ptr);
+
+    /* Memory is set aside for logical FAT - one bit per cluster */
+    logical_fat =  (UCHAR *)working_ptr;
+
+    /* Determine if there is enough memory.  */
+    if (scratch_memory_size < ((media_ptr -> fx_media_total_clusters >> 3) + 1))
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the not enough memory error.  */
+        return(FX_NOT_ENOUGH_MEMORY);
+    }
+
+    /* Initialize the logical FAT table. */
+    for (i = 0; i < ((media_ptr -> fx_media_total_clusters >> 3) + 1); i++)
+    {
+        /* Clear the logical FAT entry, which actually represents eight clusters.  */
+        logical_fat[i] =  0;
+    }
+
+#ifdef FX_ENABLE_EXFAT
+
+    /* Mark the clusters occupied by Allocation Bitmap table, Up-cast table and the first cluster of root directory. */
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+    ULONG offset = 0;
+
+        for (i = ((media_ptr -> fx_media_root_cluster_32 - FX_FAT_ENTRY_START) >> 3); i; i--)
+        {
+            logical_fat[offset++] = 0xff;
+        }
+
+        for (i = ((media_ptr -> fx_media_root_cluster_32 - FX_FAT_ENTRY_START) & 7); i; i--)
+        {
+            logical_fat[offset] = (UCHAR)((logical_fat[offset] << 1) | 0x1);
+        }
+    }
+#endif /* FX_ENABLE_EXFAT */
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    if (media_ptr -> fx_media_fault_tolerant_enabled)
+    {
+    ULONG cluster, cluster_number;
+
+        /* Mark the cluster used by fault tolerant as valid. */
+        for (cluster = media_ptr -> fx_media_fault_tolerant_start_cluster;
+             cluster < media_ptr -> fx_media_fault_tolerant_start_cluster + media_ptr -> fx_media_fault_tolerant_clusters;
+             cluster++)
+        {
+
+            cluster_number = cluster;
+
+#ifdef FX_ENABLE_EXFAT
+
+            /* For the index of the first cluster in exFAT is 2, adjust the number of clusters to fit Allocation Bitmap Table. */
+            /* We will compare logical_fat with Aollcation Bitmap table later to find out lost clusters. */
+            if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+            {
+                cluster_number = cluster - FX_FAT_ENTRY_START;
+            }
+#endif /* FX_ENABLE_EXFAT */
+
+            logical_fat[cluster_number >> 3] = (UCHAR)(logical_fat[cluster_number >> 3] | (1 << (cluster_number & 7)));
+        }
+    }
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* If FAT32 is present, determine if the root directory is coherent.  */
+#ifdef FX_ENABLE_EXFAT
+    if ((media_ptr -> fx_media_FAT_type == FX_FAT32) ||
+        (media_ptr -> fx_media_FAT_type == FX_exFAT))
+#else
+    if (media_ptr -> fx_media_32_bit_FAT)
+#endif /* FX_ENABLE_EXFAT */
+    {
+
+        /* A 32-bit FAT is present. We need to walk the clusters of the root directory to determine if
+           it is intact. */
+        current_errors =  _fx_media_check_FAT_chain_check(media_ptr, media_ptr -> fx_media_root_cluster_32,
+                                                          &last_cluster, &valid_clusters, logical_fat);
+
+        /* Make them part of the errors reported to the caller.  */
+        *errors_detected =  *errors_detected | current_errors;
+
+        /* Update the trace event with the errors detected.  */
+        FX_TRACE_EVENT_UPDATE(trace_event, trace_timestamp, FX_TRACE_MEDIA_CHECK, 0, 0, 0, *errors_detected)
+
+        /* Determine if the I/O error is set.  */
+        if (current_errors & FX_IO_ERROR)
+        {
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* File I/O Error.  */
+            return(FX_IO_ERROR);
+        }
+
+        /* Check the status.  */
+        if (*errors_detected)
+        {
+
+            /* Determine if we can fix the FAT32 root directory error.  */
+            if ((valid_clusters) && (error_correction_option & FX_FAT_CHAIN_ERROR))
+            {
+
+                /* Make the chain end at the last cluster. */
+                status = _fx_utility_FAT_entry_write(media_ptr, last_cluster, media_ptr -> fx_media_fat_last);
+
+                /* Determine if the write was successful.  */
+                if (status)
+                {
+
+                    /* Release media protection.  */
+                    FX_UNPROTECT
+
+                    /* Return the error code.  */
+                    return(status);
+                }
+
+                /* Adjust the total entries in the root directory.  */
+                media_ptr -> fx_media_root_directory_entries =  (valid_clusters * bytes_per_cluster) / FX_DIR_ENTRY_SIZE;
+            }
+            else
+            {
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* Return an error.  */
+                return(FX_ERROR_NOT_FIXED);
+            }
+        }
+    }
+
+    /* Pickup total entries in the root directory.  */
+    total_entries =  media_ptr -> fx_media_root_directory_entries;
+
+    /* Set temp directory pointer to NULL.  */
+    temp_dir_ptr =  FX_NULL;
+
+    /* Put the root directory information in the entry stack */
+    current_directory[current_directory_index].current_total_entries =    total_entries;
+    current_directory[current_directory_index].current_start_cluster =    media_ptr -> fx_media_fat_last;
+    current_directory[current_directory_index].current_directory_entry =  0;
+
+    /* Now we shall do the checking in depth first manner. */
+    do
+    {
+
+        /* Pickup the directory index.  */
+        i =  current_directory[current_directory_index].current_directory_entry;
+
+        /* Loop to process remaining directory entries.  */
+        while (i < current_directory[current_directory_index].current_total_entries)
+        {
+
+            /* Read a directory entry.  */
+#ifdef FX_ENABLE_EXFAT
+            /* Hash value of the file name is not cared. */
+            status =  _fx_directory_entry_read_ex(media_ptr, temp_dir_ptr, &i, dir_entry_ptr, 0);
+#else
+            status =  _fx_directory_entry_read(media_ptr, temp_dir_ptr, &i, dir_entry_ptr);
+#endif /* FX_ENABLE_EXFAT */
+
+            /* Determine if the read was successful.  */
+            if (status)
+            {
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* Return the error code.  */
+                return(status);
+            }
+
+            /* Check for the last entry.  */
+#ifdef FX_ENABLE_EXFAT
+            if (dir_entry_ptr -> fx_dir_entry_type == FX_EXFAT_DIR_ENTRY_TYPE_END_MARKER)
+#else
+            if (dir_entry_ptr -> fx_dir_entry_name[0] == (CHAR)FX_DIR_ENTRY_DONE)
+#endif /* FX_ENABLE_EXFAT */
+            {
+
+                /* Last entry in this directory - no need to check further.  */
+                break;
+            }
+
+            /* Is the entry free?  */
+#ifdef FX_ENABLE_EXFAT
+            if (dir_entry_ptr -> fx_dir_entry_type != FX_EXFAT_DIR_ENTRY_TYPE_FILE_DIRECTORY)
+#else
+            if ((dir_entry_ptr -> fx_dir_entry_name[0] == (CHAR)FX_DIR_ENTRY_FREE) && (dir_entry_ptr -> fx_dir_entry_short_name[0] == 0))
+#endif /* FX_ENABLE_EXFAT */
+            {
+
+                /* A deleted entry */
+                i++;
+                continue;
+            }
+
+#ifdef FX_ENABLE_EXFAT
+
+            /* Determine whether FAT chain is used. */
+            if (dir_entry_ptr -> fx_dir_entry_dont_use_fat & 1)
+            {
+            ULONG64 remaining_size = dir_entry_ptr -> fx_dir_entry_file_size;
+            ULONG   cluster = dir_entry_ptr -> fx_dir_entry_cluster, cluster_number;
+
+                valid_clusters = 0;
+
+                while (remaining_size)
+                {
+                    if (remaining_size >= bytes_per_cluster)
+                    {
+                        remaining_size -= bytes_per_cluster;
+                    }
+                    else
+                    {
+                        remaining_size = 0;
+                        last_cluster = cluster;
+                    }
+
+                    cluster_number = cluster - FX_FAT_ENTRY_START;
+
+                    /* Is the current cluster already marked? */
+                    if ((logical_fat[cluster_number / 8] >> (cluster_number % 8)) & 0x01)
+                    {
+                        current_errors = FX_FILE_SIZE_ERROR;
+                        last_cluster = dir_entry_ptr -> fx_dir_entry_cluster + valid_clusters;
+                        break;
+                    }
+                    
+                    /* Mark the current cluster. */
+                    logical_fat[cluster_number >> 3] = (UCHAR)(logical_fat[cluster_number >> 3] | (1 << (cluster_number & 7)));
+
+                    valid_clusters++;
+                    cluster++;
+                }
+            }
+            else
+            {
+#endif /* FX_ENABLE_EXFAT */
+
+                /* Look for any cross links or errors in the FAT chain of current directory entry. */
+                current_errors =  _fx_media_check_FAT_chain_check(media_ptr, dir_entry_ptr -> fx_dir_entry_cluster,
+                                                                  &last_cluster, &valid_clusters, logical_fat);
+#ifdef FX_ENABLE_EXFAT
+            }
+#endif /* FX_ENABLE_EXFAT */
+
+            /* Make them part of the errors reported to the caller.  */
+            *errors_detected =  *errors_detected | current_errors;
+
+            /* Update the trace event with the errors detected.  */
+            FX_TRACE_EVENT_UPDATE(trace_event, trace_timestamp, FX_TRACE_MEDIA_CHECK, 0, 0, 0, *errors_detected)
+
+            /* Determine if the I/O error is set.  */
+            if (current_errors & FX_IO_ERROR)
+            {
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* File I/O Error.  */
+                return(FX_IO_ERROR);
+            }
+
+            /* Check for errors.  */
+            if (*errors_detected)
+            {
+
+                /* Determine if we can fix the FAT chain.  */
+                if (error_correction_option & FX_FAT_CHAIN_ERROR)
+                {
+
+                    /* Determine if there is a valid cluster to write the EOF to.  */
+                    if (valid_clusters)
+                    {
+
+                        /* Write EOF in the last FAT entry.  */
+                        status =  _fx_utility_FAT_entry_write(media_ptr, last_cluster, media_ptr -> fx_media_fat_last);
+
+                        /* Determine if the write was successful.  */
+                        if (status)
+                        {
+
+                            /* Release media protection.  */
+                            FX_UNPROTECT
+
+                            /* Return the error code.  */
+                            return(status);
+                        }
+                    }
+                }
+            }
+
+            /* Determine if we need to update the size of the directory entry.  */
+            if (dir_entry_ptr -> fx_dir_entry_file_size > (valid_clusters * bytes_per_cluster))
+            {
+
+                /* Yes, update the directory entry's size.  */
+                dir_entry_ptr -> fx_dir_entry_file_size =  valid_clusters * bytes_per_cluster;
+
+                /* Determine if the new file size is zero. */
+                if (dir_entry_ptr -> fx_dir_entry_file_size == 0)
+                {
+
+                    /* Consider this a directory error.  */
+                    *errors_detected =  *errors_detected | FX_DIRECTORY_ERROR;
+
+                    /* Update the trace event with the errors detected.  */
+                    FX_TRACE_EVENT_UPDATE(trace_event, trace_timestamp, FX_TRACE_MEDIA_CHECK, 0, 0, 0, *errors_detected)
+
+                    /* Clear the starting cluster number of this directory entry.  */
+                    dir_entry_ptr -> fx_dir_entry_cluster =  0;
+
+                    /* If directory fixing is required, delete this directory entry as well.  */
+                    if (error_correction_option & FX_DIRECTORY_ERROR)
+                    {
+
+                        /* Mark the entry as deleted.  */
+                        dir_entry_ptr -> fx_dir_entry_name[0] =        (CHAR)FX_DIR_ENTRY_FREE;
+                        dir_entry_ptr -> fx_dir_entry_short_name[0] =  (CHAR)FX_DIR_ENTRY_FREE;
+                    }
+                }
+
+                /* Only update the directory if the FAT chain was actually updated.  */
+                if (error_correction_option & FX_FAT_CHAIN_ERROR)
+                {
+
+                    /* Update the directory entry.  */
+                    status =  _fx_directory_entry_write(media_ptr, dir_entry_ptr);
+
+                    /* Determine if the write was successful.  */
+                    if (status)
+                    {
+
+                        /* Release media protection.  */
+                        FX_UNPROTECT
+
+                        /* Return the error code.  */
+                        return(status);
+                    }
+                }
+            }
+
+            /* Determine if the entry is a sub-directory.  */
+            if ((dir_entry_ptr -> fx_dir_entry_attributes & FX_DIRECTORY)
+                 && (valid_clusters == 0))
+            {
+
+                /* Consider this a directory error.  */
+                *errors_detected =  *errors_detected | FX_DIRECTORY_ERROR;
+
+                /* Update the trace event with the errors detected.  */
+                FX_TRACE_EVENT_UPDATE(trace_event, trace_timestamp, FX_TRACE_MEDIA_CHECK, 0, 0, 0, *errors_detected)
+
+                /* Determine if we can fix the error.  */
+                if (error_correction_option & FX_DIRECTORY_ERROR)
+                {
+
+                    /* Yes, make the directory entry free.  */
+                    dir_entry_ptr -> fx_dir_entry_name[0] =        (CHAR)FX_DIR_ENTRY_FREE;
+                    dir_entry_ptr -> fx_dir_entry_short_name[0] =  (CHAR)FX_DIR_ENTRY_FREE;
+
+                    /* Delete the sub-directory entry.  */
+                    status =  _fx_directory_entry_write(media_ptr, dir_entry_ptr);
+
+                    /* Determine if the write was successful.  */
+                    if (status)
+                    {
+
+                        /* Release media protection.  */
+                        FX_UNPROTECT
+
+                        /* Return the error code.  */
+                        return(status);
+                    }
+
+                    /* Move to next entry.  */
+                    i++;
+                    continue;
+                }
+            }
+
+            /* Determine if the entry is a directory.  */
+            if (dir_entry_ptr -> fx_dir_entry_attributes & FX_DIRECTORY)
+            {
+
+                /* Current entry is a directory. The algorithm is designed to follow all
+                   sub-directories immediately, i.e., a depth first search.  */
+
+                /* First, save the next entry position. */
+                current_directory[current_directory_index].current_directory_entry =  i + 1;
+
+                /* Push the current directory entry on the stack.  */
+                current_directory_index++;
+
+                /* Check for current directory stack overflow.  */
+                if (current_directory_index >= FX_MAX_DIRECTORY_NESTING)
+                {
+
+                    /* Release media protection.  */
+                    FX_UNPROTECT
+
+                    /* Current directory stack overflow.  Return error.  */
+                    return(FX_NOT_ENOUGH_MEMORY);
+                }
+
+                /* Otherwise, setup the new directory entry.  */
+                current_directory[current_directory_index].current_total_entries =      (valid_clusters * bytes_per_cluster) / FX_DIR_ENTRY_SIZE;
+                current_directory[current_directory_index].current_start_cluster =      dir_entry_ptr -> fx_dir_entry_cluster;
+                current_directory[current_directory_index].current_directory_entry =    2;
+
+                /* Setup new source directory.  */
+                source_dir_ptr -> fx_dir_entry_cluster =              dir_entry_ptr -> fx_dir_entry_cluster;
+                source_dir_ptr -> fx_dir_entry_file_size =            current_directory[current_directory_index].current_total_entries;
+                source_dir_ptr -> fx_dir_entry_last_search_cluster =  0;
+                temp_dir_ptr =                                        source_dir_ptr;
+
+                /* Skip the first two entries of sub-directories.  */
+                i =  2;
+
+#ifdef FX_ENABLE_EXFAT
+
+                /* For exFAT, there is no dir-entries for ".." and ".". */
+                if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+                {
+                    current_directory[current_directory_index].current_directory_entry = 0;
+                    i =  0;
+                }
+#endif /* FX_ENABLE_EXFAT */
+            }
+            else
+            {
+
+                /* Regular file entry.  */
+
+                /* Check for an invalid file size.  */
+                if (((valid_clusters * bytes_per_cluster) - dir_entry_ptr -> fx_dir_entry_file_size) > bytes_per_cluster)
+                {
+
+                    /* There are more clusters allocated than needed for the file's size.  Indicate that this error
+                       is present.  */
+                    *errors_detected =  *errors_detected | FX_FILE_SIZE_ERROR;
+
+                    /* Update the trace event with the errors detected.  */
+                    FX_TRACE_EVENT_UPDATE(trace_event, trace_timestamp, FX_TRACE_MEDIA_CHECK, 0, 0, 0, *errors_detected)
+
+                    /* For now, don't shorten the cluster chain.  */
+                }
+
+                /* Look into the next entry in the current directory.  */
+                i++;
+            }
+        }
+
+        /* Once we get here, we have exhausted the current directory and need to return to the previous
+           directory.  */
+
+        /* Check for being at the root directory.  */
+        if (current_directory_index == 0)
+        {
+
+            /* Yes, we have now exhausted searching the root directory so we are done!  */
+            break;
+        }
+
+        /* Backup to the place we left off in the previous directory.  */
+        current_directory_index--;
+
+        /* Determine if we are now back at the root directory.  */
+        if (current_directory[current_directory_index].current_start_cluster == media_ptr -> fx_media_fat_last)
+        {
+
+            /* The search directory should be NULL since it is the root directory.  */
+            temp_dir_ptr =  FX_NULL;
+        }
+        else
+        {
+
+            /* Otherwise, we are returning to a sub-directory.  Setup the search directory
+               appropriately.  */
+            source_dir_ptr -> fx_dir_entry_cluster =              current_directory[current_directory_index].current_start_cluster;
+            source_dir_ptr -> fx_dir_entry_file_size =            current_directory[current_directory_index].current_total_entries;
+            source_dir_ptr -> fx_dir_entry_last_search_cluster =  0;
+            temp_dir_ptr =                                        source_dir_ptr;
+        }
+    } while (1);
+
+#ifdef FX_ENABLE_EXFAT
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+
+        /* If exFAT is in use, compare the logical_fat with Allocation Bitmap Table directly. */
+        current_errors =  _fx_media_check_exFAT_lost_cluster_check(media_ptr, logical_fat, media_ptr -> fx_media_total_clusters, error_correction_option);
+    }
+    else
+    {
+#endif /* FX_ENABLE_EXFAT */
+
+        /* At this point, all the files and sub-directories have been examined.  We now need to check for
+           lost clusters in the logical FAT.  A lost cluster is basically anything that is not reported in
+           the logical FAT that has a non-zero value in the real FAT.  */
+        current_errors =  _fx_media_check_lost_cluster_check(media_ptr, logical_fat, media_ptr -> fx_media_total_clusters, error_correction_option);
+#ifdef FX_ENABLE_EXFAT
+    }
+#endif /* FX_ENABLE_EXFAT */
+
+    /* Incorporate the error returned by the lost FAT check.  */
+    *errors_detected =  *errors_detected | current_errors;
+
+    /* Update the trace event with the errors detected.  */
+    FX_TRACE_EVENT_UPDATE(trace_event, trace_timestamp, FX_TRACE_MEDIA_CHECK, 0, 0, 0, *errors_detected)
+
+    /* Determine if the I/O error is set.  */
+    if (current_errors & FX_IO_ERROR)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* File I/O Error.  */
+        return(FX_IO_ERROR);
+    }
+
+    /* Determine if there was any error and update was selected.  */
+    if ((*errors_detected) && (error_correction_option))
+    {
+
+        /* Flush any unwritten items to the media.  */
+        _fx_media_flush(media_ptr);
+    }
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* At this point, we have completed the diagnostic of the media, return success!  */
+    return(FX_SUCCESS);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_check_FAT_chain_check.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_check_FAT_chain_check.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_check_FAT_chain_check.c	(revision 30)
@@ -0,0 +1,171 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_media.h"
+#include "fx_utility.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_media_check_FAT_chain_check                     PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function walks the supplied FAT chain looking for cross links  */
+/*    (FAT entries already used in another FAT chain) and abnormal FAT    */
+/*    entries and invalid chain termination.                              */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Pointer to a previously       */
+/*                                            opened media                */
+/*    starting_cluster                      Starting cluster of FAT chain */
+/*    last_valid_cluster                    Last valid cluster of chain   */
+/*    total_valid_clusters                  Total number of valid clusters*/
+/*    logical_fat                           Pointer to the logical FAT    */
+/*                                            bit map                     */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    error                                 Error code                    */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_FAT_entry_read            Read a FAT entry              */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    _fx_check_media                       Check media function          */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+ULONG  _fx_media_check_FAT_chain_check(FX_MEDIA *media_ptr, ULONG starting_cluster, ULONG *last_valid_cluster, ULONG *total_valid_clusters, UCHAR *logical_fat)
+{
+
+ULONG prev_cluster, cluster, next_clust = 0;
+ULONG cluster_number;
+ULONG count, error;
+UINT  status;
+
+
+    /* Initialize the error code.  */
+    error =  0;
+
+    /* Setup at the first cluster.  */
+    cluster =  starting_cluster;
+
+    /* Initialize the previous cluster.  */
+    prev_cluster =  0;
+
+    /* Initialize the count to 0. */
+    count =  0;
+
+    /* Loop to walk through the FAT chain.  */
+    while ((cluster >= (ULONG)FX_FAT_ENTRY_START) &&
+           (cluster < (FX_FAT_ENTRY_START + media_ptr -> fx_media_total_clusters)))
+    {
+
+        cluster_number = cluster;
+
+#ifdef FX_ENABLE_EXFAT
+
+        /* For the index of the first cluster in exFAT is 2, adjust the number of clusters to fit Allocation Bitmap Table. */
+        /* We will compare logical_fat with Aollcation Bitmap table later to find out lost clusters. */
+        if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+        {
+            cluster_number = cluster - FX_FAT_ENTRY_START;
+        }
+#endif /* FX_ENABLE_EXFAT */
+
+        /* Determine if this cluster is already in the logical FAT bit map.  */
+        if (logical_fat[cluster_number >> 3] & (1 << (cluster_number & 7)))
+        {
+
+            /* Yes, the cluster is already being used by another file or
+               sub-directory.  */
+            error =  FX_FAT_CHAIN_ERROR;
+            break;
+        }
+
+        /* Now read the contents of the cluster.  */
+        status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &next_clust);
+
+        /* Check the return status.  */
+        if (status != FX_SUCCESS)
+        {
+
+            /* Yes, the cluster is already being used by another file or
+               sub-directory.  */
+            error =  FX_IO_ERROR;
+            break;
+        }
+
+        /* Determine if the link is circular or the count is greater than the
+           total clusters.  */
+        if ((cluster == next_clust) ||
+            (next_clust < (ULONG)FX_FAT_ENTRY_START) ||
+            ((next_clust >= (FX_FAT_ENTRY_START + media_ptr -> fx_media_total_clusters)) &&
+             (next_clust != media_ptr -> fx_media_fat_last)))
+        {
+
+            error =  FX_FAT_CHAIN_ERROR;
+            break;
+        }
+
+        /* Everything is good with the chain at this point.  Mark it as valid.  */
+        logical_fat[cluster_number >> 3] = (UCHAR)(logical_fat[cluster_number >> 3] | (1 << (cluster_number & 7)));
+
+        /* Move the cluster variable forward.  */
+        prev_cluster =  cluster;
+        cluster =       next_clust;
+
+        /* Increment the number of valid clusters.  */
+        count++;
+    }
+
+    /* Return the last valid cluster and the total valid cluster count.  */
+    *last_valid_cluster =   prev_cluster;
+    *total_valid_clusters = count;
+
+    /* Return error code.  */
+    return(error);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_check_lost_cluster_check.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_check_lost_cluster_check.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_check_lost_cluster_check.c	(revision 30)
@@ -0,0 +1,282 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_media.h"
+#include "fx_utility.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_media_check_lost_cluster_check                  PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function examines all clusters to see if there are any unused  */
+/*    clusters that are also unavailable. If specified, this routine will */
+/*    also mark the cluster as available.                                 */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Pointer to a previously       */
+/*                                            opened media                */
+/*    logical_fat                           Pointer to the logical FAT    */
+/*                                            bit map                     */
+/*    total_clusters                        Total number of clusters      */
+/*    error_correction_option               Option for correcting lost    */
+/*                                            cluster errors              */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    error                                 Error code                    */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_FAT_entry_read            Read a FAT entry              */
+/*    _fx_utility_FAT_entry_write           Write a FAT entry             */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    _fx_check_media                       Check media function          */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+ULONG  _fx_media_check_lost_cluster_check(FX_MEDIA *media_ptr, UCHAR *logical_fat, ULONG total_clusters, ULONG error_correction_option)
+{
+
+ULONG cluster, next_cluster = 0;
+ULONG fat_last;
+ULONG error;
+UINT  status;
+
+
+    /* Calculate the FAT reserved and last sector values.  */
+    if (media_ptr -> fx_media_32_bit_FAT)
+    {
+        fat_last =      FX_LAST_CLUSTER_1_32;
+    }
+    else
+    {
+        fat_last =      FX_LAST_CLUSTER_1;
+    }
+
+    /* Initialize the error.  */
+    error =  0;
+
+    /* Loop through all the clusters to see if any clusters NOT in the logical sector FAT have
+       a non zero value.  */
+    for (cluster = FX_FAT_ENTRY_START; cluster < total_clusters; cluster++)
+    {
+
+        /* Determine if this cluster is in the logical FAT.  */
+        if (logical_fat[cluster >> 3] & (1 << (cluster & 7)))
+        {
+
+            /* Yes, the cluster is in use by a file or sub-directory.  Just continue the loop.  */
+            continue;
+        }
+
+        /* Otherwise, the cluster is not in use.  */
+
+        /* Read the contents of what should be a free cluster.  */
+        status = _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
+
+        /* Check for a good status.  */
+        if (status)
+        {
+
+            /* Set the error code.  */
+            error = error | FX_IO_ERROR;
+
+            /* Return error code.  */
+            return(error);
+        }
+
+        /* Determine if the contents of the cluster is valid.  */
+        if (((next_cluster > (ULONG)FX_FREE_CLUSTER) && (next_cluster < media_ptr -> fx_media_fat_reserved)) ||
+            (next_cluster >= fat_last))
+        {
+
+            /* Lost cluster is present.  */
+
+            /* Set the error code status.  */
+            error =  FX_LOST_CLUSTER_ERROR;
+
+            /* Determine if the lost cluster should be recovered.  */
+            if (error_correction_option & FX_LOST_CLUSTER_ERROR)
+            {
+
+                /* Make the cluster available again.  */
+                status =  _fx_utility_FAT_entry_write(media_ptr, cluster, FX_FREE_CLUSTER);
+
+                /* Check for a good status.  */
+                if (status)
+                {
+
+                    /* Increment the available clusters.  */
+                    media_ptr -> fx_media_available_clusters++;
+
+                    /* Set the error code.  */
+                    error =  error | FX_IO_ERROR;
+
+                    /* Return error code.  */
+                    return(error);
+                }
+            }
+        }
+    }
+
+    /* Return error code.  */
+    return(error);
+}
+
+#ifdef FX_ENABLE_EXFAT
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_media_check_exFAT_lost_cluster_check            PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function examines all clusters in exFAT to see if there are    */
+/*    any unused clusters that are also unavailable.                      */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Pointer to a previously       */
+/*                                            opened media                */
+/*    logical_fat                           Pointer to the logical FAT    */
+/*                                            bit map                     */
+/*    total_clusters                        Total number of clusters      */
+/*    error_correction_option               Option for correcting lost    */
+/*                                            cluster errors              */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    error                                 Error code                    */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_exFAT_bitmap_flush        Flush dirty bitmap clusters   */
+/*    _fx_utility_exFAT_bitmap_cache_update Cache bitmap clusters         */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    _fx_check_media                       Check media function          */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+ULONG  _fx_media_check_exFAT_lost_cluster_check(FX_MEDIA *media_ptr, UCHAR *logical_fat, ULONG total_clusters, ULONG error_correction_option)
+{
+ULONG cluster = FX_FAT_ENTRY_START;
+ULONG cached_bitmap_bytes = media_ptr -> fx_media_exfat_bitmap_cache_size_in_sectors * media_ptr -> fx_media_bytes_per_sector;
+ULONG cached_bitmap_bits = cached_bitmap_bytes << 3;
+ULONG offset = 0;
+UINT status, i;
+
+    /* This parameter has not been supported yet. */
+    FX_PARAMETER_NOT_USED(error_correction_option);
+
+    /* Flush Allocation Bitmap Table first. */
+    status = _fx_utility_exFAT_bitmap_flush(media_ptr);
+    
+    if (FX_SUCCESS != status)
+    {
+        return(status);
+    }
+
+    while (total_clusters)
+    {
+
+        /* Read Allocation Bitmap Table from disk. */
+        status = _fx_utility_exFAT_bitmap_cache_update(media_ptr, cluster);
+
+        if (FX_SUCCESS != status)
+        {
+            return(status);
+        }
+
+        if (total_clusters >= cached_bitmap_bits)
+        {
+            total_clusters -= cached_bitmap_bits;
+
+            /* Compare cached bitmap with logical_fat. */
+            for (i = 0; i < media_ptr -> fx_media_bytes_per_sector; i++)
+            {
+                if (logical_fat[offset + i] != ((UCHAR *)(media_ptr -> fx_media_exfat_bitmap_cache))[i])
+                {
+                    return(FX_LOST_CLUSTER_ERROR);
+                }
+
+                offset += cached_bitmap_bytes;
+                cluster += cached_bitmap_bits;
+            }
+        }
+        else
+        {
+
+            /* Compare cached bitmap with logical_fat. */
+            for (i = 0; i < ((total_clusters + 7) >> 3); i++)
+            {
+                if (logical_fat[offset + i] != ((UCHAR *)(media_ptr -> fx_media_exfat_bitmap_cache))[i])
+                {
+                    return(FX_LOST_CLUSTER_ERROR);
+                }
+            }
+
+            total_clusters = 0;
+        }
+    }
+
+    return(FX_SUCCESS);
+}
+#endif /* FX_ENABLE_EXFAT */
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_close.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_close.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_close.c	(revision 30)
@@ -0,0 +1,447 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_media.h"
+#include "fx_file.h"
+#include "fx_directory.h"
+#include "fx_utility.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_media_close                                     PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function examines the list of open files for this media and    */
+/*    closes each file.  If a file has been written to, the file's        */
+/*    directory information is also written out to the media.  After      */
+/*    the files have been closed, the internal logical sector is          */
+/*    flushed and a flush command is sent to the attached driver.         */
+/*    Finally, this media control block is removed from the list of       */
+/*    opened media control blocks and is marked as closed.                */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_entry_write             Write the directory entry     */
+/*    _fx_media_abort                       Abort the media on error      */
+/*    _fx_utility_exFAT_bitmap_flush        Flush exFAT allocation bitmap */
+/*    _fx_utility_FAT_flush                 Flush cached FAT entries      */
+/*    _fx_utility_FAT_map_flush             Flush primary FAT changes to  */
+/*                                            secondary FAT(s)            */
+/*    _fx_utility_logical_sector_flush      Flush logical sector cache    */
+/*    _fx_utility_16_unsigned_read          Read a 16-bit value           */
+/*    _fx_utility_32_unsigned_read          Read a 32-bit value           */
+/*    _fx_utility_32_unsigned_write         Write a 32-bit value          */
+/*    tx_mutex_delete                       Delete protection mutex       */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s), and      */
+/*                                            added conditional to        */
+/*                                            disable file close          */
+/*                                            and cache,                  */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_media_close(FX_MEDIA  *media_ptr)
+{
+
+FX_INT_SAVE_AREA
+
+#ifndef FX_DISABLE_FILE_CLOSE
+ULONG    open_count;
+FX_FILE *file_ptr;
+#endif /* FX_DISABLE_FILE_CLOSE */
+UINT     status;
+
+
+    /* Check the media to make sure it is open.  */
+    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
+    {
+
+        /* Return the media not opened error.  */
+        return(FX_MEDIA_NOT_OPEN);
+    }
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_MEDIA_CLOSE, media_ptr, 0, 0, 0, FX_TRACE_MEDIA_EVENTS, 0, 0)
+
+    /* If trace is enabled, unregister this object.  */
+    FX_TRACE_OBJECT_UNREGISTER(media_ptr)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+#ifndef FX_DISABLE_FILE_CLOSE
+    /* Loop through the media's open files.  */
+    open_count =  media_ptr -> fx_media_opened_file_count;
+    file_ptr =    media_ptr -> fx_media_opened_file_list;
+    while (open_count)
+    {
+
+        /* Look at each opened file to see if the same file is opened
+           for writing and has been written to.  */
+        if ((file_ptr -> fx_file_open_mode == FX_OPEN_FOR_WRITE) &&
+            (file_ptr -> fx_file_modified))
+        {
+
+            /* Lockout interrupts for time/date access.  */
+            FX_DISABLE_INTS
+
+            /* Set the new time and date.  */
+            file_ptr -> fx_file_dir_entry.fx_dir_entry_time =  _fx_system_time;
+            file_ptr -> fx_file_dir_entry.fx_dir_entry_date =  _fx_system_date;
+
+            /* Restore interrupt posture.  */
+            FX_RESTORE_INTS
+
+            /* Copy the new file size into the directory entry.  */
+            file_ptr -> fx_file_dir_entry.fx_dir_entry_file_size =
+                file_ptr -> fx_file_current_file_size;
+
+            /* Write the directory entry to the media.  */
+#ifdef FX_ENABLE_EXFAT
+            if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+            {
+
+                status = _fx_directory_exFAT_entry_write(media_ptr, &(file_ptr -> fx_file_dir_entry), UPDATE_STREAM);
+            }
+            else
+            {
+#endif /* FX_ENABLE_EXFAT */
+                status = _fx_directory_entry_write(media_ptr, &(file_ptr -> fx_file_dir_entry));
+#ifdef FX_ENABLE_EXFAT
+            }
+#endif /* FX_ENABLE_EXFAT */
+
+            /* Determine if the status was unsuccessful. */
+            if (status != FX_SUCCESS)
+            {
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* Call the media abort routine.  */
+                _fx_media_abort(media_ptr);
+
+                /* Return the error status.  */
+                return(FX_IO_ERROR);
+            }
+
+            /* Clear the file modified flag.  */
+            file_ptr -> fx_file_modified =  FX_FALSE;
+        }
+
+        /* Mark the file as closed.  */
+        file_ptr -> fx_file_id =  FX_FILE_CLOSED_ID;
+
+        /* Adjust the pointer and decrement the opened count.  */
+        file_ptr =  file_ptr -> fx_file_opened_next;
+        open_count--;
+    }
+#endif /* FX_DISABLE_FILE_CLOSE */
+
+    /* Flush the cached individual FAT entries */
+    _fx_utility_FAT_flush(media_ptr);
+
+    /* Flush changed sector(s) in the primary FAT to secondary FATs.  */
+    _fx_utility_FAT_map_flush(media_ptr);
+
+#ifdef FX_ENABLE_EXFAT
+    if ((media_ptr -> fx_media_FAT_type == FX_exFAT) &&
+        (FX_TRUE == media_ptr -> fx_media_exfat_bitmap_cache_dirty))
+    {
+
+        /* Flush bitmap.  */
+        _fx_utility_exFAT_bitmap_flush(media_ptr);
+    }
+#endif /* FX_ENABLE_EXFAT */
+
+    /* Flush the internal logical sector cache.  */
+    status =  _fx_utility_logical_sector_flush(media_ptr, ((ULONG64) 1), (ULONG64) (media_ptr -> fx_media_total_sectors), FX_FALSE);
+
+    /* Determine if the flush was unsuccessful. */
+    if (status != FX_SUCCESS)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Call the media abort routine.  */
+        _fx_media_abort(media_ptr);
+
+        /* Return the error status.  */
+        return(FX_IO_ERROR);
+    }
+
+    /* Determine if the media needs to have the additional information sector updated. This will
+       only be the case for 32-bit FATs. The logic here only needs to be done if the last reported
+       available cluster count is different that the currently available clusters.  */
+    if ((media_ptr -> fx_media_FAT32_additional_info_sector) &&
+        (media_ptr -> fx_media_FAT32_additional_info_last_available != media_ptr -> fx_media_available_clusters) &&
+        (media_ptr -> fx_media_driver_write_protect == FX_FALSE))
+    {
+
+    UCHAR *buffer_ptr;
+    ULONG  signature;
+
+
+#ifndef FX_DISABLE_CACHE
+        /* Setup a pointer to the first cached entry's buffer.  */
+        buffer_ptr =  (media_ptr -> fx_media_sector_cache_list_ptr) -> fx_cached_sector_memory_buffer;
+
+        /* Invalidate this cache entry.  */
+        (media_ptr -> fx_media_sector_cache_list_ptr) -> fx_cached_sector =  (~(ULONG64)0);
+        (media_ptr -> fx_media_sector_cache_list_ptr) -> fx_cached_sector_valid =  FX_FALSE;
+#else
+        buffer_ptr =  media_ptr -> fx_media_memory_buffer;
+#endif /* FX_DISABLE_CACHE */
+
+        /* Read the FAT32 additional information sector from the device.  */
+        media_ptr -> fx_media_driver_request =          FX_DRIVER_READ;
+        media_ptr -> fx_media_driver_status =           FX_IO_ERROR;
+        media_ptr -> fx_media_driver_buffer =           buffer_ptr;
+        media_ptr -> fx_media_driver_logical_sector =   media_ptr -> fx_media_FAT32_additional_info_sector;
+        media_ptr -> fx_media_driver_sectors =          1;
+        media_ptr -> fx_media_driver_sector_type =      FX_DIRECTORY_SECTOR;
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+        /* Increment the number of driver read sector(s) requests.  */
+        media_ptr -> fx_media_driver_read_requests++;
+#endif
+
+        /* If trace is enabled, insert this event into the trace buffer.  */
+        FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_READ, media_ptr, media_ptr -> fx_media_FAT32_additional_info_sector, 1, buffer_ptr, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+        /* Invoke the driver to read the FAT32 additional information sector.  */
+        (media_ptr -> fx_media_driver_entry) (media_ptr);
+
+        /* Determine if the FAT32 sector was read correctly. */
+        if (media_ptr -> fx_media_driver_status != FX_SUCCESS)
+        {
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* Call the media abort routine.  */
+            _fx_media_abort(media_ptr);
+
+            /* Return the error status.  */
+            return(FX_IO_ERROR);
+        }
+
+        /* Setup a pointer into the FAT32 additional information sector.  */
+        buffer_ptr =  media_ptr -> fx_media_driver_buffer;
+
+        /* Pickup the first signature long word.  */
+        signature =  _fx_utility_32_unsigned_read(&buffer_ptr[0]);
+
+        /* Determine if the signature is correct.  */
+        if (signature == 0x41615252)
+        {
+
+            /* Yes, the first signature is correct, now pickup the next signature.  */
+            signature =  _fx_utility_32_unsigned_read(&buffer_ptr[484]);
+
+            /* Determine if this signature is correct.  */
+            if (signature == 0x61417272)
+            {
+
+                /* Yes, we have a good FAT32 additional information sector.  */
+
+                /* Set the free cluster count to the available clusters in the media control block.  */
+                _fx_utility_32_unsigned_write(&buffer_ptr[488], media_ptr -> fx_media_available_clusters);
+
+                /* Set the next free cluster number hint to starting search cluster in the media control block.  */
+                _fx_utility_32_unsigned_write(&buffer_ptr[492], media_ptr -> fx_media_cluster_search_start);
+
+                /* Now write the sector back out to the media.  */
+                media_ptr -> fx_media_driver_request =          FX_DRIVER_WRITE;
+                media_ptr -> fx_media_driver_status =           FX_IO_ERROR;
+                media_ptr -> fx_media_driver_buffer =           buffer_ptr;
+                media_ptr -> fx_media_driver_logical_sector =   media_ptr -> fx_media_FAT32_additional_info_sector;
+                media_ptr -> fx_media_driver_sectors =          1;
+                media_ptr -> fx_media_driver_sector_type =      FX_DIRECTORY_SECTOR;
+
+                /* Set the system write flag since we are writing a directory sector.  */
+                media_ptr -> fx_media_driver_system_write =  FX_TRUE;
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+                /* Increment the number of driver write sector(s) requests.  */
+                media_ptr -> fx_media_driver_write_requests++;
+#endif
+
+                /* If trace is enabled, insert this event into the trace buffer.  */
+                FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_WRITE, media_ptr, media_ptr -> fx_media_FAT32_additional_info_sector, 1, buffer_ptr, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+                /* Invoke the driver to write the FAT32 additional information sector.  */
+                (media_ptr -> fx_media_driver_entry) (media_ptr);
+
+                /* Clear the system write flag.  */
+                media_ptr -> fx_media_driver_system_write =  FX_FALSE;
+
+                /* Determine if the FAT32 sector was written correctly. */
+                if (media_ptr -> fx_media_driver_status != FX_SUCCESS)
+                {
+
+                    /* Release media protection.  */
+                    FX_UNPROTECT
+
+                    /* Call the media abort routine.  */
+                    _fx_media_abort(media_ptr);
+
+                    /* Return the sector IO error status.  */
+                    return(FX_IO_ERROR);
+                }
+
+                /* Successful update of the FAT32 additional information sector. Update the
+                   last written available cluster count.  */
+                media_ptr -> fx_media_FAT32_additional_info_last_available =  media_ptr -> fx_media_available_clusters;
+            }
+        }
+    }
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of driver flush requests.  */
+    media_ptr -> fx_media_driver_flush_requests++;
+#endif
+
+    /* Build the "flush" I/O driver request.  */
+    media_ptr -> fx_media_driver_request =      FX_DRIVER_FLUSH;
+    media_ptr -> fx_media_driver_status =       FX_IO_ERROR;
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_FLUSH, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+    /* Call the specified I/O driver with the flush request.  */
+    (media_ptr -> fx_media_driver_entry) (media_ptr);
+
+    /* Build the "uninitialize" I/O driver request.  */
+    media_ptr -> fx_media_driver_request =      FX_DRIVER_UNINIT;
+    media_ptr -> fx_media_driver_status =       FX_IO_ERROR;
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_UNINIT, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+    /* Call the specified I/O driver with the uninitialize request.  */
+    (media_ptr -> fx_media_driver_entry) (media_ptr);
+
+    /* Now remove this media from the open list.  */
+
+    /* Lockout interrupts for media removal.  */
+    FX_DISABLE_INTS
+
+    /* See if the media is the only one on the media opened list.  */
+    if (_fx_system_media_opened_count == ((ULONG) 1))
+    {
+
+        /* Only opened media, just set the opened list to NULL.  */
+        _fx_system_media_opened_ptr =  FX_NULL;
+    }
+    else
+    {
+
+        /* Otherwise, not the only opened media, link-up the neighbors.  */
+        (media_ptr -> fx_media_opened_next) -> fx_media_opened_previous =
+            media_ptr -> fx_media_opened_previous;
+        (media_ptr -> fx_media_opened_previous) -> fx_media_opened_next =
+            media_ptr -> fx_media_opened_next;
+
+        /* See if we have to update the opened list head pointer.  */
+        if (_fx_system_media_opened_ptr == media_ptr)
+        {
+
+            /* Yes, move the head pointer to the next opened media. */
+            _fx_system_media_opened_ptr =  media_ptr -> fx_media_opened_next;
+        }
+    }
+
+    /* Decrement the opened media counter.  */
+    _fx_system_media_opened_count--;
+
+    /* Finally, Indicate that this media is closed.  */
+    media_ptr -> fx_media_id =  FX_MEDIA_CLOSED_ID;
+
+    /* Restore interrupt posture.  */
+    FX_RESTORE_INTS
+
+    /* Delete the media protection structure if FX_SINGLE_THREAD is not
+       defined.  */
+#ifndef FX_SINGLE_THREAD
+
+#ifndef FX_DONT_CREATE_MUTEX
+
+    /* Note that the protection is never released. The mutex delete
+       service will handle all threads waiting access to this media
+       control block.  */
+    tx_mutex_delete(& (media_ptr -> fx_media_protect));
+#endif
+#endif
+
+    /* Invoke media close callback. */
+    if (media_ptr -> fx_media_close_notify)
+    {
+        media_ptr -> fx_media_close_notify(media_ptr);
+    }
+
+#ifdef FX_DONT_CREATE_MUTEX
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+#endif
+
+    /* Return success status to the caller.  */
+    return(FX_SUCCESS);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_close_notify_set.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_close_notify_set.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_close_notify_set.c	(revision 30)
@@ -0,0 +1,82 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_media.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_media_close_notif_set                           PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function sets the notify function called when media is open.   */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    media_close_notify                    Notify function called when   */
+/*                                            media is closed             */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    FX_SUCCESS                                                          */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_media_close_notify_set(FX_MEDIA *media_ptr, VOID (*media_close_notify)(FX_MEDIA *media))
+{
+
+    /* Set the notify function. */
+    media_ptr -> fx_media_close_notify = media_close_notify;
+
+    /* Return successful status.  */
+    return(FX_SUCCESS);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_exFAT_format.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_exFAT_format.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_exFAT_format.c	(revision 30)
@@ -0,0 +1,1231 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+
+
+#ifdef FX_ENABLE_EXFAT
+#include "fx_system.h"
+#include "fx_media.h"
+#include "fx_utility.h"
+#include "fx_directory_exFAT.h"
+
+
+/* Define upper case table for exFAT formatting.  */
+
+const UCHAR _fx_utility_exFAT_upcase_table_compressed[] =
+{
+    /* Sector 1 */
+
+    0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00,
+    0x08, 0x00, 0x09, 0x00, 0x0a, 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00,
+    0x10, 0x00, 0x11, 0x00, 0x12, 0x00, 0x13, 0x00, 0x14, 0x00, 0x15, 0x00, 0x16, 0x00, 0x17, 0x00,
+    0x18, 0x00, 0x19, 0x00, 0x1a, 0x00, 0x1b, 0x00, 0x1c, 0x00, 0x1d, 0x00, 0x1e, 0x00, 0x1f, 0x00,
+    0x20, 0x00, 0x21, 0x00, 0x22, 0x00, 0x23, 0x00, 0x24, 0x00, 0x25, 0x00, 0x26, 0x00, 0x27, 0x00,
+    0x28, 0x00, 0x29, 0x00, 0x2a, 0x00, 0x2b, 0x00, 0x2c, 0x00, 0x2d, 0x00, 0x2e, 0x00, 0x2f, 0x00,
+    0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00,
+    0x38, 0x00, 0x39, 0x00, 0x3a, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00, 0x3e, 0x00, 0x3f, 0x00,
+    0x40, 0x00, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0x00, 0x45, 0x00, 0x46, 0x00, 0x47, 0x00,
+    0x48, 0x00, 0x49, 0x00, 0x4a, 0x00, 0x4b, 0x00, 0x4c, 0x00, 0x4d, 0x00, 0x4e, 0x00, 0x4f, 0x00,
+    0x50, 0x00, 0x51, 0x00, 0x52, 0x00, 0x53, 0x00, 0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57, 0x00,
+    0x58, 0x00, 0x59, 0x00, 0x5a, 0x00, 0x5b, 0x00, 0x5c, 0x00, 0x5d, 0x00, 0x5e, 0x00, 0x5f, 0x00,
+    0x60, 0x00, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0x00, 0x45, 0x00, 0x46, 0x00, 0x47, 0x00,
+    0x48, 0x00, 0x49, 0x00, 0x4a, 0x00, 0x4b, 0x00, 0x4c, 0x00, 0x4d, 0x00, 0x4e, 0x00, 0x4f, 0x00,
+    0x50, 0x00, 0x51, 0x00, 0x52, 0x00, 0x53, 0x00, 0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57, 0x00,
+    0x58, 0x00, 0x59, 0x00, 0x5a, 0x00, 0x7b, 0x00, 0x7c, 0x00, 0x7d, 0x00, 0x7e, 0x00, 0x7f, 0x00,
+    0x80, 0x00, 0x81, 0x00, 0x82, 0x00, 0x83, 0x00, 0x84, 0x00, 0x85, 0x00, 0x86, 0x00, 0x87, 0x00,
+    0x88, 0x00, 0x89, 0x00, 0x8a, 0x00, 0x8b, 0x00, 0x8c, 0x00, 0x8d, 0x00, 0x8e, 0x00, 0x8f, 0x00,
+    0x90, 0x00, 0x91, 0x00, 0x92, 0x00, 0x93, 0x00, 0x94, 0x00, 0x95, 0x00, 0x96, 0x00, 0x97, 0x00,
+    0x98, 0x00, 0x99, 0x00, 0x9a, 0x00, 0x9b, 0x00, 0x9c, 0x00, 0x9d, 0x00, 0x9e, 0x00, 0x9f, 0x00,
+    0xa0, 0x00, 0xa1, 0x00, 0xa2, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0xa5, 0x00, 0xa6, 0x00, 0xa7, 0x00,
+    0xa8, 0x00, 0xa9, 0x00, 0xaa, 0x00, 0xab, 0x00, 0xac, 0x00, 0xad, 0x00, 0xae, 0x00, 0xaf, 0x00,
+    0xb0, 0x00, 0xb1, 0x00, 0xb2, 0x00, 0xb3, 0x00, 0xb4, 0x00, 0xb5, 0x00, 0xb6, 0x00, 0xb7, 0x00,
+    0xb8, 0x00, 0xb9, 0x00, 0xba, 0x00, 0xbb, 0x00, 0xbc, 0x00, 0xbd, 0x00, 0xbe, 0x00, 0xbf, 0x00,
+    0xc0, 0x00, 0xc1, 0x00, 0xc2, 0x00, 0xc3, 0x00, 0xc4, 0x00, 0xc5, 0x00, 0xc6, 0x00, 0xc7, 0x00,
+    0xc8, 0x00, 0xc9, 0x00, 0xca, 0x00, 0xcb, 0x00, 0xcc, 0x00, 0xcd, 0x00, 0xce, 0x00, 0xcf, 0x00,
+    0xd0, 0x00, 0xd1, 0x00, 0xd2, 0x00, 0xd3, 0x00, 0xd4, 0x00, 0xd5, 0x00, 0xd6, 0x00, 0xd7, 0x00,
+    0xd8, 0x00, 0xd9, 0x00, 0xda, 0x00, 0xdb, 0x00, 0xdc, 0x00, 0xdd, 0x00, 0xde, 0x00, 0xdf, 0x00,
+    0xc0, 0x00, 0xc1, 0x00, 0xc2, 0x00, 0xc3, 0x00, 0xc4, 0x00, 0xc5, 0x00, 0xc6, 0x00, 0xc7, 0x00,
+    0xc8, 0x00, 0xc9, 0x00, 0xca, 0x00, 0xcb, 0x00, 0xcc, 0x00, 0xcd, 0x00, 0xce, 0x00, 0xcf, 0x00,
+    0xd0, 0x00, 0xd1, 0x00, 0xd2, 0x00, 0xd3, 0x00, 0xd4, 0x00, 0xd5, 0x00, 0xd6, 0x00, 0xf7, 0x00,
+    0xd8, 0x00, 0xd9, 0x00, 0xda, 0x00, 0xdb, 0x00, 0xdc, 0x00, 0xdd, 0x00, 0xde, 0x00, 0x78, 0x01,
+
+    /* Sector 2 */
+
+    0x00, 0x01, 0x00, 0x01, 0x02, 0x01, 0x02, 0x01, 0x04, 0x01, 0x04, 0x01, 0x06, 0x01, 0x06, 0x01,
+    0x08, 0x01, 0x08, 0x01, 0x0a, 0x01, 0x0a, 0x01, 0x0c, 0x01, 0x0c, 0x01, 0x0e, 0x01, 0x0e, 0x01,
+    0x10, 0x01, 0x10, 0x01, 0x12, 0x01, 0x12, 0x01, 0x14, 0x01, 0x14, 0x01, 0x16, 0x01, 0x16, 0x01,
+    0x18, 0x01, 0x18, 0x01, 0x1a, 0x01, 0x1a, 0x01, 0x1c, 0x01, 0x1c, 0x01, 0x1e, 0x01, 0x1e, 0x01,
+    0x20, 0x01, 0x20, 0x01, 0x22, 0x01, 0x22, 0x01, 0x24, 0x01, 0x24, 0x01, 0x26, 0x01, 0x26, 0x01,
+    0x28, 0x01, 0x28, 0x01, 0x2a, 0x01, 0x2a, 0x01, 0x2c, 0x01, 0x2c, 0x01, 0x2e, 0x01, 0x2e, 0x01,
+    0x30, 0x01, 0x31, 0x01, 0x32, 0x01, 0x32, 0x01, 0x34, 0x01, 0x34, 0x01, 0x36, 0x01, 0x36, 0x01,
+    0x38, 0x01, 0x39, 0x01, 0x39, 0x01, 0x3b, 0x01, 0x3b, 0x01, 0x3d, 0x01, 0x3d, 0x01, 0x3f, 0x01,
+    0x3f, 0x01, 0x41, 0x01, 0x41, 0x01, 0x43, 0x01, 0x43, 0x01, 0x45, 0x01, 0x45, 0x01, 0x47, 0x01,
+    0x47, 0x01, 0x49, 0x01, 0x4a, 0x01, 0x4a, 0x01, 0x4c, 0x01, 0x4c, 0x01, 0x4e, 0x01, 0x4e, 0x01,
+    0x50, 0x01, 0x50, 0x01, 0x52, 0x01, 0x52, 0x01, 0x54, 0x01, 0x54, 0x01, 0x56, 0x01, 0x56, 0x01,
+    0x58, 0x01, 0x58, 0x01, 0x5a, 0x01, 0x5a, 0x01, 0x5c, 0x01, 0x5c, 0x01, 0x5e, 0x01, 0x5e, 0x01,
+    0x60, 0x01, 0x60, 0x01, 0x62, 0x01, 0x62, 0x01, 0x64, 0x01, 0x64, 0x01, 0x66, 0x01, 0x66, 0x01,
+    0x68, 0x01, 0x68, 0x01, 0x6a, 0x01, 0x6a, 0x01, 0x6c, 0x01, 0x6c, 0x01, 0x6e, 0x01, 0x6e, 0x01,
+    0x70, 0x01, 0x70, 0x01, 0x72, 0x01, 0x72, 0x01, 0x74, 0x01, 0x74, 0x01, 0x76, 0x01, 0x76, 0x01,
+    0x78, 0x01, 0x79, 0x01, 0x79, 0x01, 0x7b, 0x01, 0x7b, 0x01, 0x7d, 0x01, 0x7d, 0x01, 0x7f, 0x01,
+    0x43, 0x02, 0x81, 0x01, 0x82, 0x01, 0x82, 0x01, 0x84, 0x01, 0x84, 0x01, 0x86, 0x01, 0x87, 0x01,
+    0x87, 0x01, 0x89, 0x01, 0x8a, 0x01, 0x8b, 0x01, 0x8b, 0x01, 0x8d, 0x01, 0x8e, 0x01, 0x8f, 0x01,
+    0x90, 0x01, 0x91, 0x01, 0x91, 0x01, 0x93, 0x01, 0x94, 0x01, 0xf6, 0x01, 0x96, 0x01, 0x97, 0x01,
+    0x98, 0x01, 0x98, 0x01, 0x3d, 0x02, 0x9b, 0x01, 0x9c, 0x01, 0x9d, 0x01, 0x20, 0x02, 0x9f, 0x01,
+    0xa0, 0x01, 0xa0, 0x01, 0xa2, 0x01, 0xa2, 0x01, 0xa4, 0x01, 0xa4, 0x01, 0xa6, 0x01, 0xa7, 0x01,
+    0xa7, 0x01, 0xa9, 0x01, 0xaa, 0x01, 0xab, 0x01, 0xac, 0x01, 0xac, 0x01, 0xae, 0x01, 0xaf, 0x01,
+    0xaf, 0x01, 0xb1, 0x01, 0xb2, 0x01, 0xb3, 0x01, 0xb3, 0x01, 0xb5, 0x01, 0xb5, 0x01, 0xb7, 0x01,
+    0xb8, 0x01, 0xb8, 0x01, 0xba, 0x01, 0xbb, 0x01, 0xbc, 0x01, 0xbc, 0x01, 0xbe, 0x01, 0xf7, 0x01,
+    0xc0, 0x01, 0xc1, 0x01, 0xc2, 0x01, 0xc3, 0x01, 0xc4, 0x01, 0xc5, 0x01, 0xc4, 0x01, 0xc7, 0x01,
+    0xc8, 0x01, 0xc7, 0x01, 0xca, 0x01, 0xcb, 0x01, 0xca, 0x01, 0xcd, 0x01, 0xcd, 0x01, 0xcf, 0x01,
+    0xcf, 0x01, 0xd1, 0x01, 0xd1, 0x01, 0xd3, 0x01, 0xd3, 0x01, 0xd5, 0x01, 0xd5, 0x01, 0xd7, 0x01,
+    0xd7, 0x01, 0xd9, 0x01, 0xd9, 0x01, 0xdb, 0x01, 0xdb, 0x01, 0x8e, 0x01, 0xde, 0x01, 0xde, 0x01,
+    0xe0, 0x01, 0xe0, 0x01, 0xe2, 0x01, 0xe2, 0x01, 0xe4, 0x01, 0xe4, 0x01, 0xe6, 0x01, 0xe6, 0x01,
+    0xe8, 0x01, 0xe8, 0x01, 0xea, 0x01, 0xea, 0x01, 0xec, 0x01, 0xec, 0x01, 0xee, 0x01, 0xee, 0x01,
+    0xf0, 0x01, 0xf1, 0x01, 0xf2, 0x01, 0xf1, 0x01, 0xf4, 0x01, 0xf4, 0x01, 0xf6, 0x01, 0xf7, 0x01,
+    0xf8, 0x01, 0xf8, 0x01, 0xfa, 0x01, 0xfa, 0x01, 0xfc, 0x01, 0xfc, 0x01, 0xfe, 0x01, 0xfe, 0x01,
+
+    /* Sector 3 */
+
+    0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x04, 0x02, 0x04, 0x02, 0x06, 0x02, 0x06, 0x02,
+    0x08, 0x02, 0x08, 0x02, 0x0a, 0x02, 0x0a, 0x02, 0x0c, 0x02, 0x0c, 0x02, 0x0e, 0x02, 0x0e, 0x02,
+    0x10, 0x02, 0x10, 0x02, 0x12, 0x02, 0x12, 0x02, 0x14, 0x02, 0x14, 0x02, 0x16, 0x02, 0x16, 0x02,
+    0x18, 0x02, 0x18, 0x02, 0x1a, 0x02, 0x1a, 0x02, 0x1c, 0x02, 0x1c, 0x02, 0x1e, 0x02, 0x1e, 0x02,
+    0x20, 0x02, 0x21, 0x02, 0x22, 0x02, 0x22, 0x02, 0x24, 0x02, 0x24, 0x02, 0x26, 0x02, 0x26, 0x02,
+    0x28, 0x02, 0x28, 0x02, 0x2a, 0x02, 0x2a, 0x02, 0x2c, 0x02, 0x2c, 0x02, 0x2e, 0x02, 0x2e, 0x02,
+    0x30, 0x02, 0x30, 0x02, 0x32, 0x02, 0x32, 0x02, 0x34, 0x02, 0x35, 0x02, 0x36, 0x02, 0x37, 0x02,
+    0x38, 0x02, 0x39, 0x02, 0x65, 0x2c, 0x3b, 0x02, 0x3b, 0x02, 0x3d, 0x02, 0x66, 0x2c, 0x3f, 0x02,
+    0x40, 0x02, 0x41, 0x02, 0x41, 0x02, 0x43, 0x02, 0x44, 0x02, 0x45, 0x02, 0x46, 0x02, 0x46, 0x02,
+    0x48, 0x02, 0x48, 0x02, 0x4a, 0x02, 0x4a, 0x02, 0x4c, 0x02, 0x4c, 0x02, 0x4e, 0x02, 0x4e, 0x02,
+    0x50, 0x02, 0x51, 0x02, 0x52, 0x02, 0x81, 0x01, 0x86, 0x01, 0x55, 0x02, 0x89, 0x01, 0x8a, 0x01,
+    0x58, 0x02, 0x8f, 0x01, 0x5a, 0x02, 0x90, 0x01, 0x5c, 0x02, 0x5d, 0x02, 0x5e, 0x02, 0x5f, 0x02,
+    0x93, 0x01, 0x61, 0x02, 0x62, 0x02, 0x94, 0x01, 0x64, 0x02, 0x65, 0x02, 0x66, 0x02, 0x67, 0x02,
+    0x97, 0x01, 0x96, 0x01, 0x6a, 0x02, 0x62, 0x2c, 0x6c, 0x02, 0x6d, 0x02, 0x6e, 0x02, 0x9c, 0x01,
+    0x70, 0x02, 0x71, 0x02, 0x9d, 0x01, 0x73, 0x02, 0x74, 0x02, 0x9f, 0x01, 0x76, 0x02, 0x77, 0x02,
+    0x78, 0x02, 0x79, 0x02, 0x7a, 0x02, 0x7b, 0x02, 0x7c, 0x02, 0x64, 0x2c, 0x7e, 0x02, 0x7f, 0x02,
+    0xa6, 0x01, 0x81, 0x02, 0x82, 0x02, 0xa9, 0x01, 0x84, 0x02, 0x85, 0x02, 0x86, 0x02, 0x87, 0x02,
+    0xae, 0x01, 0x44, 0x02, 0xb1, 0x01, 0xb2, 0x01, 0x45, 0x02, 0x8d, 0x02, 0x8e, 0x02, 0x8f, 0x02,
+    0x90, 0x02, 0x91, 0x02, 0xb7, 0x01, 0x93, 0x02, 0x94, 0x02, 0x95, 0x02, 0x96, 0x02, 0x97, 0x02,
+    0x98, 0x02, 0x99, 0x02, 0x9a, 0x02, 0x9b, 0x02, 0x9c, 0x02, 0x9d, 0x02, 0x9e, 0x02, 0x9f, 0x02,
+    0xa0, 0x02, 0xa1, 0x02, 0xa2, 0x02, 0xa3, 0x02, 0xa4, 0x02, 0xa5, 0x02, 0xa6, 0x02, 0xa7, 0x02,
+    0xa8, 0x02, 0xa9, 0x02, 0xaa, 0x02, 0xab, 0x02, 0xac, 0x02, 0xad, 0x02, 0xae, 0x02, 0xaf, 0x02,
+    0xb0, 0x02, 0xb1, 0x02, 0xb2, 0x02, 0xb3, 0x02, 0xb4, 0x02, 0xb5, 0x02, 0xb6, 0x02, 0xb7, 0x02,
+    0xb8, 0x02, 0xb9, 0x02, 0xba, 0x02, 0xbb, 0x02, 0xbc, 0x02, 0xbd, 0x02, 0xbe, 0x02, 0xbf, 0x02,
+    0xc0, 0x02, 0xc1, 0x02, 0xc2, 0x02, 0xc3, 0x02, 0xc4, 0x02, 0xc5, 0x02, 0xc6, 0x02, 0xc7, 0x02,
+    0xc8, 0x02, 0xc9, 0x02, 0xca, 0x02, 0xcb, 0x02, 0xcc, 0x02, 0xcd, 0x02, 0xce, 0x02, 0xcf, 0x02,
+    0xd0, 0x02, 0xd1, 0x02, 0xd2, 0x02, 0xd3, 0x02, 0xd4, 0x02, 0xd5, 0x02, 0xd6, 0x02, 0xd7, 0x02,
+    0xd8, 0x02, 0xd9, 0x02, 0xda, 0x02, 0xdb, 0x02, 0xdc, 0x02, 0xdd, 0x02, 0xde, 0x02, 0xdf, 0x02,
+    0xe0, 0x02, 0xe1, 0x02, 0xe2, 0x02, 0xe3, 0x02, 0xe4, 0x02, 0xe5, 0x02, 0xe6, 0x02, 0xe7, 0x02,
+    0xe8, 0x02, 0xe9, 0x02, 0xea, 0x02, 0xeb, 0x02, 0xec, 0x02, 0xed, 0x02, 0xee, 0x02, 0xef, 0x02,
+    0xf0, 0x02, 0xf1, 0x02, 0xf2, 0x02, 0xf3, 0x02, 0xf4, 0x02, 0xf5, 0x02, 0xf6, 0x02, 0xf7, 0x02,
+    0xf8, 0x02, 0xf9, 0x02, 0xfa, 0x02, 0xfb, 0x02, 0xfc, 0x02, 0xfd, 0x02, 0xfe, 0x02, 0xff, 0x02,
+
+    /* Sector 4 */
+
+    0x00, 0x03, 0x01, 0x03, 0x02, 0x03, 0x03, 0x03, 0x04, 0x03, 0x05, 0x03, 0x06, 0x03, 0x07, 0x03,
+    0x08, 0x03, 0x09, 0x03, 0x0a, 0x03, 0x0b, 0x03, 0x0c, 0x03, 0x0d, 0x03, 0x0e, 0x03, 0x0f, 0x03,
+    0x10, 0x03, 0x11, 0x03, 0x12, 0x03, 0x13, 0x03, 0x14, 0x03, 0x15, 0x03, 0x16, 0x03, 0x17, 0x03,
+    0x18, 0x03, 0x19, 0x03, 0x1a, 0x03, 0x1b, 0x03, 0x1c, 0x03, 0x1d, 0x03, 0x1e, 0x03, 0x1f, 0x03,
+    0x20, 0x03, 0x21, 0x03, 0x22, 0x03, 0x23, 0x03, 0x24, 0x03, 0x25, 0x03, 0x26, 0x03, 0x27, 0x03,
+    0x28, 0x03, 0x29, 0x03, 0x2a, 0x03, 0x2b, 0x03, 0x2c, 0x03, 0x2d, 0x03, 0x2e, 0x03, 0x2f, 0x03,
+    0x30, 0x03, 0x31, 0x03, 0x32, 0x03, 0x33, 0x03, 0x34, 0x03, 0x35, 0x03, 0x36, 0x03, 0x37, 0x03,
+    0x38, 0x03, 0x39, 0x03, 0x3a, 0x03, 0x3b, 0x03, 0x3c, 0x03, 0x3d, 0x03, 0x3e, 0x03, 0x3f, 0x03,
+    0x40, 0x03, 0x41, 0x03, 0x42, 0x03, 0x43, 0x03, 0x44, 0x03, 0x45, 0x03, 0x46, 0x03, 0x47, 0x03,
+    0x48, 0x03, 0x49, 0x03, 0x4a, 0x03, 0x4b, 0x03, 0x4c, 0x03, 0x4d, 0x03, 0x4e, 0x03, 0x4f, 0x03,
+    0x50, 0x03, 0x51, 0x03, 0x52, 0x03, 0x53, 0x03, 0x54, 0x03, 0x55, 0x03, 0x56, 0x03, 0x57, 0x03,
+    0x58, 0x03, 0x59, 0x03, 0x5a, 0x03, 0x5b, 0x03, 0x5c, 0x03, 0x5d, 0x03, 0x5e, 0x03, 0x5f, 0x03,
+    0x60, 0x03, 0x61, 0x03, 0x62, 0x03, 0x63, 0x03, 0x64, 0x03, 0x65, 0x03, 0x66, 0x03, 0x67, 0x03,
+    0x68, 0x03, 0x69, 0x03, 0x6a, 0x03, 0x6b, 0x03, 0x6c, 0x03, 0x6d, 0x03, 0x6e, 0x03, 0x6f, 0x03,
+    0x70, 0x03, 0x71, 0x03, 0x72, 0x03, 0x73, 0x03, 0x74, 0x03, 0x75, 0x03, 0x76, 0x03, 0x77, 0x03,
+    0x78, 0x03, 0x79, 0x03, 0x7a, 0x03, 0xfd, 0x03, 0xfe, 0x03, 0xff, 0x03, 0x7e, 0x03, 0x7f, 0x03,
+    0x80, 0x03, 0x81, 0x03, 0x82, 0x03, 0x83, 0x03, 0x84, 0x03, 0x85, 0x03, 0x86, 0x03, 0x87, 0x03,
+    0x88, 0x03, 0x89, 0x03, 0x8a, 0x03, 0x8b, 0x03, 0x8c, 0x03, 0x8d, 0x03, 0x8e, 0x03, 0x8f, 0x03,
+    0x90, 0x03, 0x91, 0x03, 0x92, 0x03, 0x93, 0x03, 0x94, 0x03, 0x95, 0x03, 0x96, 0x03, 0x97, 0x03,
+    0x98, 0x03, 0x99, 0x03, 0x9a, 0x03, 0x9b, 0x03, 0x9c, 0x03, 0x9d, 0x03, 0x9e, 0x03, 0x9f, 0x03,
+    0xa0, 0x03, 0xa1, 0x03, 0xa2, 0x03, 0xa3, 0x03, 0xa4, 0x03, 0xa5, 0x03, 0xa6, 0x03, 0xa7, 0x03,
+    0xa8, 0x03, 0xa9, 0x03, 0xaa, 0x03, 0xab, 0x03, 0x86, 0x03, 0x88, 0x03, 0x89, 0x03, 0x8a, 0x03,
+    0xb0, 0x03, 0x91, 0x03, 0x92, 0x03, 0x93, 0x03, 0x94, 0x03, 0x95, 0x03, 0x96, 0x03, 0x97, 0x03,
+    0x98, 0x03, 0x99, 0x03, 0x9a, 0x03, 0x9b, 0x03, 0x9c, 0x03, 0x9d, 0x03, 0x9e, 0x03, 0x9f, 0x03,
+    0xa0, 0x03, 0xa1, 0x03, 0xa3, 0x03, 0xa3, 0x03, 0xa4, 0x03, 0xa5, 0x03, 0xa6, 0x03, 0xa7, 0x03,
+    0xa8, 0x03, 0xa9, 0x03, 0xaa, 0x03, 0xab, 0x03, 0x8c, 0x03, 0x8e, 0x03, 0x8f, 0x03, 0xcf, 0x03,
+    0xd0, 0x03, 0xd1, 0x03, 0xd2, 0x03, 0xd3, 0x03, 0xd4, 0x03, 0xd5, 0x03, 0xd6, 0x03, 0xd7, 0x03,
+    0xd8, 0x03, 0xd8, 0x03, 0xda, 0x03, 0xda, 0x03, 0xdc, 0x03, 0xdc, 0x03, 0xde, 0x03, 0xde, 0x03,
+    0xe0, 0x03, 0xe0, 0x03, 0xe2, 0x03, 0xe2, 0x03, 0xe4, 0x03, 0xe4, 0x03, 0xe6, 0x03, 0xe6, 0x03,
+    0xe8, 0x03, 0xe8, 0x03, 0xea, 0x03, 0xea, 0x03, 0xec, 0x03, 0xec, 0x03, 0xee, 0x03, 0xee, 0x03,
+    0xf0, 0x03, 0xf1, 0x03, 0xf9, 0x03, 0xf3, 0x03, 0xf4, 0x03, 0xf5, 0x03, 0xf6, 0x03, 0xf7, 0x03,
+    0xf7, 0x03, 0xf9, 0x03, 0xfa, 0x03, 0xfa, 0x03, 0xfc, 0x03, 0xfd, 0x03, 0xfe, 0x03, 0xff, 0x03,
+
+    /* Sector 5 */
+
+    0x00, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x04, 0x04, 0x04, 0x05, 0x04, 0x06, 0x04, 0x07, 0x04,
+    0x08, 0x04, 0x09, 0x04, 0x0a, 0x04, 0x0b, 0x04, 0x0c, 0x04, 0x0d, 0x04, 0x0e, 0x04, 0x0f, 0x04,
+    0x10, 0x04, 0x11, 0x04, 0x12, 0x04, 0x13, 0x04, 0x14, 0x04, 0x15, 0x04, 0x16, 0x04, 0x17, 0x04,
+    0x18, 0x04, 0x19, 0x04, 0x1a, 0x04, 0x1b, 0x04, 0x1c, 0x04, 0x1d, 0x04, 0x1e, 0x04, 0x1f, 0x04,
+    0x20, 0x04, 0x21, 0x04, 0x22, 0x04, 0x23, 0x04, 0x24, 0x04, 0x25, 0x04, 0x26, 0x04, 0x27, 0x04,
+    0x28, 0x04, 0x29, 0x04, 0x2a, 0x04, 0x2b, 0x04, 0x2c, 0x04, 0x2d, 0x04, 0x2e, 0x04, 0x2f, 0x04,
+    0x10, 0x04, 0x11, 0x04, 0x12, 0x04, 0x13, 0x04, 0x14, 0x04, 0x15, 0x04, 0x16, 0x04, 0x17, 0x04,
+    0x18, 0x04, 0x19, 0x04, 0x1a, 0x04, 0x1b, 0x04, 0x1c, 0x04, 0x1d, 0x04, 0x1e, 0x04, 0x1f, 0x04,
+    0x20, 0x04, 0x21, 0x04, 0x22, 0x04, 0x23, 0x04, 0x24, 0x04, 0x25, 0x04, 0x26, 0x04, 0x27, 0x04,
+    0x28, 0x04, 0x29, 0x04, 0x2a, 0x04, 0x2b, 0x04, 0x2c, 0x04, 0x2d, 0x04, 0x2e, 0x04, 0x2f, 0x04,
+    0x00, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x04, 0x04, 0x04, 0x05, 0x04, 0x06, 0x04, 0x07, 0x04,
+    0x08, 0x04, 0x09, 0x04, 0x0a, 0x04, 0x0b, 0x04, 0x0c, 0x04, 0x0d, 0x04, 0x0e, 0x04, 0x0f, 0x04,
+    0x60, 0x04, 0x60, 0x04, 0x62, 0x04, 0x62, 0x04, 0x64, 0x04, 0x64, 0x04, 0x66, 0x04, 0x66, 0x04,
+    0x68, 0x04, 0x68, 0x04, 0x6a, 0x04, 0x6a, 0x04, 0x6c, 0x04, 0x6c, 0x04, 0x6e, 0x04, 0x6e, 0x04,
+    0x70, 0x04, 0x70, 0x04, 0x72, 0x04, 0x72, 0x04, 0x74, 0x04, 0x74, 0x04, 0x76, 0x04, 0x76, 0x04,
+    0x78, 0x04, 0x78, 0x04, 0x7a, 0x04, 0x7a, 0x04, 0x7c, 0x04, 0x7c, 0x04, 0x7e, 0x04, 0x7e, 0x04,
+    0x80, 0x04, 0x80, 0x04, 0x82, 0x04, 0x83, 0x04, 0x84, 0x04, 0x85, 0x04, 0x86, 0x04, 0x87, 0x04,
+    0x88, 0x04, 0x89, 0x04, 0x8a, 0x04, 0x8a, 0x04, 0x8c, 0x04, 0x8c, 0x04, 0x8e, 0x04, 0x8e, 0x04,
+    0x90, 0x04, 0x90, 0x04, 0x92, 0x04, 0x92, 0x04, 0x94, 0x04, 0x94, 0x04, 0x96, 0x04, 0x96, 0x04,
+    0x98, 0x04, 0x98, 0x04, 0x9a, 0x04, 0x9a, 0x04, 0x9c, 0x04, 0x9c, 0x04, 0x9e, 0x04, 0x9e, 0x04,
+    0xa0, 0x04, 0xa0, 0x04, 0xa2, 0x04, 0xa2, 0x04, 0xa4, 0x04, 0xa4, 0x04, 0xa6, 0x04, 0xa6, 0x04,
+    0xa8, 0x04, 0xa8, 0x04, 0xaa, 0x04, 0xaa, 0x04, 0xac, 0x04, 0xac, 0x04, 0xae, 0x04, 0xae, 0x04,
+    0xb0, 0x04, 0xb0, 0x04, 0xb2, 0x04, 0xb2, 0x04, 0xb4, 0x04, 0xb4, 0x04, 0xb6, 0x04, 0xb6, 0x04,
+    0xb8, 0x04, 0xb8, 0x04, 0xba, 0x04, 0xba, 0x04, 0xbc, 0x04, 0xbc, 0x04, 0xbe, 0x04, 0xbe, 0x04,
+    0xc0, 0x04, 0xc1, 0x04, 0xc1, 0x04, 0xc3, 0x04, 0xc3, 0x04, 0xc5, 0x04, 0xc5, 0x04, 0xc7, 0x04,
+    0xc7, 0x04, 0xc9, 0x04, 0xc9, 0x04, 0xcb, 0x04, 0xcb, 0x04, 0xcd, 0x04, 0xcd, 0x04, 0xc0, 0x04,
+    0xd0, 0x04, 0xd0, 0x04, 0xd2, 0x04, 0xd2, 0x04, 0xd4, 0x04, 0xd4, 0x04, 0xd6, 0x04, 0xd6, 0x04,
+    0xd8, 0x04, 0xd8, 0x04, 0xda, 0x04, 0xda, 0x04, 0xdc, 0x04, 0xdc, 0x04, 0xde, 0x04, 0xde, 0x04,
+    0xe0, 0x04, 0xe0, 0x04, 0xe2, 0x04, 0xe2, 0x04, 0xe4, 0x04, 0xe4, 0x04, 0xe6, 0x04, 0xe6, 0x04,
+    0xe8, 0x04, 0xe8, 0x04, 0xea, 0x04, 0xea, 0x04, 0xec, 0x04, 0xec, 0x04, 0xee, 0x04, 0xee, 0x04,
+    0xf0, 0x04, 0xf0, 0x04, 0xf2, 0x04, 0xf2, 0x04, 0xf4, 0x04, 0xf4, 0x04, 0xf6, 0x04, 0xf6, 0x04,
+    0xf8, 0x04, 0xf8, 0x04, 0xfa, 0x04, 0xfa, 0x04, 0xfc, 0x04, 0xfc, 0x04, 0xfe, 0x04, 0xfe, 0x04,
+
+    /* Sector 6 */
+
+    0x00, 0x05, 0x00, 0x05, 0x02, 0x05, 0x02, 0x05, 0x04, 0x05, 0x04, 0x05, 0x06, 0x05, 0x06, 0x05,
+    0x08, 0x05, 0x08, 0x05, 0x0a, 0x05, 0x0a, 0x05, 0x0c, 0x05, 0x0c, 0x05, 0x0e, 0x05, 0x0e, 0x05,
+    0x10, 0x05, 0x10, 0x05, 0x12, 0x05, 0x12, 0x05, 0x14, 0x05, 0x15, 0x05, 0x16, 0x05, 0x17, 0x05,
+    0x18, 0x05, 0x19, 0x05, 0x1a, 0x05, 0x1b, 0x05, 0x1c, 0x05, 0x1d, 0x05, 0x1e, 0x05, 0x1f, 0x05,
+    0x20, 0x05, 0x21, 0x05, 0x22, 0x05, 0x23, 0x05, 0x24, 0x05, 0x25, 0x05, 0x26, 0x05, 0x27, 0x05,
+    0x28, 0x05, 0x29, 0x05, 0x2a, 0x05, 0x2b, 0x05, 0x2c, 0x05, 0x2d, 0x05, 0x2e, 0x05, 0x2f, 0x05,
+    0x30, 0x05, 0x31, 0x05, 0x32, 0x05, 0x33, 0x05, 0x34, 0x05, 0x35, 0x05, 0x36, 0x05, 0x37, 0x05,
+    0x38, 0x05, 0x39, 0x05, 0x3a, 0x05, 0x3b, 0x05, 0x3c, 0x05, 0x3d, 0x05, 0x3e, 0x05, 0x3f, 0x05,
+    0x40, 0x05, 0x41, 0x05, 0x42, 0x05, 0x43, 0x05, 0x44, 0x05, 0x45, 0x05, 0x46, 0x05, 0x47, 0x05,
+    0x48, 0x05, 0x49, 0x05, 0x4a, 0x05, 0x4b, 0x05, 0x4c, 0x05, 0x4d, 0x05, 0x4e, 0x05, 0x4f, 0x05,
+    0x50, 0x05, 0x51, 0x05, 0x52, 0x05, 0x53, 0x05, 0x54, 0x05, 0x55, 0x05, 0x56, 0x05, 0x57, 0x05,
+    0x58, 0x05, 0x59, 0x05, 0x5a, 0x05, 0x5b, 0x05, 0x5c, 0x05, 0x5d, 0x05, 0x5e, 0x05, 0x5f, 0x05,
+    0x60, 0x05, 0x31, 0x05, 0x32, 0x05, 0x33, 0x05, 0x34, 0x05, 0x35, 0x05, 0x36, 0x05, 0x37, 0x05,
+    0x38, 0x05, 0x39, 0x05, 0x3a, 0x05, 0x3b, 0x05, 0x3c, 0x05, 0x3d, 0x05, 0x3e, 0x05, 0x3f, 0x05,
+    0x40, 0x05, 0x41, 0x05, 0x42, 0x05, 0x43, 0x05, 0x44, 0x05, 0x45, 0x05, 0x46, 0x05, 0x47, 0x05,
+    0x48, 0x05, 0x49, 0x05, 0x4a, 0x05, 0x4b, 0x05, 0x4c, 0x05, 0x4d, 0x05, 0x4e, 0x05, 0x4f, 0x05,
+    0x50, 0x05, 0x51, 0x05, 0x52, 0x05, 0x53, 0x05, 0x54, 0x05, 0x55, 0x05, 0x56, 0x05, 0xff, 0xff,
+    0xf6, 0x17, 0x63, 0x2c, 0x7e, 0x1d, 0x7f, 0x1d, 0x80, 0x1d, 0x81, 0x1d, 0x82, 0x1d, 0x83, 0x1d,
+    0x84, 0x1d, 0x85, 0x1d, 0x86, 0x1d, 0x87, 0x1d, 0x88, 0x1d, 0x89, 0x1d, 0x8a, 0x1d, 0x8b, 0x1d,
+    0x8c, 0x1d, 0x8d, 0x1d, 0x8e, 0x1d, 0x8f, 0x1d, 0x90, 0x1d, 0x91, 0x1d, 0x92, 0x1d, 0x93, 0x1d,
+    0x94, 0x1d, 0x95, 0x1d, 0x96, 0x1d, 0x97, 0x1d, 0x98, 0x1d, 0x99, 0x1d, 0x9a, 0x1d, 0x9b, 0x1d,
+    0x9c, 0x1d, 0x9d, 0x1d, 0x9e, 0x1d, 0x9f, 0x1d, 0xa0, 0x1d, 0xa1, 0x1d, 0xa2, 0x1d, 0xa3, 0x1d,
+    0xa4, 0x1d, 0xa5, 0x1d, 0xa6, 0x1d, 0xa7, 0x1d, 0xa8, 0x1d, 0xa9, 0x1d, 0xaa, 0x1d, 0xab, 0x1d,
+    0xac, 0x1d, 0xad, 0x1d, 0xae, 0x1d, 0xaf, 0x1d, 0xb0, 0x1d, 0xb1, 0x1d, 0xb2, 0x1d, 0xb3, 0x1d,
+    0xb4, 0x1d, 0xb5, 0x1d, 0xb6, 0x1d, 0xb7, 0x1d, 0xb8, 0x1d, 0xb9, 0x1d, 0xba, 0x1d, 0xbb, 0x1d,
+    0xbc, 0x1d, 0xbd, 0x1d, 0xbe, 0x1d, 0xbf, 0x1d, 0xc0, 0x1d, 0xc1, 0x1d, 0xc2, 0x1d, 0xc3, 0x1d,
+    0xc4, 0x1d, 0xc5, 0x1d, 0xc6, 0x1d, 0xc7, 0x1d, 0xc8, 0x1d, 0xc9, 0x1d, 0xca, 0x1d, 0xcb, 0x1d,
+    0xcc, 0x1d, 0xcd, 0x1d, 0xce, 0x1d, 0xcf, 0x1d, 0xd0, 0x1d, 0xd1, 0x1d, 0xd2, 0x1d, 0xd3, 0x1d,
+    0xd4, 0x1d, 0xd5, 0x1d, 0xd6, 0x1d, 0xd7, 0x1d, 0xd8, 0x1d, 0xd9, 0x1d, 0xda, 0x1d, 0xdb, 0x1d,
+    0xdc, 0x1d, 0xdd, 0x1d, 0xde, 0x1d, 0xdf, 0x1d, 0xe0, 0x1d, 0xe1, 0x1d, 0xe2, 0x1d, 0xe3, 0x1d,
+    0xe4, 0x1d, 0xe5, 0x1d, 0xe6, 0x1d, 0xe7, 0x1d, 0xe8, 0x1d, 0xe9, 0x1d, 0xea, 0x1d, 0xeb, 0x1d,
+    0xec, 0x1d, 0xed, 0x1d, 0xee, 0x1d, 0xef, 0x1d, 0xf0, 0x1d, 0xf1, 0x1d, 0xf2, 0x1d, 0xf3, 0x1d,
+
+    /* Sector 7 */
+
+    0xf4, 0x1d, 0xf5, 0x1d, 0xf6, 0x1d, 0xf7, 0x1d, 0xf8, 0x1d, 0xf9, 0x1d, 0xfa, 0x1d, 0xfb, 0x1d,
+    0xfc, 0x1d, 0xfd, 0x1d, 0xfe, 0x1d, 0xff, 0x1d, 0x00, 0x1e, 0x00, 0x1e, 0x02, 0x1e, 0x02, 0x1e,
+    0x04, 0x1e, 0x04, 0x1e, 0x06, 0x1e, 0x06, 0x1e, 0x08, 0x1e, 0x08, 0x1e, 0x0a, 0x1e, 0x0a, 0x1e,
+    0x0c, 0x1e, 0x0c, 0x1e, 0x0e, 0x1e, 0x0e, 0x1e, 0x10, 0x1e, 0x10, 0x1e, 0x12, 0x1e, 0x12, 0x1e,
+    0x14, 0x1e, 0x14, 0x1e, 0x16, 0x1e, 0x16, 0x1e, 0x18, 0x1e, 0x18, 0x1e, 0x1a, 0x1e, 0x1a, 0x1e,
+    0x1c, 0x1e, 0x1c, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x20, 0x1e, 0x20, 0x1e, 0x22, 0x1e, 0x22, 0x1e,
+    0x24, 0x1e, 0x24, 0x1e, 0x26, 0x1e, 0x26, 0x1e, 0x28, 0x1e, 0x28, 0x1e, 0x2a, 0x1e, 0x2a, 0x1e,
+    0x2c, 0x1e, 0x2c, 0x1e, 0x2e, 0x1e, 0x2e, 0x1e, 0x30, 0x1e, 0x30, 0x1e, 0x32, 0x1e, 0x32, 0x1e,
+    0x34, 0x1e, 0x34, 0x1e, 0x36, 0x1e, 0x36, 0x1e, 0x38, 0x1e, 0x38, 0x1e, 0x3a, 0x1e, 0x3a, 0x1e,
+    0x3c, 0x1e, 0x3c, 0x1e, 0x3e, 0x1e, 0x3e, 0x1e, 0x40, 0x1e, 0x40, 0x1e, 0x42, 0x1e, 0x42, 0x1e,
+    0x44, 0x1e, 0x44, 0x1e, 0x46, 0x1e, 0x46, 0x1e, 0x48, 0x1e, 0x48, 0x1e, 0x4a, 0x1e, 0x4a, 0x1e,
+    0x4c, 0x1e, 0x4c, 0x1e, 0x4e, 0x1e, 0x4e, 0x1e, 0x50, 0x1e, 0x50, 0x1e, 0x52, 0x1e, 0x52, 0x1e,
+    0x54, 0x1e, 0x54, 0x1e, 0x56, 0x1e, 0x56, 0x1e, 0x58, 0x1e, 0x58, 0x1e, 0x5a, 0x1e, 0x5a, 0x1e,
+    0x5c, 0x1e, 0x5c, 0x1e, 0x5e, 0x1e, 0x5e, 0x1e, 0x60, 0x1e, 0x60, 0x1e, 0x62, 0x1e, 0x62, 0x1e,
+    0x64, 0x1e, 0x64, 0x1e, 0x66, 0x1e, 0x66, 0x1e, 0x68, 0x1e, 0x68, 0x1e, 0x6a, 0x1e, 0x6a, 0x1e,
+    0x6c, 0x1e, 0x6c, 0x1e, 0x6e, 0x1e, 0x6e, 0x1e, 0x70, 0x1e, 0x70, 0x1e, 0x72, 0x1e, 0x72, 0x1e,
+    0x74, 0x1e, 0x74, 0x1e, 0x76, 0x1e, 0x76, 0x1e, 0x78, 0x1e, 0x78, 0x1e, 0x7a, 0x1e, 0x7a, 0x1e,
+    0x7c, 0x1e, 0x7c, 0x1e, 0x7e, 0x1e, 0x7e, 0x1e, 0x80, 0x1e, 0x80, 0x1e, 0x82, 0x1e, 0x82, 0x1e,
+    0x84, 0x1e, 0x84, 0x1e, 0x86, 0x1e, 0x86, 0x1e, 0x88, 0x1e, 0x88, 0x1e, 0x8a, 0x1e, 0x8a, 0x1e,
+    0x8c, 0x1e, 0x8c, 0x1e, 0x8e, 0x1e, 0x8e, 0x1e, 0x90, 0x1e, 0x90, 0x1e, 0x92, 0x1e, 0x92, 0x1e,
+    0x94, 0x1e, 0x94, 0x1e, 0x96, 0x1e, 0x97, 0x1e, 0x98, 0x1e, 0x99, 0x1e, 0x9a, 0x1e, 0x9b, 0x1e,
+    0x9c, 0x1e, 0x9d, 0x1e, 0x9e, 0x1e, 0x9f, 0x1e, 0xa0, 0x1e, 0xa0, 0x1e, 0xa2, 0x1e, 0xa2, 0x1e,
+    0xa4, 0x1e, 0xa4, 0x1e, 0xa6, 0x1e, 0xa6, 0x1e, 0xa8, 0x1e, 0xa8, 0x1e, 0xaa, 0x1e, 0xaa, 0x1e,
+    0xac, 0x1e, 0xac, 0x1e, 0xae, 0x1e, 0xae, 0x1e, 0xb0, 0x1e, 0xb0, 0x1e, 0xb2, 0x1e, 0xb2, 0x1e,
+    0xb4, 0x1e, 0xb4, 0x1e, 0xb6, 0x1e, 0xb6, 0x1e, 0xb8, 0x1e, 0xb8, 0x1e, 0xba, 0x1e, 0xba, 0x1e,
+    0xbc, 0x1e, 0xbc, 0x1e, 0xbe, 0x1e, 0xbe, 0x1e, 0xc0, 0x1e, 0xc0, 0x1e, 0xc2, 0x1e, 0xc2, 0x1e,
+    0xc4, 0x1e, 0xc4, 0x1e, 0xc6, 0x1e, 0xc6, 0x1e, 0xc8, 0x1e, 0xc8, 0x1e, 0xca, 0x1e, 0xca, 0x1e,
+    0xcc, 0x1e, 0xcc, 0x1e, 0xce, 0x1e, 0xce, 0x1e, 0xd0, 0x1e, 0xd0, 0x1e, 0xd2, 0x1e, 0xd2, 0x1e,
+    0xd4, 0x1e, 0xd4, 0x1e, 0xd6, 0x1e, 0xd6, 0x1e, 0xd8, 0x1e, 0xd8, 0x1e, 0xda, 0x1e, 0xda, 0x1e,
+    0xdc, 0x1e, 0xdc, 0x1e, 0xde, 0x1e, 0xde, 0x1e, 0xe0, 0x1e, 0xe0, 0x1e, 0xe2, 0x1e, 0xe2, 0x1e,
+    0xe4, 0x1e, 0xe4, 0x1e, 0xe6, 0x1e, 0xe6, 0x1e, 0xe8, 0x1e, 0xe8, 0x1e, 0xea, 0x1e, 0xea, 0x1e,
+    0xec, 0x1e, 0xec, 0x1e, 0xee, 0x1e, 0xee, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf2, 0x1e, 0xf2, 0x1e,
+
+    /* Sector 8 */
+
+    0xf4, 0x1e, 0xf4, 0x1e, 0xf6, 0x1e, 0xf6, 0x1e, 0xf8, 0x1e, 0xf8, 0x1e, 0xfa, 0x1e, 0xfb, 0x1e,
+    0xfc, 0x1e, 0xfd, 0x1e, 0xfe, 0x1e, 0xff, 0x1e, 0x08, 0x1f, 0x09, 0x1f, 0x0a, 0x1f, 0x0b, 0x1f,
+    0x0c, 0x1f, 0x0d, 0x1f, 0x0e, 0x1f, 0x0f, 0x1f, 0x08, 0x1f, 0x09, 0x1f, 0x0a, 0x1f, 0x0b, 0x1f,
+    0x0c, 0x1f, 0x0d, 0x1f, 0x0e, 0x1f, 0x0f, 0x1f, 0x18, 0x1f, 0x19, 0x1f, 0x1a, 0x1f, 0x1b, 0x1f,
+    0x1c, 0x1f, 0x1d, 0x1f, 0x16, 0x1f, 0x17, 0x1f, 0x18, 0x1f, 0x19, 0x1f, 0x1a, 0x1f, 0x1b, 0x1f,
+    0x1c, 0x1f, 0x1d, 0x1f, 0x1e, 0x1f, 0x1f, 0x1f, 0x28, 0x1f, 0x29, 0x1f, 0x2a, 0x1f, 0x2b, 0x1f,
+    0x2c, 0x1f, 0x2d, 0x1f, 0x2e, 0x1f, 0x2f, 0x1f, 0x28, 0x1f, 0x29, 0x1f, 0x2a, 0x1f, 0x2b, 0x1f,
+    0x2c, 0x1f, 0x2d, 0x1f, 0x2e, 0x1f, 0x2f, 0x1f, 0x38, 0x1f, 0x39, 0x1f, 0x3a, 0x1f, 0x3b, 0x1f,
+    0x3c, 0x1f, 0x3d, 0x1f, 0x3e, 0x1f, 0x3f, 0x1f, 0x38, 0x1f, 0x39, 0x1f, 0x3a, 0x1f, 0x3b, 0x1f,
+    0x3c, 0x1f, 0x3d, 0x1f, 0x3e, 0x1f, 0x3f, 0x1f, 0x48, 0x1f, 0x49, 0x1f, 0x4a, 0x1f, 0x4b, 0x1f,
+    0x4c, 0x1f, 0x4d, 0x1f, 0x46, 0x1f, 0x47, 0x1f, 0x48, 0x1f, 0x49, 0x1f, 0x4a, 0x1f, 0x4b, 0x1f,
+    0x4c, 0x1f, 0x4d, 0x1f, 0x4e, 0x1f, 0x4f, 0x1f, 0x50, 0x1f, 0x59, 0x1f, 0x52, 0x1f, 0x5b, 0x1f,
+    0x54, 0x1f, 0x5d, 0x1f, 0x56, 0x1f, 0x5f, 0x1f, 0x58, 0x1f, 0x59, 0x1f, 0x5a, 0x1f, 0x5b, 0x1f,
+    0x5c, 0x1f, 0x5d, 0x1f, 0x5e, 0x1f, 0x5f, 0x1f, 0x68, 0x1f, 0x69, 0x1f, 0x6a, 0x1f, 0x6b, 0x1f,
+    0x6c, 0x1f, 0x6d, 0x1f, 0x6e, 0x1f, 0x6f, 0x1f, 0x68, 0x1f, 0x69, 0x1f, 0x6a, 0x1f, 0x6b, 0x1f,
+    0x6c, 0x1f, 0x6d, 0x1f, 0x6e, 0x1f, 0x6f, 0x1f, 0xba, 0x1f, 0xbb, 0x1f, 0xc8, 0x1f, 0xc9, 0x1f,
+    0xca, 0x1f, 0xcb, 0x1f, 0xda, 0x1f, 0xdb, 0x1f, 0xf8, 0x1f, 0xf9, 0x1f, 0xea, 0x1f, 0xeb, 0x1f,
+    0xfa, 0x1f, 0xfb, 0x1f, 0x7e, 0x1f, 0x7f, 0x1f, 0x88, 0x1f, 0x89, 0x1f, 0x8a, 0x1f, 0x8b, 0x1f,
+    0x8c, 0x1f, 0x8d, 0x1f, 0x8e, 0x1f, 0x8f, 0x1f, 0x88, 0x1f, 0x89, 0x1f, 0x8a, 0x1f, 0x8b, 0x1f,
+    0x8c, 0x1f, 0x8d, 0x1f, 0x8e, 0x1f, 0x8f, 0x1f, 0x98, 0x1f, 0x99, 0x1f, 0x9a, 0x1f, 0x9b, 0x1f,
+    0x9c, 0x1f, 0x9d, 0x1f, 0x9e, 0x1f, 0x9f, 0x1f, 0x98, 0x1f, 0x99, 0x1f, 0x9a, 0x1f, 0x9b, 0x1f,
+    0x9c, 0x1f, 0x9d, 0x1f, 0x9e, 0x1f, 0x9f, 0x1f, 0xa8, 0x1f, 0xa9, 0x1f, 0xaa, 0x1f, 0xab, 0x1f,
+    0xac, 0x1f, 0xad, 0x1f, 0xae, 0x1f, 0xaf, 0x1f, 0xa8, 0x1f, 0xa9, 0x1f, 0xaa, 0x1f, 0xab, 0x1f,
+    0xac, 0x1f, 0xad, 0x1f, 0xae, 0x1f, 0xaf, 0x1f, 0xb8, 0x1f, 0xb9, 0x1f, 0xb2, 0x1f, 0xbc, 0x1f,
+    0xb4, 0x1f, 0xb5, 0x1f, 0xb6, 0x1f, 0xb7, 0x1f, 0xb8, 0x1f, 0xb9, 0x1f, 0xba, 0x1f, 0xbb, 0x1f,
+    0xbc, 0x1f, 0xbd, 0x1f, 0xbe, 0x1f, 0xbf, 0x1f, 0xc0, 0x1f, 0xc1, 0x1f, 0xc2, 0x1f, 0xc3, 0x1f,
+    0xc4, 0x1f, 0xc5, 0x1f, 0xc6, 0x1f, 0xc7, 0x1f, 0xc8, 0x1f, 0xc9, 0x1f, 0xca, 0x1f, 0xcb, 0x1f,
+    0xc3, 0x1f, 0xcd, 0x1f, 0xce, 0x1f, 0xcf, 0x1f, 0xd8, 0x1f, 0xd9, 0x1f, 0xd2, 0x1f, 0xd3, 0x1f,
+    0xd4, 0x1f, 0xd5, 0x1f, 0xd6, 0x1f, 0xd7, 0x1f, 0xd8, 0x1f, 0xd9, 0x1f, 0xda, 0x1f, 0xdb, 0x1f,
+    0xdc, 0x1f, 0xdd, 0x1f, 0xde, 0x1f, 0xdf, 0x1f, 0xe8, 0x1f, 0xe9, 0x1f, 0xe2, 0x1f, 0xe3, 0x1f,
+    0xe4, 0x1f, 0xec, 0x1f, 0xe6, 0x1f, 0xe7, 0x1f, 0xe8, 0x1f, 0xe9, 0x1f, 0xea, 0x1f, 0xeb, 0x1f,
+    0xec, 0x1f, 0xed, 0x1f, 0xee, 0x1f, 0xef, 0x1f, 0xf0, 0x1f, 0xf1, 0x1f, 0xf2, 0x1f, 0xf3, 0x1f,
+
+    /* Sector 9 */
+
+    0xf4, 0x1f, 0xf5, 0x1f, 0xf6, 0x1f, 0xf7, 0x1f, 0xf8, 0x1f, 0xf9, 0x1f, 0xfa, 0x1f, 0xfb, 0x1f,
+    0xf3, 0x1f, 0xfd, 0x1f, 0xfe, 0x1f, 0xff, 0x1f, 0x00, 0x20, 0x01, 0x20, 0x02, 0x20, 0x03, 0x20,
+    0x04, 0x20, 0x05, 0x20, 0x06, 0x20, 0x07, 0x20, 0x08, 0x20, 0x09, 0x20, 0x0a, 0x20, 0x0b, 0x20,
+    0x0c, 0x20, 0x0d, 0x20, 0x0e, 0x20, 0x0f, 0x20, 0x10, 0x20, 0x11, 0x20, 0x12, 0x20, 0x13, 0x20,
+    0x14, 0x20, 0x15, 0x20, 0x16, 0x20, 0x17, 0x20, 0x18, 0x20, 0x19, 0x20, 0x1a, 0x20, 0x1b, 0x20,
+    0x1c, 0x20, 0x1d, 0x20, 0x1e, 0x20, 0x1f, 0x20, 0x20, 0x20, 0x21, 0x20, 0x22, 0x20, 0x23, 0x20,
+    0x24, 0x20, 0x25, 0x20, 0x26, 0x20, 0x27, 0x20, 0x28, 0x20, 0x29, 0x20, 0x2a, 0x20, 0x2b, 0x20,
+    0x2c, 0x20, 0x2d, 0x20, 0x2e, 0x20, 0x2f, 0x20, 0x30, 0x20, 0x31, 0x20, 0x32, 0x20, 0x33, 0x20,
+    0x34, 0x20, 0x35, 0x20, 0x36, 0x20, 0x37, 0x20, 0x38, 0x20, 0x39, 0x20, 0x3a, 0x20, 0x3b, 0x20,
+    0x3c, 0x20, 0x3d, 0x20, 0x3e, 0x20, 0x3f, 0x20, 0x40, 0x20, 0x41, 0x20, 0x42, 0x20, 0x43, 0x20,
+    0x44, 0x20, 0x45, 0x20, 0x46, 0x20, 0x47, 0x20, 0x48, 0x20, 0x49, 0x20, 0x4a, 0x20, 0x4b, 0x20,
+    0x4c, 0x20, 0x4d, 0x20, 0x4e, 0x20, 0x4f, 0x20, 0x50, 0x20, 0x51, 0x20, 0x52, 0x20, 0x53, 0x20,
+    0x54, 0x20, 0x55, 0x20, 0x56, 0x20, 0x57, 0x20, 0x58, 0x20, 0x59, 0x20, 0x5a, 0x20, 0x5b, 0x20,
+    0x5c, 0x20, 0x5d, 0x20, 0x5e, 0x20, 0x5f, 0x20, 0x60, 0x20, 0x61, 0x20, 0x62, 0x20, 0x63, 0x20,
+    0x64, 0x20, 0x65, 0x20, 0x66, 0x20, 0x67, 0x20, 0x68, 0x20, 0x69, 0x20, 0x6a, 0x20, 0x6b, 0x20,
+    0x6c, 0x20, 0x6d, 0x20, 0x6e, 0x20, 0x6f, 0x20, 0x70, 0x20, 0x71, 0x20, 0x72, 0x20, 0x73, 0x20,
+    0x74, 0x20, 0x75, 0x20, 0x76, 0x20, 0x77, 0x20, 0x78, 0x20, 0x79, 0x20, 0x7a, 0x20, 0x7b, 0x20,
+    0x7c, 0x20, 0x7d, 0x20, 0x7e, 0x20, 0x7f, 0x20, 0x80, 0x20, 0x81, 0x20, 0x82, 0x20, 0x83, 0x20,
+    0x84, 0x20, 0x85, 0x20, 0x86, 0x20, 0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x8a, 0x20, 0x8b, 0x20,
+    0x8c, 0x20, 0x8d, 0x20, 0x8e, 0x20, 0x8f, 0x20, 0x90, 0x20, 0x91, 0x20, 0x92, 0x20, 0x93, 0x20,
+    0x94, 0x20, 0x95, 0x20, 0x96, 0x20, 0x97, 0x20, 0x98, 0x20, 0x99, 0x20, 0x9a, 0x20, 0x9b, 0x20,
+    0x9c, 0x20, 0x9d, 0x20, 0x9e, 0x20, 0x9f, 0x20, 0xa0, 0x20, 0xa1, 0x20, 0xa2, 0x20, 0xa3, 0x20,
+    0xa4, 0x20, 0xa5, 0x20, 0xa6, 0x20, 0xa7, 0x20, 0xa8, 0x20, 0xa9, 0x20, 0xaa, 0x20, 0xab, 0x20,
+    0xac, 0x20, 0xad, 0x20, 0xae, 0x20, 0xaf, 0x20, 0xb0, 0x20, 0xb1, 0x20, 0xb2, 0x20, 0xb3, 0x20,
+    0xb4, 0x20, 0xb5, 0x20, 0xb6, 0x20, 0xb7, 0x20, 0xb8, 0x20, 0xb9, 0x20, 0xba, 0x20, 0xbb, 0x20,
+    0xbc, 0x20, 0xbd, 0x20, 0xbe, 0x20, 0xbf, 0x20, 0xc0, 0x20, 0xc1, 0x20, 0xc2, 0x20, 0xc3, 0x20,
+    0xc4, 0x20, 0xc5, 0x20, 0xc6, 0x20, 0xc7, 0x20, 0xc8, 0x20, 0xc9, 0x20, 0xca, 0x20, 0xcb, 0x20,
+    0xcc, 0x20, 0xcd, 0x20, 0xce, 0x20, 0xcf, 0x20, 0xd0, 0x20, 0xd1, 0x20, 0xd2, 0x20, 0xd3, 0x20,
+    0xd4, 0x20, 0xd5, 0x20, 0xd6, 0x20, 0xd7, 0x20, 0xd8, 0x20, 0xd9, 0x20, 0xda, 0x20, 0xdb, 0x20,
+    0xdc, 0x20, 0xdd, 0x20, 0xde, 0x20, 0xdf, 0x20, 0xe0, 0x20, 0xe1, 0x20, 0xe2, 0x20, 0xe3, 0x20,
+    0xe4, 0x20, 0xe5, 0x20, 0xe6, 0x20, 0xe7, 0x20, 0xe8, 0x20, 0xe9, 0x20, 0xea, 0x20, 0xeb, 0x20,
+    0xec, 0x20, 0xed, 0x20, 0xee, 0x20, 0xef, 0x20, 0xf0, 0x20, 0xf1, 0x20, 0xf2, 0x20, 0xf3, 0x20,
+
+    /* Sector 10 */
+
+    0xf4, 0x20, 0xf5, 0x20, 0xf6, 0x20, 0xf7, 0x20, 0xf8, 0x20, 0xf9, 0x20, 0xfa, 0x20, 0xfb, 0x20,
+    0xfc, 0x20, 0xfd, 0x20, 0xfe, 0x20, 0xff, 0x20, 0x00, 0x21, 0x01, 0x21, 0x02, 0x21, 0x03, 0x21,
+    0x04, 0x21, 0x05, 0x21, 0x06, 0x21, 0x07, 0x21, 0x08, 0x21, 0x09, 0x21, 0x0a, 0x21, 0x0b, 0x21,
+    0x0c, 0x21, 0x0d, 0x21, 0x0e, 0x21, 0x0f, 0x21, 0x10, 0x21, 0x11, 0x21, 0x12, 0x21, 0x13, 0x21,
+    0x14, 0x21, 0x15, 0x21, 0x16, 0x21, 0x17, 0x21, 0x18, 0x21, 0x19, 0x21, 0x1a, 0x21, 0x1b, 0x21,
+    0x1c, 0x21, 0x1d, 0x21, 0x1e, 0x21, 0x1f, 0x21, 0x20, 0x21, 0x21, 0x21, 0x22, 0x21, 0x23, 0x21,
+    0x24, 0x21, 0x25, 0x21, 0x26, 0x21, 0x27, 0x21, 0x28, 0x21, 0x29, 0x21, 0x2a, 0x21, 0x2b, 0x21,
+    0x2c, 0x21, 0x2d, 0x21, 0x2e, 0x21, 0x2f, 0x21, 0x30, 0x21, 0x31, 0x21, 0x32, 0x21, 0x33, 0x21,
+    0x34, 0x21, 0x35, 0x21, 0x36, 0x21, 0x37, 0x21, 0x38, 0x21, 0x39, 0x21, 0x3a, 0x21, 0x3b, 0x21,
+    0x3c, 0x21, 0x3d, 0x21, 0x3e, 0x21, 0x3f, 0x21, 0x40, 0x21, 0x41, 0x21, 0x42, 0x21, 0x43, 0x21,
+    0x44, 0x21, 0x45, 0x21, 0x46, 0x21, 0x47, 0x21, 0x48, 0x21, 0x49, 0x21, 0x4a, 0x21, 0x4b, 0x21,
+    0x4c, 0x21, 0x4d, 0x21, 0x32, 0x21, 0x4f, 0x21, 0x50, 0x21, 0x51, 0x21, 0x52, 0x21, 0x53, 0x21,
+    0x54, 0x21, 0x55, 0x21, 0x56, 0x21, 0x57, 0x21, 0x58, 0x21, 0x59, 0x21, 0x5a, 0x21, 0x5b, 0x21,
+    0x5c, 0x21, 0x5d, 0x21, 0x5e, 0x21, 0x5f, 0x21, 0x60, 0x21, 0x61, 0x21, 0x62, 0x21, 0x63, 0x21,
+    0x64, 0x21, 0x65, 0x21, 0x66, 0x21, 0x67, 0x21, 0x68, 0x21, 0x69, 0x21, 0x6a, 0x21, 0x6b, 0x21,
+    0x6c, 0x21, 0x6d, 0x21, 0x6e, 0x21, 0x6f, 0x21, 0x60, 0x21, 0x61, 0x21, 0x62, 0x21, 0x63, 0x21,
+    0x64, 0x21, 0x65, 0x21, 0x66, 0x21, 0x67, 0x21, 0x68, 0x21, 0x69, 0x21, 0x6a, 0x21, 0x6b, 0x21,
+    0x6c, 0x21, 0x6d, 0x21, 0x6e, 0x21, 0x6f, 0x21, 0x80, 0x21, 0x81, 0x21, 0x82, 0x21, 0x83, 0x21,
+    0x83, 0x21, 0xff, 0xff, 0x4b, 0x03, 0xb6, 0x24, 0xb7, 0x24, 0xb8, 0x24, 0xb9, 0x24, 0xba, 0x24,
+    0xbb, 0x24, 0xbc, 0x24, 0xbd, 0x24, 0xbe, 0x24, 0xbf, 0x24, 0xc0, 0x24, 0xc1, 0x24, 0xc2, 0x24,
+    0xc3, 0x24, 0xc4, 0x24, 0xc5, 0x24, 0xc6, 0x24, 0xc7, 0x24, 0xc8, 0x24, 0xc9, 0x24, 0xca, 0x24,
+    0xcb, 0x24, 0xcc, 0x24, 0xcd, 0x24, 0xce, 0x24, 0xcf, 0x24, 0xff, 0xff, 0x46, 0x07, 0x00, 0x2c,
+    0x01, 0x2c, 0x02, 0x2c, 0x03, 0x2c, 0x04, 0x2c, 0x05, 0x2c, 0x06, 0x2c, 0x07, 0x2c, 0x08, 0x2c,
+    0x09, 0x2c, 0x0a, 0x2c, 0x0b, 0x2c, 0x0c, 0x2c, 0x0d, 0x2c, 0x0e, 0x2c, 0x0f, 0x2c, 0x10, 0x2c,
+    0x11, 0x2c, 0x12, 0x2c, 0x13, 0x2c, 0x14, 0x2c, 0x15, 0x2c, 0x16, 0x2c, 0x17, 0x2c, 0x18, 0x2c,
+    0x19, 0x2c, 0x1a, 0x2c, 0x1b, 0x2c, 0x1c, 0x2c, 0x1d, 0x2c, 0x1e, 0x2c, 0x1f, 0x2c, 0x20, 0x2c,
+    0x21, 0x2c, 0x22, 0x2c, 0x23, 0x2c, 0x24, 0x2c, 0x25, 0x2c, 0x26, 0x2c, 0x27, 0x2c, 0x28, 0x2c,
+    0x29, 0x2c, 0x2a, 0x2c, 0x2b, 0x2c, 0x2c, 0x2c, 0x2d, 0x2c, 0x2e, 0x2c, 0x5f, 0x2c, 0x60, 0x2c,
+    0x60, 0x2c, 0x62, 0x2c, 0x63, 0x2c, 0x64, 0x2c, 0x65, 0x2c, 0x66, 0x2c, 0x67, 0x2c, 0x67, 0x2c,
+    0x69, 0x2c, 0x69, 0x2c, 0x6b, 0x2c, 0x6b, 0x2c, 0x6d, 0x2c, 0x6e, 0x2c, 0x6f, 0x2c, 0x70, 0x2c,
+    0x71, 0x2c, 0x72, 0x2c, 0x73, 0x2c, 0x74, 0x2c, 0x75, 0x2c, 0x75, 0x2c, 0x77, 0x2c, 0x78, 0x2c,
+    0x79, 0x2c, 0x7a, 0x2c, 0x7b, 0x2c, 0x7c, 0x2c, 0x7d, 0x2c, 0x7e, 0x2c, 0x7f, 0x2c, 0x80, 0x2c,
+
+    /* Sector 11 */
+
+    0x80, 0x2c, 0x82, 0x2c, 0x82, 0x2c, 0x84, 0x2c, 0x84, 0x2c, 0x86, 0x2c, 0x86, 0x2c, 0x88, 0x2c,
+    0x88, 0x2c, 0x8a, 0x2c, 0x8a, 0x2c, 0x8c, 0x2c, 0x8c, 0x2c, 0x8e, 0x2c, 0x8e, 0x2c, 0x90, 0x2c,
+    0x90, 0x2c, 0x92, 0x2c, 0x92, 0x2c, 0x94, 0x2c, 0x94, 0x2c, 0x96, 0x2c, 0x96, 0x2c, 0x98, 0x2c,
+    0x98, 0x2c, 0x9a, 0x2c, 0x9a, 0x2c, 0x9c, 0x2c, 0x9c, 0x2c, 0x9e, 0x2c, 0x9e, 0x2c, 0xa0, 0x2c,
+    0xa0, 0x2c, 0xa2, 0x2c, 0xa2, 0x2c, 0xa4, 0x2c, 0xa4, 0x2c, 0xa6, 0x2c, 0xa6, 0x2c, 0xa8, 0x2c,
+    0xa8, 0x2c, 0xaa, 0x2c, 0xaa, 0x2c, 0xac, 0x2c, 0xac, 0x2c, 0xae, 0x2c, 0xae, 0x2c, 0xb0, 0x2c,
+    0xb0, 0x2c, 0xb2, 0x2c, 0xb2, 0x2c, 0xb4, 0x2c, 0xb4, 0x2c, 0xb6, 0x2c, 0xb6, 0x2c, 0xb8, 0x2c,
+    0xb8, 0x2c, 0xba, 0x2c, 0xba, 0x2c, 0xbc, 0x2c, 0xbc, 0x2c, 0xbe, 0x2c, 0xbe, 0x2c, 0xc0, 0x2c,
+    0xc0, 0x2c, 0xc2, 0x2c, 0xc2, 0x2c, 0xc4, 0x2c, 0xc4, 0x2c, 0xc6, 0x2c, 0xc6, 0x2c, 0xc8, 0x2c,
+    0xc8, 0x2c, 0xca, 0x2c, 0xca, 0x2c, 0xcc, 0x2c, 0xcc, 0x2c, 0xce, 0x2c, 0xce, 0x2c, 0xd0, 0x2c,
+    0xd0, 0x2c, 0xd2, 0x2c, 0xd2, 0x2c, 0xd4, 0x2c, 0xd4, 0x2c, 0xd6, 0x2c, 0xd6, 0x2c, 0xd8, 0x2c,
+    0xd8, 0x2c, 0xda, 0x2c, 0xda, 0x2c, 0xdc, 0x2c, 0xdc, 0x2c, 0xde, 0x2c, 0xde, 0x2c, 0xe0, 0x2c,
+    0xe0, 0x2c, 0xe2, 0x2c, 0xe2, 0x2c, 0xe4, 0x2c, 0xe5, 0x2c, 0xe6, 0x2c, 0xe7, 0x2c, 0xe8, 0x2c,
+    0xe9, 0x2c, 0xea, 0x2c, 0xeb, 0x2c, 0xec, 0x2c, 0xed, 0x2c, 0xee, 0x2c, 0xef, 0x2c, 0xf0, 0x2c,
+    0xf1, 0x2c, 0xf2, 0x2c, 0xf3, 0x2c, 0xf4, 0x2c, 0xf5, 0x2c, 0xf6, 0x2c, 0xf7, 0x2c, 0xf8, 0x2c,
+    0xf9, 0x2c, 0xfa, 0x2c, 0xfb, 0x2c, 0xfc, 0x2c, 0xfd, 0x2c, 0xfe, 0x2c, 0xff, 0x2c, 0xa0, 0x10,
+    0xa1, 0x10, 0xa2, 0x10, 0xa3, 0x10, 0xa4, 0x10, 0xa5, 0x10, 0xa6, 0x10, 0xa7, 0x10, 0xa8, 0x10,
+    0xa9, 0x10, 0xaa, 0x10, 0xab, 0x10, 0xac, 0x10, 0xad, 0x10, 0xae, 0x10, 0xaf, 0x10, 0xb0, 0x10,
+    0xb1, 0x10, 0xb2, 0x10, 0xb3, 0x10, 0xb4, 0x10, 0xb5, 0x10, 0xb6, 0x10, 0xb7, 0x10, 0xb8, 0x10,
+    0xb9, 0x10, 0xba, 0x10, 0xbb, 0x10, 0xbc, 0x10, 0xbd, 0x10, 0xbe, 0x10, 0xbf, 0x10, 0xc0, 0x10,
+    0xc1, 0x10, 0xc2, 0x10, 0xc3, 0x10, 0xc4, 0x10, 0xc5, 0x10, 0xff, 0xff, 0x1b, 0xd2, 0x21, 0xff,
+    0x22, 0xff, 0x23, 0xff, 0x24, 0xff, 0x25, 0xff, 0x26, 0xff, 0x27, 0xff, 0x28, 0xff, 0x29, 0xff,
+    0x2a, 0xff, 0x2b, 0xff, 0x2c, 0xff, 0x2d, 0xff, 0x2e, 0xff, 0x2f, 0xff, 0x30, 0xff, 0x31, 0xff,
+    0x32, 0xff, 0x33, 0xff, 0x34, 0xff, 0x35, 0xff, 0x36, 0xff, 0x37, 0xff, 0x38, 0xff, 0x39, 0xff,
+    0x3a, 0xff, 0x5b, 0xff, 0x5c, 0xff, 0x5d, 0xff, 0x5e, 0xff, 0x5f, 0xff, 0x60, 0xff, 0x61, 0xff,
+    0x62, 0xff, 0x63, 0xff, 0x64, 0xff, 0x65, 0xff, 0x66, 0xff, 0x67, 0xff, 0x68, 0xff, 0x69, 0xff,
+    0x6a, 0xff, 0x6b, 0xff, 0x6c, 0xff, 0x6d, 0xff, 0x6e, 0xff, 0x6f, 0xff, 0x70, 0xff, 0x71, 0xff,
+    0x72, 0xff, 0x73, 0xff, 0x74, 0xff, 0x75, 0xff, 0x76, 0xff, 0x77, 0xff, 0x78, 0xff, 0x79, 0xff,
+    0x7a, 0xff, 0x7b, 0xff, 0x7c, 0xff, 0x7d, 0xff, 0x7e, 0xff, 0x7f, 0xff, 0x80, 0xff, 0x81, 0xff,
+    0x82, 0xff, 0x83, 0xff, 0x84, 0xff, 0x85, 0xff, 0x86, 0xff, 0x87, 0xff, 0x88, 0xff, 0x89, 0xff,
+    0x8a, 0xff, 0x8b, 0xff, 0x8c, 0xff, 0x8d, 0xff, 0x8e, 0xff, 0x8f, 0xff, 0x90, 0xff, 0x91, 0xff,
+    0x92, 0xff, 0x93, 0xff, 0x94, 0xff, 0x95, 0xff, 0x96, 0xff, 0x97, 0xff, 0x98, 0xff, 0x99, 0xff,
+
+    /* Sector 12 */
+
+    0x9a, 0xff, 0x9b, 0xff, 0x9c, 0xff, 0x9d, 0xff, 0x9e, 0xff, 0x9f, 0xff, 0xa0, 0xff, 0xa1, 0xff,
+    0xa2, 0xff, 0xa3, 0xff, 0xa4, 0xff, 0xa5, 0xff, 0xa6, 0xff, 0xa7, 0xff, 0xa8, 0xff, 0xa9, 0xff,
+    0xaa, 0xff, 0xab, 0xff, 0xac, 0xff, 0xad, 0xff, 0xae, 0xff, 0xaf, 0xff, 0xb0, 0xff, 0xb1, 0xff,
+    0xb2, 0xff, 0xb3, 0xff, 0xb4, 0xff, 0xb5, 0xff, 0xb6, 0xff, 0xb7, 0xff, 0xb8, 0xff, 0xb9, 0xff,
+    0xba, 0xff, 0xbb, 0xff, 0xbc, 0xff, 0xbd, 0xff, 0xbe, 0xff, 0xbf, 0xff, 0xc0, 0xff, 0xc1, 0xff,
+    0xc2, 0xff, 0xc3, 0xff, 0xc4, 0xff, 0xc5, 0xff, 0xc6, 0xff, 0xc7, 0xff, 0xc8, 0xff, 0xc9, 0xff,
+    0xca, 0xff, 0xcb, 0xff, 0xcc, 0xff, 0xcd, 0xff, 0xce, 0xff, 0xcf, 0xff, 0xd0, 0xff, 0xd1, 0xff,
+    0xd2, 0xff, 0xd3, 0xff, 0xd4, 0xff, 0xd5, 0xff, 0xd6, 0xff, 0xd7, 0xff, 0xd8, 0xff, 0xd9, 0xff,
+    0xda, 0xff, 0xdb, 0xff, 0xdc, 0xff, 0xdd, 0xff, 0xde, 0xff, 0xdf, 0xff, 0xe0, 0xff, 0xe1, 0xff,
+    0xe2, 0xff, 0xe3, 0xff, 0xe4, 0xff, 0xe5, 0xff, 0xe6, 0xff, 0xe7, 0xff, 0xe8, 0xff, 0xe9, 0xff,
+    0xea, 0xff, 0xeb, 0xff, 0xec, 0xff, 0xed, 0xff, 0xee, 0xff, 0xef, 0xff, 0xf0, 0xff, 0xf1, 0xff,
+    0xf2, 0xff, 0xf3, 0xff, 0xf4, 0xff, 0xf5, 0xff, 0xf6, 0xff, 0xf7, 0xff, 0xf8, 0xff, 0xf9, 0xff,
+    0xfa, 0xff, 0xfb, 0xff, 0xfc, 0xff, 0xfd, 0xff, 0xfe, 0xff, 0xff, 0xff
+};
+
+
+const ULONG UpCaseTableCheckSum = 0xE619D30D;
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_media_exFAT_format                              PORTABLE C      */
+/*                                                           6.1.10       */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function formats the media with exFAT file system with raw     */
+/*    calls to the I/O driver. It can and must be called before the       */
+/*    fx_media_open and is designed to utilize the same underlying        */
+/*    FileX driver.                                                       */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Pointer to media control block*/
+/*                                            (does not need to be opened)*/
+/*    driver                                Pointer to FileX driver (must */
+/*                                            be able to field requests   */
+/*                                            prior to opening)           */
+/*    driver_info_ptr                       Optional information pointer  */
+/*    memory_ptr                            Pointer to memory used by the */
+/*                                            FileX for this media.       */
+/*    memory_size                           Size of media memory - must   */
+/*                                            at least 512 bytes and      */
+/*                                            one sector size.            */
+/*    volume_name                           Name of the volume            */
+/*    number_of_fats                        Number of FAT tables          */
+/*    hidden_sectors                        Number of hidden sectors      */
+/*    total_sectors                         Total number of sectors       */
+/*    bytes_per_sector                      Number of bytes per sector    */
+/*    sectors_per_cluster                   Number of sectors per cluster */
+/*    volume_serial_number                  Volume Serial Number          */
+/*    boundary_unit                         Data area alignment in sectors*/
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    Completion Status                                                   */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    Media driver                                                        */
+/*    _fx_utility_exFAT_size_calculate      Calculate FAT size            */
+/*    _fx_utility_exFAT_system_sector_write Write a format sector         */
+/*    _fx_utility_exFAT_system_area_format  Format the exFAT system area  */
+/*    _fx_utility_exFAT_system_area_checksum_write                        */
+/*                                          Write the checksum            */
+/*    _fx_utility_memory_set                Set memory                    */
+/*    _fx_utility_memory_copy               Copy memory                   */
+/*    _fx_utility_16_unsigned_write         Write 16-bit unsigned         */
+/*    _fx_utility_32_unsigned_write         Write 32-bit unsigned         */
+/*    _fx_utility_64_unsigned_write         Write 64-bit unsigned         */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s), verified */
+/*                                            memcpy usage,               */
+/*                                            resulting in version 6.1    */
+/*  01-31-2022     Bhupendra Naphade        Modified comment(s), removed  */
+/*                                            fixed sector size in exFAT, */
+/*                                            resulting in version 6.1.10 */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_media_exFAT_format(FX_MEDIA *media_ptr,
+                             VOID (*driver)(FX_MEDIA *media),
+                             VOID *driver_info_ptr,
+                             UCHAR *memory_ptr,
+                             UINT memory_size,
+                             CHAR *volume_name,
+                             UINT number_of_fats,
+                             ULONG64 hidden_sectors,
+                             ULONG64 total_sectors,
+                             UINT bytes_per_sector,
+                             UINT sectors_per_cluster,
+                             UINT volume_serial_number,
+                             UINT boundary_unit)
+{
+
+UCHAR *byte_ptr;
+UCHAR  jump_boot[]        = {0xEB, 0x76, 0x90};
+UCHAR  file_system_name[] = {'E', 'X', 'F', 'A', 'T', 0x20, 0x20, 0x20};
+UCHAR  fat_init_mask[]    = {0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+ULONG  i;
+ULONG  sector_offset;
+ULONG  fat_offset;
+ULONG  sectors_per_fat;
+ULONG  cluster_heap_offset;
+ULONG  cluster_count;
+ULONG  root_dir_entry_first_sector;
+ULONG  root_dir_entry_first_cluster;
+CHAR   bytes_per_sector_shift;
+CHAR   sector_per_cluster_shift;
+ULONG  bitmap_size_in_bytes;
+ULONG  bitmap_size_in_clusters;
+ULONG  upcase_table_size_in_bytes;
+ULONG  upcase_table_size_in_clusters;
+ULONG  upcase_table_checksum = 0;
+ULONG  system_area_checksum = 0;
+ULONG  offset;
+UINT   status;
+
+
+    /* This parameter has not been supported yet. */
+    FX_PARAMETER_NOT_USED(number_of_fats);
+
+    /* Validate bytes per sector value:  no more than 4096. */
+    if(bytes_per_sector > 4096)
+        return(FX_SECTOR_INVALID);
+
+    /* Validate bytes per cluster value: no more than 32MB */
+    if((bytes_per_sector * sectors_per_cluster) > (1 << 25))
+        return(FX_SECTOR_INVALID);
+
+   /* Validate bytes per sector value: no more than bitmap cache size */
+    if (bytes_per_sector > sizeof(media_ptr -> fx_media_exfat_bitmap_cache))
+    {
+        return(FX_NOT_ENOUGH_MEMORY);
+    }
+
+    /* Create & write bootrecord from drive geometry information.  */
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_MEDIA_FORMAT, media_ptr, hidden_sectors, total_sectors, sectors_per_cluster, FX_TRACE_MEDIA_EVENTS, 0, 0)
+
+    /* Setup driver pointer and memory information.  */
+    media_ptr -> fx_media_driver_entry =                driver;
+    media_ptr -> fx_media_memory_buffer =               (UCHAR *)memory_ptr;
+    media_ptr -> fx_media_memory_size =                 memory_size;
+
+    /* Store geometry information in media record - driver needs this.  */
+    media_ptr -> fx_media_bytes_per_sector =            bytes_per_sector;
+#ifdef FX_DRIVER_USE_64BIT_LBA
+    media_ptr -> fx_media_hidden_sectors =              hidden_sectors;
+#else
+    media_ptr -> fx_media_hidden_sectors =              (ULONG)hidden_sectors;
+#endif
+    /* Initialize the supplied media I/O driver.  First, build the
+       initialize driver request.  */
+    media_ptr -> fx_media_driver_request =              FX_DRIVER_INIT;
+    media_ptr -> fx_media_driver_status =               FX_IO_ERROR;
+    media_ptr -> fx_media_driver_info =                 driver_info_ptr;
+    media_ptr -> fx_media_driver_write_protect =        FX_FALSE;
+    media_ptr -> fx_media_driver_free_sector_update =   FX_FALSE;
+    media_ptr -> fx_media_driver_data_sector_read =     FX_FALSE;
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_INIT, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+    /* Call the specified I/O driver with the initialize request.  */
+    (media_ptr -> fx_media_driver_entry) (media_ptr);
+
+    /* Determine if the I/O driver initialized successfully.  */
+    if (media_ptr -> fx_media_driver_status != FX_SUCCESS)
+    {
+
+        /* Return the driver error status.  */
+        return(FX_IO_ERROR);
+    }
+
+    /* Setup driver buffer memory.  */
+    media_ptr -> fx_media_driver_buffer =  memory_ptr;
+
+    /* Move the buffer pointer into a local copy.  */
+    byte_ptr =  media_ptr -> fx_media_driver_buffer;
+
+    /* If the boundary unit is zero, set it to default value.  */
+    if (boundary_unit == 0)
+    {
+
+        /* Set the boundary unit to default value.  */
+        boundary_unit = EXFAT_DEFAULT_BOUNDARY_UNIT;
+    }
+
+    /* Recalculate FAT size/cluster heap offset according Incoming values.  */
+    _fx_utility_exFAT_size_calculate(bytes_per_sector,
+                                     boundary_unit,
+                                     total_sectors,
+                                     sectors_per_cluster,
+                                     &sectors_per_fat,
+                                     &fat_offset,
+                                     &cluster_heap_offset);
+
+    /* Fill Boot Sector fields.  */
+
+    /* Clear work buffer.  */
+    _fx_utility_memory_set(byte_ptr, 0x00, media_ptr -> fx_media_bytes_per_sector);
+
+    _fx_utility_memory_copy((UCHAR *)jump_boot, /* Use case of memcpy is verified. */
+                            &byte_ptr[FX_JUMP_INSTR],
+                            sizeof(jump_boot));
+
+    _fx_utility_memory_copy((UCHAR *)file_system_name, /* Use case of memcpy is verified. */
+                            &byte_ptr[FX_OEM_NAME],
+                            sizeof(file_system_name));
+
+    _fx_utility_64_unsigned_write(&byte_ptr[FX_EF_PARTITION_OFFSET],
+                                  hidden_sectors);
+
+    _fx_utility_64_unsigned_write(&byte_ptr[FX_EF_VOLUME_LENGTH],
+                                  total_sectors);
+
+    _fx_utility_32_unsigned_write(&byte_ptr[FX_EF_FAT_OFFSET],
+                                  fat_offset);
+
+    _fx_utility_32_unsigned_write(&byte_ptr[FX_EF_FAT_LENGTH],
+                                  sectors_per_fat);
+
+    _fx_utility_32_unsigned_write(&byte_ptr[FX_EF_CLUSTER_HEAP_OFFSET],
+                                  cluster_heap_offset);
+
+    /* Calculate total number of Clusters.  */
+    cluster_count = (ULONG)((total_sectors - cluster_heap_offset) /
+                            sectors_per_cluster);
+
+    _fx_utility_32_unsigned_write(&byte_ptr[FX_EF_CLUSTER_COUNT],
+                                  cluster_count);
+
+    _fx_utility_32_unsigned_write(&byte_ptr[FX_EF_VOLUME_SERIAL_NUMBER],
+                                  volume_serial_number);
+
+    _fx_utility_16_unsigned_write(&byte_ptr[FX_EF_FILE_SYSTEM_REVISION],
+                                  (USHORT)EXFAT_FAT_FILE_SYS_REVISION);
+
+    _fx_utility_16_unsigned_write(&byte_ptr[FX_EF_VOLUME_FLAGS],
+                                  (USHORT)EXFAT_FAT_VOLUME_FLAG);
+
+    /* Calculate Bytes Per Sector Shift value.  */
+    i = bytes_per_sector;
+    bytes_per_sector_shift = 0;
+
+    /* Loop to count the shift value. If the LSB is set, we got the shift value.  */
+    while (0 == (i & 0x01))
+    {
+
+        /* Add the shift value.  */
+        bytes_per_sector_shift++;
+
+        /* Right shift by 1 position.  */
+        i >>= 1;
+    }
+
+    byte_ptr[FX_EF_BYTE_PER_SECTOR_SHIFT] = (UCHAR)bytes_per_sector_shift;
+
+    /* Calculate Sector Per Cluster Shift value.  */
+    i = sectors_per_cluster;
+    sector_per_cluster_shift = 0;
+
+    /* Loop to count the shift value. If the LSB is set, we got the shift value.  */
+    while (0 == (i & 0x01))
+    {
+
+        /* Add the shift value.  */
+        sector_per_cluster_shift++;
+
+        /* Right shift by 1 position.  */
+        i >>= 1;
+    }
+
+    /* Write SectorsPerClusterShift, NumberOfFats, DriveSelect and PercentInUse fields.  */
+    byte_ptr[FX_EF_SECTOR_PER_CLUSTER_SHIFT] =  (UCHAR)sector_per_cluster_shift;
+    byte_ptr[FX_EF_NUMBER_OF_FATS] =            EXFAT_FAT_NUM_OF_FATS;
+    byte_ptr[FX_EF_DRIVE_SELECT]   =            EXFAT_FAT_DRIVE_SELECT;
+    byte_ptr[FX_EF_PERCENT_IN_USE] =            0;
+
+    /* Write Boot Sector Signature.  */
+    byte_ptr[FX_SIG_OFFSET + 0] = FX_SIG_BYTE_1;
+    byte_ptr[FX_SIG_OFFSET + 1] = FX_SIG_BYTE_2;
+
+    /* Calculate exFAT Bit Map and UpCase tables geometry
+       and first Cluster of Root Dir Entry.  */
+    bitmap_size_in_bytes = DIVIDE_TO_CEILING(cluster_count, BITS_PER_BYTE);
+
+    /* Calculate Bit Map Size in sectors.  */
+    bitmap_size_in_clusters = DIVIDE_TO_CEILING(bitmap_size_in_bytes, media_ptr -> fx_media_bytes_per_sector);
+
+    /* Calculate Bit Map size in clusters.  */
+    bitmap_size_in_clusters = DIVIDE_TO_CEILING(bitmap_size_in_clusters, sectors_per_cluster);
+
+    /* Calculate UpCase Table Size in bytes.  */
+    upcase_table_size_in_bytes = sizeof(_fx_utility_exFAT_upcase_table_compressed);
+
+    /* Calculate UpCase Table size sectors.  */
+    upcase_table_size_in_clusters = DIVIDE_TO_CEILING(upcase_table_size_in_bytes, media_ptr -> fx_media_bytes_per_sector);
+
+    /* Calculate UpCase size in clusters.  */
+    upcase_table_size_in_clusters = DIVIDE_TO_CEILING(upcase_table_size_in_clusters, sectors_per_cluster);
+
+    /* Determine first Root Dir Entry cluster.  */
+    root_dir_entry_first_cluster = (UINT)(bitmap_size_in_clusters +
+                                          upcase_table_size_in_clusters +
+                                          FX_FAT_ENTRY_START);
+
+    /* Determine the first sector for the root directory entry.  */
+    root_dir_entry_first_sector = cluster_heap_offset +
+        ((root_dir_entry_first_cluster - FX_FAT_ENTRY_START) <<
+                                 sector_per_cluster_shift);
+
+    /* Fill FirstClusterOfRootDirectory field.  */
+    _fx_utility_32_unsigned_write(&byte_ptr[FX_EF_FIRST_CLUSTER_OF_ROOT_DIR],
+                                  root_dir_entry_first_cluster);
+
+    /* Calculate Boot Sector checksum.  */
+    for (i = 0; i < media_ptr -> fx_media_bytes_per_sector; i++)
+    {
+
+        /* Skip VolumeFlags and PercentInUse fields.  */
+        if ((FX_EF_VOLUME_FLAGS     == i) ||
+            (FX_EF_VOLUME_FLAGS + 1 == i) ||
+            (FX_EF_PERCENT_IN_USE   == i))
+        {
+
+            /* Skip the current byte.  */
+            continue;
+        }
+
+        /* Calculate the checksum using the algorithm specified in the specification.  */
+        /* Right rotate the checksum by one bit position and add the data.  */
+        system_area_checksum = ((system_area_checksum >> 1) | (system_area_checksum << 31)) + (ULONG)byte_ptr[i];
+    }
+
+    /* Write Main Partition Boot sector.  */
+    _fx_utility_exFAT_system_sector_write(media_ptr, byte_ptr, 0, 1, FX_BOOT_SECTOR);
+
+    /* Determine if the write was successful.  */
+    if (FX_SUCCESS != media_ptr -> fx_media_driver_status)
+    {
+
+        /* Not successful. Return the error status.  */
+        return(media_ptr -> fx_media_driver_status);
+    }
+
+    /* Write BackUp Partition Boot sector.  */
+    _fx_utility_exFAT_system_sector_write(media_ptr, byte_ptr, FX_EXFAT_FAT_MAIN_SYSTEM_AREA_SIZE, 1, FX_BOOT_SECTOR);
+
+    /* Determine if the write was successful.  */
+    if (FX_SUCCESS != media_ptr -> fx_media_driver_status)
+    {
+
+        /* Not successful. Return the error status.  */
+        return(media_ptr -> fx_media_driver_status);
+    }
+
+    /* Format exFAT System Area.  */
+    status = _fx_utility_exFAT_system_area_format(media_ptr,
+                                                  boundary_unit,
+                                                  &system_area_checksum,
+                                                  memory_ptr,
+                                                  memory_size);
+    /* Check status.  */
+    if (status != FX_SUCCESS)
+    {
+
+        /* Not successful. Return the error status.  */
+        return(status);
+    }
+
+    /* Write System Area CheckSum.  */
+    status = _fx_utility_exFAT_system_area_checksum_write(media_ptr, byte_ptr, &system_area_checksum);
+
+    /* Determine if the operation was successful.  */
+    if (status != FX_SUCCESS)
+    {
+
+        /* Not successful. Return the error status.  */
+        return(status);
+    }
+
+    /* Format FAT table  */
+    _fx_utility_memory_set(byte_ptr, 0x00, media_ptr -> fx_media_bytes_per_sector);
+
+    /* Get the offset for the next available FAT entry after the initialized FAT entries.  */
+    offset = sizeof(fat_init_mask);
+
+    /* Copy the initial values for FAT table.  */
+    _fx_utility_memory_copy((UCHAR *)fat_init_mask, /* Use case of memcpy is verified. */
+                            byte_ptr,
+                            sizeof(fat_init_mask));
+
+    /* Set free cluster number.  */
+    i = FX_FAT_ENTRY_START;
+
+    /* Reset the sector offset used for sector writing.  */
+    sector_offset = 0;
+
+    /* Allocate clusters for BitMap Table.  */
+    for (cluster_count = 1; cluster_count < bitmap_size_in_clusters; cluster_count++)
+    {
+
+        /* Increase the next cluster number.  */
+        i++;
+
+        /* Fill the FAT entry.  */
+        _fx_utility_32_unsigned_write(&byte_ptr[offset], i);
+
+        /* Move to next FAT entry.  */
+        offset += sizeof(ULONG);
+
+        /* Check if we reach the sector end.  */
+        if (offset == bytes_per_sector)
+        {
+
+            /* Write the sector out.  */
+            status = _fx_utility_exFAT_system_sector_write(media_ptr, byte_ptr,
+                                                           fat_offset + sector_offset,
+                                                           1, FX_FAT_SECTOR);
+
+            /* Determine if the operation was successful.  */
+            if (status != FX_SUCCESS)
+            {
+                return(status);
+            }
+
+            /* Go back to the sector buffer head.  */
+            offset = 0;
+
+            /* Move to next sector.  */
+            sector_offset++;
+        }
+    }
+
+    /* Mark as last cluster.  */
+    _fx_utility_32_unsigned_write(&byte_ptr[offset],
+                                  EXFAT_LAST_CLUSTER_MASK);
+
+    /* Move to next cluster.  */
+    i++;
+    offset += sizeof(ULONG);
+
+    /* Check if we reach the sector end.  */
+    if (offset == bytes_per_sector)
+    {
+
+        /* Write the sector out.  */
+        status = _fx_utility_exFAT_system_sector_write(media_ptr, byte_ptr,
+                                                       fat_offset + sector_offset,
+                                                       1, FX_FAT_SECTOR);
+
+        /* Determine if the write was successful.  */
+        if (status != FX_SUCCESS)
+        {
+
+            /* Not successful. Return the error status.  */
+            return(status);
+        }
+
+        /* Go back to the sector buffer head.  */
+        offset = 0;
+        sector_offset++;
+    }
+
+    /* Allocate clusters for UpCase Table.  */
+    for (cluster_count = 1; cluster_count < upcase_table_size_in_clusters; cluster_count++)
+    {
+
+        /* Increase the next cluster number.  */
+        i++;
+
+        /* Fill the FAT entry.  */
+        _fx_utility_32_unsigned_write(&byte_ptr[offset], i);
+
+        /* Move to next FAT entry.  */
+        offset += sizeof(ULONG);
+
+        /* Check if we reach the sector end.  */
+        if (offset == bytes_per_sector)
+        {
+
+            /* Write the sector out.  */
+            status = _fx_utility_exFAT_system_sector_write(media_ptr, byte_ptr,
+                                                           fat_offset + sector_offset,
+                                                           1, FX_FAT_SECTOR);
+
+            /* Determine if the write was successful.  */
+            if (status != FX_SUCCESS)
+            {
+
+                /* Not successful. Return the error status.  */
+                return(status);
+            }
+
+            /* Go back to the sector buffer head.  */
+            offset = 0;
+            sector_offset++;
+        }
+    }
+
+    /* Mark as last cluster.  */
+    _fx_utility_32_unsigned_write(&byte_ptr[offset],
+                                  EXFAT_LAST_CLUSTER_MASK);
+
+    /* Move to next FAT entry.  */
+    offset += sizeof(ULONG);
+
+    /* Check if we reach the sector end.  */
+    if (offset == bytes_per_sector)
+    {
+
+        /* Write the sector out.  */
+        status = _fx_utility_exFAT_system_sector_write(media_ptr, byte_ptr,
+                                                       fat_offset + sector_offset,
+                                                       1, FX_FAT_SECTOR);
+
+        /* Determine if the write was successful.  */
+        if (status != FX_SUCCESS)
+        {
+
+            /* Not successful. Return the error status.  */
+            return(status);
+        }
+
+        /* Go back to the sector buffer head.  */
+        offset = 0;
+        sector_offset++;
+    }
+
+    /* Allocate cluster for RootDir Entry.  */
+    _fx_utility_32_unsigned_write(&byte_ptr[offset],
+                                  EXFAT_LAST_CLUSTER_MASK);
+
+    /* Write the sector out.  */
+    status = _fx_utility_exFAT_system_sector_write(media_ptr, byte_ptr,
+                                                   fat_offset + sector_offset,
+                                                   1, FX_FAT_SECTOR);
+
+    /* Determine if the write was successful.  */
+    if (status != FX_SUCCESS)
+    {
+
+        /* Not successful. Return the error status.  */
+        return(status);
+    }
+
+    /* Format Bit Map Table.  */
+    sector_offset = 0;
+    offset = 0;
+
+    /* Check if the bitmap has sectors with all set bits.  */
+    if ((root_dir_entry_first_cluster - 1) / 8 >= bytes_per_sector)
+    {
+
+        /* Fill the buffer with one.  */
+        _fx_utility_memory_set(byte_ptr, 0xFF, media_ptr -> fx_media_bytes_per_sector);
+
+        /* Loop to write all the secotrs with all set bits.  */
+        for (i = ((root_dir_entry_first_cluster - 1) / 8) % bytes_per_sector; i; i--)
+        {
+
+            /* Write out the bitmap sector.  */
+            status = _fx_utility_exFAT_system_sector_write(media_ptr, byte_ptr,
+                                                           cluster_heap_offset + sector_offset,
+                                                           1, FX_FAT_SECTOR);
+
+            /* Determine if the write was successful.  */
+            if (status != FX_SUCCESS)
+            {
+
+                /* Not successful. Return the error status.  */
+                return(status);
+            }
+
+            /* Move to next sector.  */
+            sector_offset++;
+        }
+    }
+
+    /* Loop to mark already occupied clusters in 8 clusters size.  */
+    for (i = ((root_dir_entry_first_cluster - 1) / 8) % bytes_per_sector; i; i--)
+    {
+
+        /* Write the byte with all set bits.  */
+        byte_ptr[offset++] = 0xFF;
+    }
+
+    /* Clear all the remaining bytes.  */
+    _fx_utility_memory_set(byte_ptr + offset, 0x00, media_ptr -> fx_media_bytes_per_sector - offset);
+
+    /* Loop to set the remaining bits.  */
+    for (i = (root_dir_entry_first_cluster - 1) % 8; i; i--)
+    {
+
+        byte_ptr[offset] = (UCHAR)((byte_ptr[offset] << 1) | 0x1);
+    }
+
+    /* Write out the bitmap sector.  */
+    status = _fx_utility_exFAT_system_sector_write(media_ptr, byte_ptr,
+                                                   cluster_heap_offset + sector_offset,
+                                                   1, FX_FAT_SECTOR);
+
+    /* Determine if the write was successful.  */
+    if (status != FX_SUCCESS)
+    {
+
+        /* Not successful. Return the error status.  */
+        return(status);
+    }
+
+    /* Move to next sector.  */
+    sector_offset++;
+
+    /* Fill the remaining bitmap with zeros.  */
+    if ((bitmap_size_in_clusters << sector_per_cluster_shift) > sector_offset)
+    {
+
+        /* Fill the sector buffer with zero.  */
+        _fx_utility_memory_set(byte_ptr, 0x00, media_ptr -> fx_media_bytes_per_sector);
+
+        /* Loop to write all the remaining bitmap sectors.  */
+        for (i = (bitmap_size_in_clusters << sector_per_cluster_shift) - sector_offset; i; i--)
+        {
+
+            /* Write out the bitmap sector.  */
+            status = _fx_utility_exFAT_system_sector_write(media_ptr, byte_ptr,
+                                                           cluster_heap_offset + sector_offset,
+                                                           1, FX_FAT_SECTOR);
+
+            /* Determine if the write was successful.  */
+            if (status != FX_SUCCESS)
+            {
+
+                /* Not successful. Return the error status.  */
+                return(status);
+            }
+
+            sector_offset++;
+        }
+    }
+
+    /* Write the  upcase table that fits in sector size.  */
+    status = _fx_utility_exFAT_system_sector_write(media_ptr, (UCHAR *)_fx_utility_exFAT_upcase_table_compressed,
+                                                   cluster_heap_offset + (bitmap_size_in_clusters << sector_per_cluster_shift),
+                                                   sizeof(_fx_utility_exFAT_upcase_table_compressed) / media_ptr -> fx_media_bytes_per_sector,
+                                                   FX_DATA_SECTOR);
+
+    /* Determine if the write was successful.  */
+    if (status != FX_SUCCESS)
+    {
+
+        /* Not successful. Return the error status.  */
+        return(status);
+    }
+
+    /* Write the remaining upcase table bytes.  */
+    i = sizeof(_fx_utility_exFAT_upcase_table_compressed) % media_ptr -> fx_media_bytes_per_sector;
+    if (i != 0)
+    {
+
+        /* Clear the sector buffer.  */
+        _fx_utility_memory_set(byte_ptr, 0x00, media_ptr -> fx_media_bytes_per_sector);
+
+        /* Copy the remaining bytes.  */
+        _fx_utility_memory_copy((UCHAR *)_fx_utility_exFAT_upcase_table_compressed + sizeof(_fx_utility_exFAT_upcase_table_compressed) - i, byte_ptr, i); /* Use case of memcpy is verified. */
+
+        /* Write out the sector.  */
+        status = _fx_utility_exFAT_system_sector_write(media_ptr, byte_ptr,
+                                                       cluster_heap_offset + (bitmap_size_in_clusters << sector_per_cluster_shift) + sizeof(_fx_utility_exFAT_upcase_table_compressed) / media_ptr -> fx_media_bytes_per_sector,
+                                                       1, FX_DATA_SECTOR);
+
+        /* Determine if the write was successful.  */
+        if (status != FX_SUCCESS)
+        {
+
+            /* Not successful. Return the error status.  */
+            return(status);
+        }
+    }
+
+    /* Format Dir Entry.  */
+
+    /* Clear work buffer.  */
+    _fx_utility_memory_set(byte_ptr, 0x00, media_ptr -> fx_media_bytes_per_sector);
+
+    /* Create Volume Label Dir Entry. This is a first entry.  */
+    byte_ptr[FX_EXFAT_DIR_ENTRY_SIZE * 0 + FX_EXFAT_ENTRY_TYPE] = FX_EXFAT_DIR_ENTRY_TYPE_VOLUME_LABEL;
+
+    /* Copy volume label.  */
+    for (i = 0; i < EXFAT_FAT_VOLUME_NAME_FIELD_SIZE; i++)
+    {
+
+        /* Check for end of Label Name.  */
+        if (0 == volume_name[i])
+        {
+            break;
+        }
+
+        /* Store one character.  */
+        _fx_utility_16_unsigned_write(&byte_ptr[FX_EXFAT_DIR_ENTRY_SIZE * 0 + FX_EXFAT_VOLUME_LABEL + i * 2], (UINT)volume_name[i]);
+    }
+
+    byte_ptr[FX_EXFAT_DIR_ENTRY_SIZE * 0 + FX_EXFAT_CHAR_COUNT] = (UCHAR)i;
+
+    /* Create Allocated BitMap Dir Entry.  */
+    byte_ptr[FX_EXFAT_DIR_ENTRY_SIZE * 1 + FX_EXFAT_ENTRY_TYPE] = FX_EXFAT_DIR_ENTRY_TYPE_ALLOCATION_BITMAP;
+    byte_ptr[FX_EXFAT_DIR_ENTRY_SIZE * 1 + FX_EXFAT_BIT_MAP_FLAGS] = EXFAT_BIT_MAP_FIRST_TABLE;
+
+    _fx_utility_32_unsigned_write(&byte_ptr[FX_EXFAT_DIR_ENTRY_SIZE * 1 + FX_EXFAT_FIRST_CLUSTER],
+                                  FX_FAT_ENTRY_START);
+
+    _fx_utility_32_unsigned_write(&byte_ptr[FX_EXFAT_DIR_ENTRY_SIZE * 1 + FX_EXFAT_DATA_LENGTH],
+                                  bitmap_size_in_bytes);
+
+    /* Create UpCase Table Dir Entry.  */
+    byte_ptr[FX_EXFAT_DIR_ENTRY_SIZE * 2 + FX_EXFAT_ENTRY_TYPE] = FX_EXFAT_DIR_ENTRY_TYPE_UP_CASE_TABLE;
+
+    /* Loop to calculate Compressed UpCase table Check Sum.  */
+    for (i = 0; i < sizeof(_fx_utility_exFAT_upcase_table_compressed); i++)
+    {
+
+        /* Calculate the checksum using the algorithm specified in the specification.  */
+        /* Right rotate the checksum by one bit position and add the data.  */
+        upcase_table_checksum = ((upcase_table_checksum >> 1) | (upcase_table_checksum << 31)) +
+            (ULONG)_fx_utility_exFAT_upcase_table_compressed[i];
+    }
+
+    /* Fill the checksum field.  */
+    _fx_utility_32_unsigned_write(&byte_ptr[FX_EXFAT_DIR_ENTRY_SIZE * 2 + FX_EXFAT_UP_CASE_TABLE_CHECK_SUM],
+                                  upcase_table_checksum);
+
+    /* Fill the first cluster field.  */
+    _fx_utility_32_unsigned_write(&byte_ptr[FX_EXFAT_DIR_ENTRY_SIZE * 2 + FX_EXFAT_FIRST_CLUSTER],
+                                  FX_FAT_ENTRY_START + bitmap_size_in_clusters);
+
+    /* Fill the data length field.  */
+    _fx_utility_32_unsigned_write(&byte_ptr[FX_EXFAT_DIR_ENTRY_SIZE * 2 + FX_EXFAT_DATA_LENGTH],
+                                  upcase_table_size_in_bytes);
+
+    /* Write the directory entry.  */
+    status = _fx_utility_exFAT_system_sector_write(media_ptr, byte_ptr,
+                                                   root_dir_entry_first_sector,
+                                                   1, FX_BOOT_SECTOR);
+
+    /* Determine if the write was successful.  */
+    if (status != FX_SUCCESS)
+    {
+
+        /* Not successful. Return the error status.  */
+        return(status);
+    }
+
+    /* Clear the secotr buffer.  */
+    _fx_utility_memory_set(byte_ptr, 0x00, media_ptr -> fx_media_bytes_per_sector);
+
+    /* Loop to clear the remaining root directory sectors.  */
+    for (i = 1; i < sectors_per_cluster; i++)
+    {
+
+        /* Write the directory entry sector.  */
+        status = _fx_utility_exFAT_system_sector_write(media_ptr, byte_ptr,
+                                                       root_dir_entry_first_sector + i,
+                                                       1, FX_BOOT_SECTOR);
+
+        /* Determine if the write was successful.  */
+        if (status != FX_SUCCESS)
+        {
+
+            /* Not successful. Return the error status.  */
+            return(status);
+        }
+    }
+
+    /* Build the "uninitialize" I/O driver request.  */
+    media_ptr -> fx_media_driver_request =      FX_DRIVER_UNINIT;
+    media_ptr -> fx_media_driver_status =       FX_IO_ERROR;
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_UNINIT, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+    /* Call the specified I/O driver with the uninitialize request.  */
+    (media_ptr -> fx_media_driver_entry) (media_ptr);
+
+    return(media_ptr -> fx_media_driver_status);
+}
+
+#endif /* FX_ENABLE_EXFAT */
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_extended_space_available.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_extended_space_available.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_extended_space_available.c	(revision 30)
@@ -0,0 +1,115 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_media.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_media_extended_space_available                  PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function returns the number of bytes available in the          */
+/*    specified media.                                                    */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    available_bytes_ptr                   Pointer to available bytes    */
+/*                                            destination                 */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_media_extended_space_available(FX_MEDIA *media_ptr, ULONG64 *available_bytes_ptr)
+{
+
+ULONG64 available_bytes;
+ULONG   bytes_per_cluster;
+ULONG   available_clusters;
+
+
+    /* Check the media to make sure it is open.  */
+    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
+    {
+
+        /* Return the media not opened error.  */
+        return(FX_MEDIA_NOT_OPEN);
+    }
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_MEDIA_SPACE_AVAILABLE, media_ptr, available_bytes_ptr, media_ptr -> fx_media_available_clusters, 0, FX_TRACE_MEDIA_EVENTS, 0, 0)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+    /* Pickup the number of free clusters.  */
+    available_clusters =  media_ptr -> fx_media_available_clusters;
+
+    /* Derive the bytes per cluster.  */
+    bytes_per_cluster =  media_ptr -> fx_media_bytes_per_sector * media_ptr -> fx_media_sectors_per_cluster;
+
+    /* Calculate the free space.  */
+    available_bytes =  ((ULONG64)available_clusters) * ((ULONG64)bytes_per_cluster);
+
+    /* Return the value.  */
+    *available_bytes_ptr =  available_bytes;
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* Return a successful status to the caller.  */
+    return(FX_SUCCESS);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_flush.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_flush.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_flush.c	(revision 30)
@@ -0,0 +1,373 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_media.h"
+#include "fx_file.h"
+#include "fx_directory.h"
+#include "fx_utility.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_media_flush                                     PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function examines the list of open files for this media and    */
+/*    "flushes" each written open file to the underlying media.  After    */
+/*    the open files have been flushed, the internal logical sector is    */
+/*    flushed.  Finally, the attached driver is sent a flush command so   */
+/*    that it can flush its sector cache (if any) to the media.           */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_entry_write             Write the directory entry     */
+/*    _fx_utility_FAT_flush                 Flush cached FAT entries      */
+/*    _fx_utility_FAT_map_flush             Flush primary FAT changes to  */
+/*                                            secondary FAT(s)            */
+/*    _fx_utility_logical_sector_flush      Flush logical sector cache    */
+/*    _fx_utility_32_unsigned_read          Read 32-bit unsigned          */
+/*    _fx_utility_32_unsigned_write         Write 32-bit unsigned         */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s), and      */
+/*                                            added conditional to        */
+/*                                            disable cache,              */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_media_flush(FX_MEDIA  *media_ptr)
+{
+
+UINT     status;
+ULONG    open_count;
+FX_FILE *file_ptr;
+FX_INT_SAVE_AREA
+
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of times this service has been called.  */
+    media_ptr -> fx_media_flushes++;
+#endif
+
+    /* Check the media to make sure it is open.  */
+    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
+    {
+
+        /* Return the media not opened error.  */
+        return(FX_MEDIA_NOT_OPEN);
+    }
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_MEDIA_FLUSH, media_ptr, 0, 0, 0, FX_TRACE_MEDIA_EVENTS, 0, 0)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+    /* Check for write protect at the media level (set by driver).  */
+    if (media_ptr -> fx_media_driver_write_protect)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return write protect error.  */
+        return(FX_WRITE_PROTECT);
+    }
+
+    /* Loop through the media's open files.  */
+    open_count =  media_ptr -> fx_media_opened_file_count;
+    file_ptr =    media_ptr -> fx_media_opened_file_list;
+    while (open_count)
+    {
+
+        /* Look at each opened file to see if the same file is opened
+           for writing and has been written to.  */
+        if ((file_ptr -> fx_file_open_mode == FX_OPEN_FOR_WRITE) &&
+            (file_ptr -> fx_file_modified))
+        {
+
+            /* Protect against update.  */
+            FX_DISABLE_INTS
+
+            /* Set the new time and date.  */
+            file_ptr -> fx_file_dir_entry.fx_dir_entry_time =  _fx_system_time;
+            file_ptr -> fx_file_dir_entry.fx_dir_entry_date =  _fx_system_date;
+
+            /* Restore interrupts.  */
+            FX_RESTORE_INTS
+
+            /* Copy the new file size into the directory entry.  */
+            file_ptr -> fx_file_dir_entry.fx_dir_entry_file_size =
+                file_ptr -> fx_file_current_file_size;
+
+            /* Write the directory entry to the media.  */
+#ifdef FX_ENABLE_EXFAT
+            if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+            {
+                status = _fx_directory_exFAT_entry_write(
+                        media_ptr, &(file_ptr -> fx_file_dir_entry), UPDATE_STREAM);
+            }
+            else
+            {
+#endif /* FX_ENABLE_EXFAT */
+                status = _fx_directory_entry_write(media_ptr, &(file_ptr -> fx_file_dir_entry));
+#ifdef FX_ENABLE_EXFAT
+            }
+#endif /* FX_ENABLE_EXFAT */
+
+            /* Check for a good status.  */
+            if (status != FX_SUCCESS)
+            {
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* Error writing the directory.  */
+                return(status);
+            }
+
+            /* Clear the file modified flag.  */
+            file_ptr -> fx_file_modified =  FX_FALSE;
+        }
+
+        /* Adjust the pointer and decrement the opened count.  */
+        file_ptr =  file_ptr -> fx_file_opened_next;
+        open_count--;
+    }
+
+    /* Flush the cached individual FAT entries */
+    _fx_utility_FAT_flush(media_ptr);
+
+    /* Flush changed sector(s) in the primary FAT to secondary FATs.  */
+    _fx_utility_FAT_map_flush(media_ptr);
+
+#ifdef FX_ENABLE_EXFAT
+    if ((media_ptr -> fx_media_FAT_type == FX_exFAT) &&
+        (FX_TRUE == media_ptr -> fx_media_exfat_bitmap_cache_dirty))
+    {
+
+        /* Flush bitmap.  */
+        _fx_utility_exFAT_bitmap_flush(media_ptr);
+    }
+#endif /* FX_ENABLE_EXFAT */
+
+    /* Flush the internal logical sector cache.  */
+    status =  _fx_utility_logical_sector_flush(media_ptr, ((ULONG64) 1), (ULONG64) (media_ptr -> fx_media_total_sectors), FX_FALSE);
+
+    /* Check for a good status.  */
+    if (status != FX_SUCCESS)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Error writing the directory.  */
+        return(status);
+    }
+
+    /* Determine if the media needs to have the additional information sector updated. This will
+       only be the case for 32-bit FATs. The logic here only needs to be done if the last reported
+       available cluster count is different that the currently available clusters.  */
+    if ((media_ptr -> fx_media_FAT32_additional_info_sector) &&
+        (media_ptr -> fx_media_FAT32_additional_info_last_available != media_ptr -> fx_media_available_clusters))
+    {
+
+    UCHAR *buffer_ptr;
+    ULONG  signature;
+
+#ifndef FX_DISABLE_CACHE
+
+        /* Setup a pointer to the first cached entry's buffer.  */
+        buffer_ptr =  (media_ptr -> fx_media_sector_cache_list_ptr) -> fx_cached_sector_memory_buffer;
+
+        /* Invalidate this cache entry.  */
+        (media_ptr -> fx_media_sector_cache_list_ptr) -> fx_cached_sector =  (~(ULONG64)0);
+        (media_ptr -> fx_media_sector_cache_list_ptr) -> fx_cached_sector_valid =  FX_FALSE;
+#else
+        buffer_ptr =  media_ptr -> fx_media_memory_buffer;
+#endif /* FX_DISABLE_CACHE */
+
+        /* Read the FAT32 additional information sector from the device.  */
+        media_ptr -> fx_media_driver_request =          FX_DRIVER_READ;
+        media_ptr -> fx_media_driver_status =           FX_IO_ERROR;
+        media_ptr -> fx_media_driver_buffer =           buffer_ptr;
+        media_ptr -> fx_media_driver_logical_sector =   media_ptr -> fx_media_FAT32_additional_info_sector;
+        media_ptr -> fx_media_driver_sectors =          1;
+        media_ptr -> fx_media_driver_sector_type =      FX_DIRECTORY_SECTOR;
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+        /* Increment the number of driver read sector(s) requests.  */
+        media_ptr -> fx_media_driver_read_requests++;
+#endif
+
+        /* If trace is enabled, insert this event into the trace buffer.  */
+        FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_READ, media_ptr, media_ptr -> fx_media_FAT32_additional_info_sector, 1, buffer_ptr, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+        /* Invoke the driver to read the FAT32 additional information sector.  */
+        (media_ptr -> fx_media_driver_entry) (media_ptr);
+
+        /* Determine if the FAT32 sector was read correctly. */
+        if (media_ptr -> fx_media_driver_status != FX_SUCCESS)
+        {
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* Return the error status.  */
+            return(FX_IO_ERROR);
+        }
+
+        /* Setup a pointer into the FAT32 additional information sector.  */
+        buffer_ptr =  media_ptr -> fx_media_driver_buffer;
+
+        /* Pickup the first signature long word.  */
+        signature =  _fx_utility_32_unsigned_read(&buffer_ptr[0]);
+
+        /* Determine if the signature is correct.  */
+        if (signature == 0x41615252)
+        {
+
+            /* Yes, the first signature is correct, now pickup the next signature.  */
+            signature =  _fx_utility_32_unsigned_read(&buffer_ptr[484]);
+
+            /* Determine if this signature is correct.  */
+            if (signature == 0x61417272)
+            {
+
+                /* Yes, we have a good FAT32 additional information sector.  */
+
+                /* Set the free cluster count to the available clusters in the media control block.  */
+                _fx_utility_32_unsigned_write(&buffer_ptr[488], media_ptr -> fx_media_available_clusters);
+
+                /* Set the next free cluster number hint to starting search cluster in the media control block.  */
+                _fx_utility_32_unsigned_write(&buffer_ptr[492], media_ptr -> fx_media_cluster_search_start);
+
+                /* Now write the sector back out to the media.  */
+                media_ptr -> fx_media_driver_request =          FX_DRIVER_WRITE;
+                media_ptr -> fx_media_driver_status =           FX_IO_ERROR;
+                media_ptr -> fx_media_driver_buffer =           buffer_ptr;
+                media_ptr -> fx_media_driver_logical_sector =   media_ptr -> fx_media_FAT32_additional_info_sector;
+                media_ptr -> fx_media_driver_sectors =          1;
+                media_ptr -> fx_media_driver_sector_type =      FX_DIRECTORY_SECTOR;
+
+                /* Set the system write flag since we are writing a directory sector.  */
+                media_ptr -> fx_media_driver_system_write =  FX_TRUE;
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+                /* Increment the number of driver write sector(s) requests.  */
+                media_ptr -> fx_media_driver_write_requests++;
+#endif
+
+                /* If trace is enabled, insert this event into the trace buffer.  */
+                FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_WRITE, media_ptr, media_ptr -> fx_media_FAT32_additional_info_sector, 1, buffer_ptr, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+                /* Invoke the driver to write the FAT32 additional information sector.  */
+                (media_ptr -> fx_media_driver_entry) (media_ptr);
+
+                /* Clear the system write flag.  */
+                media_ptr -> fx_media_driver_system_write =  FX_FALSE;
+
+                /* Determine if the FAT32 sector was written correctly. */
+                if (media_ptr -> fx_media_driver_status != FX_SUCCESS)
+                {
+
+                    /* Release media protection.  */
+                    FX_UNPROTECT
+
+                    /* Return the sector IO error status.  */
+                    return(FX_IO_ERROR);
+                }
+
+                /* Successful update of the FAT32 additional information sector. Update the
+                   last written available cluster count.  */
+                media_ptr -> fx_media_FAT32_additional_info_last_available =  media_ptr -> fx_media_available_clusters;
+            }
+        }
+    }
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of driver flush requests.  */
+    media_ptr -> fx_media_driver_flush_requests++;
+#endif
+
+    /* Build the "flush" I/O driver request.  */
+    media_ptr -> fx_media_driver_request =      FX_DRIVER_FLUSH;
+    media_ptr -> fx_media_driver_status =       FX_IO_ERROR;
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_FLUSH, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+    /* Call the specified I/O driver with the flush request.  */
+    (media_ptr -> fx_media_driver_entry) (media_ptr);
+
+    /* Determine if the I/O driver flushed successfully.  */
+    if (media_ptr -> fx_media_driver_status != FX_SUCCESS)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the driver error status.  */
+        return(FX_IO_ERROR);
+    }
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* If we get here, return successful status to the caller.  */
+    return(FX_SUCCESS);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_format.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_format.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_format.c	(revision 30)
@@ -0,0 +1,695 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_media.h"
+#include "fx_utility.h"
+
+
+/* Define global variables necessary for formatting.  */
+
+/* Define OEM Name. This name must be 8 characters long and be blank padded.
+   The default may be changed by modifying this file or calling the
+   fx_media_format_oem_name_set utility prior to calling fx_media_format.  */
+
+UCHAR   _fx_media_format_oem_name[8] = "EL FILEX";
+
+
+/* Define the default media type.  This default may be changed by modifying
+   this file or calling the fx_media_format_type_set utility prior to calling
+   fx_media_format.  */
+
+UCHAR _fx_media_format_media_type =  0xF8;
+
+
+/* Define the default volume ID.  This default may be changed by modifying
+   this file or calling the fx_media_format_volume_id_set utility prior to calling
+   fx_media_format.  */
+
+ULONG _fx_media_format_volume_id =  1;
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_media_format                                    PORTABLE C      */
+/*                                                           6.1.11       */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function creates a FAT12/16/32 format with raw calls to the    */
+/*    I/O driver. It can and must be called before the fx_media_open      */
+/*    and is designed to utilize the same underlying FileX driver.        */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Pointer to media control block*/
+/*                                            (does not need to be opened)*/
+/*    driver                                Pointer to FileX driver (must */
+/*                                            be able to field requests   */
+/*                                            prior to opening)           */
+/*    driver_info_ptr                       Optional information pointer  */
+/*    memory_ptr                            Pointer to memory used by the */
+/*                                            FileX for this media.       */
+/*    memory_size                           Size of media memory - must   */
+/*                                            at least 512 bytes and      */
+/*                                            one sector size.            */
+/*    volume_name                           Name of the volume            */
+/*    number_of_fats                        Number of FAT tables          */
+/*    directory_entries                     Number of directory entries   */
+/*    hidden_sectors                        Number of hidden sectors      */
+/*    total_sectors                         Total number of sectors       */
+/*    bytes_per_sector                      Number of bytes per sector    */
+/*    sectors_per_cluster                   Number of sectors per cluster */
+/*    heads                                 Number of heads               */
+/*    sectors_per_track                     Number of sectors per track   */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    Completion Status                                                   */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    Media driver                                                        */
+/*    _fx_utility_16_unsigned_write         Write 16-bit unsigned         */
+/*    _fx_utility_32_unsigned_write         Write 32-bit unsigned         */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s), and      */
+/*                                            added conditional to        */
+/*                                            disable force memset,       */
+/*                                            resulting in version 6.1    */
+/*  03-02-2021     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1.5  */
+/*  08-02-2021     Bhupendra Naphade        Modified comment(s), and      */
+/*                                            updated boot write logic,   */
+/*                                            resulting in version 6.1.8  */
+/*  04-25-2022     Bhupendra Naphade        Modified comment(s), and      */
+/*                                            updated reserved FAT entry  */
+/*                                            value,                      */
+/*                                            resulting in version 6.1.11 */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_media_format(FX_MEDIA *media_ptr, VOID (*driver)(FX_MEDIA *media), VOID *driver_info_ptr, UCHAR *memory_ptr, UINT memory_size,
+                       CHAR *volume_name, UINT number_of_fats, UINT directory_entries, UINT hidden_sectors,
+                       ULONG total_sectors, UINT bytes_per_sector, UINT sectors_per_cluster,
+                       UINT heads, UINT sectors_per_track)
+{
+
+UCHAR *byte_ptr;
+UINT   reserved_sectors, i, j, root_sectors, total_clusters, bytes_needed;
+UINT   sectors_per_fat, f, s;
+
+
+    /* Create & write bootrecord from drive geometry information.  */
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_MEDIA_FORMAT, media_ptr, directory_entries, total_sectors, sectors_per_cluster, FX_TRACE_MEDIA_EVENTS, 0, 0)
+
+    /* Validate bytes per sector value: greater than zero and no more than 4096.  */
+    if((bytes_per_sector == 0) || (bytes_per_sector > 4096))
+        return(FX_SECTOR_INVALID);
+
+    /* Validate sectors per cluster value: greater than zero and no more than 128.  */
+    if((sectors_per_cluster == 0) || (sectors_per_cluster > 128))
+        return(FX_SECTOR_INVALID);
+
+    /* Setup driver pointer and memory information.  */
+    media_ptr -> fx_media_driver_entry =                driver;
+    media_ptr -> fx_media_memory_buffer =               (UCHAR *)memory_ptr;
+    media_ptr -> fx_media_memory_size =                 memory_size;
+
+    /* Store geometry information in media record - driver needs this.  */
+    media_ptr -> fx_media_bytes_per_sector =            bytes_per_sector;
+    media_ptr -> fx_media_sectors_per_track =           sectors_per_track;
+    media_ptr -> fx_media_heads =                       heads;
+    media_ptr -> fx_media_hidden_sectors =              hidden_sectors;
+
+    /* Initialize the supplied media I/O driver.  First, build the
+       initialize driver request.  */
+    media_ptr -> fx_media_driver_request =              FX_DRIVER_INIT;
+    media_ptr -> fx_media_driver_status =               FX_IO_ERROR;
+    media_ptr -> fx_media_driver_info =                 driver_info_ptr;
+    media_ptr -> fx_media_driver_write_protect =        FX_FALSE;
+    media_ptr -> fx_media_driver_free_sector_update =   FX_FALSE;
+    media_ptr -> fx_media_driver_data_sector_read =     FX_FALSE;
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_INIT, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+    /* Call the specified I/O driver with the initialize request.  */
+    (media_ptr -> fx_media_driver_entry) (media_ptr);
+
+    /* Determine if the I/O driver initialized successfully.  */
+    if (media_ptr -> fx_media_driver_status != FX_SUCCESS)
+    {
+
+        /* Return the driver error status.  */
+        return(FX_IO_ERROR);
+    }
+
+    /* Setup driver buffer memory.  */
+    media_ptr -> fx_media_driver_buffer =  memory_ptr;
+
+    /* Move the buffer pointer into a local copy.  */
+    byte_ptr =  media_ptr -> fx_media_driver_buffer;
+
+#ifndef FX_DISABLE_FORCE_MEMORY_OPERATION
+    /* Clear the buffer record out, assuming it is large enough for one sector.   */
+    for (i = 0; i < bytes_per_sector; i++)
+    {
+
+        /* Clear each byte of the boot record.  */
+        byte_ptr[i] =  (UCHAR)0;
+    }
+#else
+    _fx_utility_memory_set(byte_ptr, 0, bytes_per_sector);
+#endif /* FX_DISABLE_FORCE_MEMORY_OPERATION */
+
+    /* Set jump instruction at the beginning of the sector.  */
+    byte_ptr[0] =  (UCHAR)0xEB;
+    byte_ptr[1] =  (UCHAR)0x34;
+    byte_ptr[2] =  (UCHAR)0x90;
+
+    /* Set the OEM name in the boot record.  */
+    for (i = 0; i < 8; i++)
+    {
+
+        /* Copy a character from the OEM name.  */
+        byte_ptr[i + 3] =  _fx_media_format_oem_name[i];
+    }
+
+    /* Set the media type in the boot record.  */
+    byte_ptr[FX_MEDIA_TYPE] =  _fx_media_format_media_type;
+
+    /* Set the number of bytes per sector.  */
+    _fx_utility_16_unsigned_write(&byte_ptr[FX_BYTES_SECTOR], bytes_per_sector);
+
+    /* Set the number of sectors per track.  */
+    _fx_utility_16_unsigned_write(&byte_ptr[FX_SECTORS_PER_TRK], sectors_per_track);
+
+    /* Set the number of heads.  */
+    _fx_utility_16_unsigned_write(&byte_ptr[FX_HEADS], heads);
+
+#ifdef FX_FORCE_512_BYTE_BOOT_SECTOR
+
+    /* Calculate the number of reserved sectors. If sector size is smaller than 512 bytes, there will be
+       reserved sectors, otherwise assumed that only the sector containing bootrecord is reserved.  */
+    if (bytes_per_sector < 512)
+    {
+        reserved_sectors =  512 / bytes_per_sector;
+    }
+    else
+    {
+        reserved_sectors =  1;
+    }
+#else
+
+    /* The boot sector is the only reserved sector.  */
+    reserved_sectors =  1;
+#endif
+
+
+    /* Calculate the maximum clusters.... This is actually greater than the actual since the FAT
+       sectors have yet to be accounted for.  */
+    total_clusters =  (total_sectors - reserved_sectors - ((directory_entries * FX_DIR_ENTRY_SIZE) + (bytes_per_sector - 1)) / bytes_per_sector) / sectors_per_cluster;
+
+    /* Calculate the maximum number of FAT sectors necessary for FAT12.  */
+    if (total_clusters % 2)
+    {
+        bytes_needed = (total_clusters + total_clusters / 2) + 1;
+    }
+    else
+    {
+        bytes_needed = (total_clusters + total_clusters / 2);
+    }
+    sectors_per_fat =  bytes_needed / bytes_per_sector;
+    if (bytes_needed % bytes_per_sector)
+    {
+        sectors_per_fat++;
+    }
+
+    /* Now adjust the total clusters by the number of sectors per FAT.  */
+    total_clusters =  total_clusters - ((sectors_per_fat * number_of_fats) + (sectors_per_cluster - 1)) / sectors_per_cluster;
+
+    /* Is the total cluster count greater than the FAT12 maximum?  */
+    if (total_clusters >= FX_12_BIT_FAT_SIZE)
+    {
+
+        /* Yes, too big for FAT12, we need to evaluate for FAT16.  */
+
+        /* Reset the maximum clusters.... This is actually greater than the actual since the FAT
+           sectors have yet to be accounted for.  */
+        total_clusters =  (total_sectors - reserved_sectors -  ((directory_entries * FX_DIR_ENTRY_SIZE) + (bytes_per_sector - 1)) / bytes_per_sector) / sectors_per_cluster;
+
+        /* Calculate 16-bit FAT is present. Each cluster requires a 2 byte entry in the FAT table.  */
+        sectors_per_fat =  (total_clusters * 2) / bytes_per_sector;
+        if ((total_clusters * 2) % bytes_per_sector)
+        {
+            sectors_per_fat++;
+        }
+
+        /* Now adjust the total clusters by the number of sectors per FAT.  */
+        total_clusters =  total_clusters - ((sectors_per_fat * number_of_fats) + (sectors_per_cluster - 1)) / sectors_per_cluster;
+
+        /* Is the total cluster count greater than the FAT16 maximum?  */
+        if (total_clusters >= FX_16_BIT_FAT_SIZE)
+        {
+
+            /* Yes, FAT32 is present.  */
+
+            /* Allocate room for the FAT32 additional information sector. This contains useful information
+               such as the number of available clusters between successive mounting of the media.  */
+            if (bytes_per_sector == 512)
+            {
+
+                /* Write sector number 1 to the additional information sector.  */
+                _fx_utility_16_unsigned_write(&byte_ptr[48], 1);
+
+                /* Increment the reserved sectors count, since this will count as a reserved sector.  */
+                reserved_sectors++;
+            }
+            else
+            {
+
+                /* Write value to indicate there is no additional information sector.  */
+                _fx_utility_16_unsigned_write(&byte_ptr[48], 0xFFFF);
+            }
+
+            /* Allocate the first cluster to the root directory.  */
+            _fx_utility_32_unsigned_write(&byte_ptr[FX_ROOT_CLUSTER_32], FX_FAT_ENTRY_START);
+
+            /* Determine if the number of root directory entries should be modified.  */
+            directory_entries =  (sectors_per_cluster * bytes_per_sector) / FX_DIR_ENTRY_SIZE;
+
+            /* Reset the total_clusters for the FAT32 calculation.  */
+            total_clusters =  (total_sectors - reserved_sectors) / sectors_per_cluster;
+
+            /* 32-bit FAT is present. Each cluster requires a 4 byte entry in the FAT table.  */
+            sectors_per_fat =  (total_clusters * 4) / bytes_per_sector;
+            if ((total_clusters * 4) % bytes_per_sector)
+            {
+                sectors_per_fat++;
+            }
+
+            /* Now adjust the total clusters by the number of sectors per FAT.  */
+            total_clusters =  total_clusters - ((sectors_per_fat * number_of_fats) + (sectors_per_cluster - 1)) / sectors_per_cluster;
+        }
+    }
+
+    /* Set sectors per FAT type.  */
+    if (total_clusters < FX_16_BIT_FAT_SIZE)
+    {
+
+        /* Set the number of sectors per FAT12/16.  */
+        _fx_utility_16_unsigned_write(&byte_ptr[FX_SECTORS_PER_FAT], sectors_per_fat);
+
+        /* Set the signature.  */
+        byte_ptr[FX_BOOT_SIG] =  0x29;
+
+        /* Setup the volume ID.  */
+        _fx_utility_32_unsigned_write(&byte_ptr[FX_VOLUME_ID], _fx_media_format_volume_id);
+    }
+    else
+    {
+
+        /* Set the number of sectors per FAT32.  */
+        _fx_utility_32_unsigned_write(&byte_ptr[FX_SECTORS_PER_FAT_32], sectors_per_fat);
+
+        /* Set the signature.  */
+        byte_ptr[FX_BOOT_SIG_32] =  0x29;
+
+        /* Setup the volume ID.  */
+        _fx_utility_32_unsigned_write(&byte_ptr[FX_VOLUME_ID_32], _fx_media_format_volume_id);
+    }
+
+    /* Set the total number of sectors.  */
+    if (total_sectors < (ULONG)0xFFFF)
+    {
+
+        /* Write the 16-bit total sector field.  */
+        _fx_utility_16_unsigned_write(&byte_ptr[FX_SECTORS], (UINT)(total_sectors));
+
+        /* Set the number of huge sectors.  */
+        _fx_utility_32_unsigned_write(&byte_ptr[FX_HUGE_SECTORS], 0);
+    }
+    else
+    {
+
+        /* Write the 16-bit total sector field as 0.  */
+        _fx_utility_16_unsigned_write(&byte_ptr[FX_SECTORS], (UINT)0);
+
+        /* Set the number of huge sectors.  */
+        _fx_utility_32_unsigned_write(&byte_ptr[FX_HUGE_SECTORS], total_sectors);
+    }
+
+    /* Set the number of reserved sectors.  */
+    _fx_utility_16_unsigned_write(&byte_ptr[FX_RESERVED_SECTORS], reserved_sectors);
+
+    /* Set the number of sectors per cluster */
+    byte_ptr[FX_SECTORS_CLUSTER] =  (UCHAR)sectors_per_cluster;
+
+    /* Set the number of FATs.  */
+    byte_ptr[FX_NUMBER_OF_FATS] =  (UCHAR)number_of_fats;
+
+    /* Set the number of hidden sectors.  */
+    _fx_utility_32_unsigned_write(&byte_ptr[FX_HIDDEN_SECTORS], hidden_sectors);
+
+    /* Determine if a FAT12 or FAT16 is present.  If FAT32 is present, these fields are left alone!   */
+    if (total_clusters < FX_16_BIT_FAT_SIZE)
+    {
+
+        /* Yes, set the number of root directory entries.  */
+        _fx_utility_16_unsigned_write(&byte_ptr[FX_ROOT_DIR_ENTRIES], directory_entries);
+    }
+
+    /* Now setup the volume label. */
+    if (total_clusters < FX_16_BIT_FAT_SIZE)
+    {
+
+        /* FAT12/16 volume label offset.  */
+        j =  FX_VOLUME_LABEL;
+    }
+    else
+    {
+
+        /* FAT32 volume label offset.  */
+        j =  FX_VOLUME_LABEL_32;
+    }
+
+    i = 0;
+    while (i < 11)
+    {
+
+        /* Determine if it is NULL.  */
+        if (volume_name[i] == 0)
+        {
+
+            /* Yes, the copying is finished.  */
+            break;
+        }
+
+        /* Otherwise, copy byte of volume name into boot record.  */
+        byte_ptr[j + i] =  (UCHAR)volume_name[i];
+
+        /* Increment byte position.  */
+        i++;
+    }
+
+    /* Now blank-pad the remainder of the volume name.  */
+#ifndef FX_DISABLE_FORCE_MEMORY_OPERATION
+    while (i < 11)
+    {
+
+        byte_ptr[j + i] =  (UCHAR)' ';
+        i++;
+    }
+#else
+    _fx_utility_memory_set(&byte_ptr[j + i], ' ', (11 - i));
+#endif /* FX_DISABLE_FORCE_MEMORY_OPERATION */
+
+
+#ifdef FX_FORCE_512_BYTE_BOOT_SECTOR
+
+    /* Set bootrecord signature.  */
+    byte_ptr[510] = 0x55;
+    byte_ptr[511] = 0xAA;
+#else
+
+    /* Set bootrecord signature.  */
+    byte_ptr[bytes_per_sector - 2] = 0x55;
+    byte_ptr[bytes_per_sector - 1] = 0xAA;
+#endif
+
+    /* Select the boot record write command.  */
+    media_ptr -> fx_media_driver_request =       FX_DRIVER_BOOT_WRITE;
+    media_ptr -> fx_media_driver_system_write =  FX_TRUE;
+    media_ptr -> fx_media_driver_sectors =       1;
+    media_ptr -> fx_media_driver_sector_type =   FX_BOOT_SECTOR;
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_BOOT_WRITE, media_ptr, memory_ptr, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+    /* Write out the bootrecord */
+    (driver)(media_ptr);
+
+    /* Clear the write flag.  */
+    media_ptr -> fx_media_driver_system_write =  FX_FALSE;
+
+    /* Determine if it was successful.  */
+    if (media_ptr -> fx_media_driver_status != FX_SUCCESS)
+    {
+        return(FX_IO_ERROR);
+    }
+
+    /* Calculate the number of root sectors.  */
+    root_sectors =    ((directory_entries * FX_DIR_ENTRY_SIZE) + bytes_per_sector - 1) / bytes_per_sector;
+
+    /* Determine if FAT32 is present AND if the bytes per sector is large enough to have
+       a FSINFO sector.  */
+    if ((total_clusters >= FX_16_BIT_FAT_SIZE) && (bytes_per_sector == 512))
+    {
+
+#ifndef FX_DISABLE_FORCE_MEMORY_OPERATION
+        /* Clear sector buffer.  */
+        for (i = 0; i < bytes_per_sector; i++)
+        {
+            byte_ptr[i] =  (CHAR)0;
+        }
+#else
+        _fx_utility_memory_set(byte_ptr, 0, bytes_per_sector);
+#endif /* FX_DISABLE_FORCE_MEMORY_OPERATION */
+
+        /* Build the FSINFO fields.  */
+
+        /* Build first signature word, used to help verify this is a FSINFO sector.  */
+        byte_ptr[0] =  0x52;
+        byte_ptr[1] =  0x52;
+        byte_ptr[2] =  0x61;
+        byte_ptr[3] =  0x41;
+
+        /* Build the next signature word, this too is used to help verify that this is a FSINFO sector.  */
+        byte_ptr[484] =  0x72;
+        byte_ptr[485] =  0x72;
+        byte_ptr[486] =  0x41;
+        byte_ptr[487] =  0x61;
+
+        /* Build the final signature word, this too is used to help verify that this is a FSINFO sector.  */
+        byte_ptr[508] =  0x55;
+        byte_ptr[509] =  0xAA;
+
+        /* Setup the total available clusters on the media. We need to subtract 1 for the FAT32 root directory.  */
+        _fx_utility_32_unsigned_write(&byte_ptr[488], (total_clusters - 1));
+
+        /* Setup the starting free cluster to 3, since cluster 2 is reserved for the FAT32 root directory.  */
+        _fx_utility_32_unsigned_write(&byte_ptr[492], 3);
+
+        /* Now write the FSINFO sector to the media.  */
+        media_ptr -> fx_media_driver_logical_sector =  1;
+        media_ptr -> fx_media_driver_request =         FX_DRIVER_WRITE;
+        media_ptr -> fx_media_driver_sectors =         1;
+        media_ptr -> fx_media_driver_system_write =    FX_TRUE;
+        media_ptr -> fx_media_driver_sector_type =     FX_BOOT_SECTOR;
+
+        /* If trace is enabled, insert this event into the trace buffer.  */
+        FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_WRITE, media_ptr, 1, 1, memory_ptr, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+        /* Write out the sector.  */
+        (driver)(media_ptr);
+
+        /* Clear the system write flag.  */
+        media_ptr -> fx_media_driver_system_write =  FX_FALSE;
+
+        /* Determine if it was successful.  */
+        if (media_ptr -> fx_media_driver_status != FX_SUCCESS)
+        {
+            return(FX_IO_ERROR);
+        }
+    }
+
+    /* At this point we need set up first to FAT entries and clear the remaining FAT sectors area.  */
+
+    /* Loop through number of FATs. The first is the only one used.  */
+    for (f = 0; f < number_of_fats; f++)
+    {
+
+        /* Loop through all the sectors in this FAT.  */
+        for (s = 0; s < sectors_per_fat; s++)
+        {
+
+            if (s == 0)
+            {
+
+                /* Reserve the first two FAT table entries.  */
+                if (total_clusters < FX_12_BIT_FAT_SIZE)
+                {
+
+                    /* Reserve the first two FAT-12 entries.  */
+                    byte_ptr[0] =  _fx_media_format_media_type;
+                    byte_ptr[1] =  (UCHAR)0xFF;
+                    byte_ptr[2] =  (UCHAR)0xFF;
+
+                    /* Start clearing at FAT entry 3.  */
+                    i =  3;
+                }
+                else if (total_clusters < FX_16_BIT_FAT_SIZE)
+                {
+
+                    /* Reserve the first two FAT-16 entries.  */
+                    byte_ptr[0] =  _fx_media_format_media_type;
+                    byte_ptr[1] =  (UCHAR)0xFF;
+                    byte_ptr[2] =  (UCHAR)0xFF;
+                    byte_ptr[3] =  (UCHAR)0xFF;
+
+                    /* Start clearing at FAT entry 3.  */
+                    i =  4;
+                }
+                else
+                {
+
+                    /* Reserve the first two FAT-32 entries.   */
+                    byte_ptr[0] =  _fx_media_format_media_type;
+                    byte_ptr[1] =  (UCHAR)0xFF;
+                    byte_ptr[2] =  (UCHAR)0xFF;
+                    byte_ptr[3] =  (UCHAR)0x0F;
+                    byte_ptr[4] =  (UCHAR)0xFF;
+                    byte_ptr[5] =  (UCHAR)0xFF;
+                    byte_ptr[6] =  (UCHAR)0xFF;
+                    byte_ptr[7] =  (UCHAR)0x0F;
+
+                    /* Preallocate the first cluster for the root directory.  */
+                    byte_ptr[8] =   (UCHAR)0xFF;
+                    byte_ptr[9] =   (UCHAR)0xFF;
+                    byte_ptr[10] =  (UCHAR)0xFF;
+                    byte_ptr[11] =  (UCHAR)0x0F;
+
+                    /* Start clearing at FAT entry 3.  */
+                    i =  12;
+                }
+            }
+            else
+            {
+                i = 0;
+            }
+
+#ifndef FX_DISABLE_FORCE_MEMORY_OPERATION
+            /* Clear remainder of sector buffer.  */
+            for (; i < bytes_per_sector; i++)
+            {
+                byte_ptr[i] =  (CHAR)0;
+            }
+#else
+            _fx_utility_memory_set(&byte_ptr[i], 0, (bytes_per_sector - i));
+#endif  /* FX_DISABLE_FORCE_MEMORY_OPERATION */
+
+            /* Build sector write command.  */
+            media_ptr -> fx_media_driver_logical_sector =  reserved_sectors + (f * sectors_per_fat) + s;
+            media_ptr -> fx_media_driver_request =         FX_DRIVER_WRITE;
+            media_ptr -> fx_media_driver_sectors =         1;
+            media_ptr -> fx_media_driver_system_write =    FX_TRUE;
+            media_ptr -> fx_media_driver_sector_type =     FX_FAT_SECTOR;
+
+            /* If trace is enabled, insert this event into the trace buffer.  */
+            FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_WRITE, media_ptr, media_ptr -> fx_media_driver_logical_sector, 1, memory_ptr, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+            /* Write out the sector.  */
+            (driver)(media_ptr);
+
+            /* Clear the system write flag.  */
+            media_ptr -> fx_media_driver_system_write =  FX_FALSE;
+
+            /* Determine if it was successful.  */
+            if (media_ptr -> fx_media_driver_status != FX_SUCCESS)
+            {
+                return(FX_IO_ERROR);
+            }
+        }
+    }
+
+#ifndef FX_DISABLE_FORCE_MEMORY_OPERATION
+    /* Clear sector buffer.  */
+    for (i = 0; i < bytes_per_sector; i++)
+    {
+        byte_ptr[i] =  (CHAR)0;
+    }
+#else
+    _fx_utility_memory_set(byte_ptr, 0, bytes_per_sector);
+#endif /* FX_DISABLE_FORCE_MEMORY_OPERATION */
+
+    /* Now clear the root directory sectors.  */
+    for (s = 0; s < root_sectors; s++)
+    {
+
+        /* Build sector write command.  */
+        media_ptr -> fx_media_driver_logical_sector =  reserved_sectors + (number_of_fats * sectors_per_fat) + s;
+        media_ptr -> fx_media_driver_request =         FX_DRIVER_WRITE;
+        media_ptr -> fx_media_driver_sectors =         1;
+        media_ptr -> fx_media_driver_system_write =    FX_TRUE;
+        media_ptr -> fx_media_driver_sector_type =     FX_DIRECTORY_SECTOR;
+
+        /* If trace is enabled, insert this event into the trace buffer.  */
+        FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_WRITE, media_ptr, media_ptr -> fx_media_driver_logical_sector, 1, memory_ptr, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+        /* Write out the sector.  */
+        (driver)(media_ptr);
+
+        /* Clear the write flag.  */
+        media_ptr -> fx_media_driver_system_write =  FX_FALSE;
+
+        /* Determine if it was successful.  */
+        if (media_ptr -> fx_media_driver_status != FX_SUCCESS)
+        {
+            return(FX_IO_ERROR);
+        }
+    }
+
+    /* Build the "uninitialize" I/O driver request.  */
+    media_ptr -> fx_media_driver_request =      FX_DRIVER_UNINIT;
+    media_ptr -> fx_media_driver_status =       FX_IO_ERROR;
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_UNINIT, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+    /* Call the specified I/O driver with the uninitialize request.  */
+    (media_ptr -> fx_media_driver_entry) (media_ptr);
+
+    /* Return success!  */
+    return(media_ptr -> fx_media_driver_status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_format_oem_name_set.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_format_oem_name_set.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_format_oem_name_set.c	(revision 30)
@@ -0,0 +1,97 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */ 
+/** FileX Component                                                       */ 
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_media.h"
+
+
+/* Define external reference to OEM name string.  */
+
+extern UCHAR   _fx_media_format_oem_name[8];
+UINT  fx_media_format_oem_name_set(UCHAR new_oem_name[8]);
+
+/**************************************************************************/ 
+/*                                                                        */ 
+/*  FUNCTION                                               RELEASE        */ 
+/*                                                                        */ 
+/*    _fx_media_format_oem_name_set                       PORTABLE C      */ 
+/*                                                           6.1.5        */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */ 
+/*    This function modifies the default OEM name for all formatting. The */ 
+/*    new OEM name must be 8 characters long - blank padded if necessary. */ 
+/*                                                                        */ 
+/*                                                                        */ 
+/*  INPUT                                                                 */ 
+/*                                                                        */ 
+/*    new_oem_name                          Pointer to new OEM name       */ 
+/*                                                                        */ 
+/*  OUTPUT                                                                */ 
+/*                                                                        */ 
+/*    Completion Status                                                   */ 
+/*                                                                        */ 
+/*  CALLS                                                                 */ 
+/*                                                                        */ 
+/*    None                                                                */ 
+/*                                                                        */ 
+/*  CALLED BY                                                             */ 
+/*                                                                        */ 
+/*    Application Code                                                    */ 
+/*                                                                        */ 
+/*  RELEASE HISTORY                                                       */ 
+/*                                                                        */ 
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*  03-02-2021     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1.5  */
+/*                                                                        */
+/**************************************************************************/
+UINT  fx_media_format_oem_name_set(UCHAR new_oem_name[8])
+{
+
+UINT    i;
+
+
+    /* Simply copy the new OEM name into the default location.  */
+    for (i = 0; i < 8; i++)
+    {
+
+        /* Copy one character of the new OEM name.  */
+        _fx_media_format_oem_name[i] =  new_oem_name[i];
+    }
+
+    /* Return success.  */
+    return(FX_SUCCESS);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_format_type_set.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_format_type_set.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_format_type_set.c	(revision 30)
@@ -0,0 +1,88 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */ 
+/** FileX Component                                                       */ 
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_media.h"
+
+
+/* Define external reference to media type.  */
+
+extern UCHAR   _fx_media_format_media_type;
+UINT  fx_media_format_type_set(UCHAR new_media_type);
+
+/**************************************************************************/ 
+/*                                                                        */ 
+/*  FUNCTION                                               RELEASE        */ 
+/*                                                                        */ 
+/*    _fx_media_format_type_set                           PORTABLE C      */ 
+/*                                                           6.1.5        */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */ 
+/*    This function modifies the default media type for all formatting.   */ 
+/*                                                                        */ 
+/*                                                                        */ 
+/*  INPUT                                                                 */ 
+/*                                                                        */ 
+/*    new_media_type                        New media type value          */ 
+/*                                                                        */ 
+/*  OUTPUT                                                                */ 
+/*                                                                        */ 
+/*    Completion Status                                                   */ 
+/*                                                                        */ 
+/*  CALLS                                                                 */ 
+/*                                                                        */ 
+/*    None                                                                */ 
+/*                                                                        */ 
+/*  CALLED BY                                                             */ 
+/*                                                                        */ 
+/*    Application Code                                                    */ 
+/*                                                                        */ 
+/*  RELEASE HISTORY                                                       */ 
+/*                                                                        */ 
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*  03-02-2021     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1.5  */
+/*                                                                        */
+/**************************************************************************/
+UINT  fx_media_format_type_set(UCHAR new_media_type)
+{
+
+    /* Simply copy the new media type into the default location.  */
+    _fx_media_format_media_type =  new_media_type;
+
+    /* Return success.  */
+    return(FX_SUCCESS);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_format_volume_id_set.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_format_volume_id_set.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_format_volume_id_set.c	(revision 30)
@@ -0,0 +1,88 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */ 
+/** FileX Component                                                       */ 
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_media.h"
+
+
+/* Define external reference to media volume ID.  */
+
+extern ULONG   _fx_media_format_volume_id;
+UINT  fx_media_format_volume_id_set(ULONG new_volume_id);
+
+/**************************************************************************/ 
+/*                                                                        */ 
+/*  FUNCTION                                               RELEASE        */ 
+/*                                                                        */ 
+/*    _fx_media_format_media_volume_id_set                PORTABLE C      */ 
+/*                                                           6.1.5        */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */ 
+/*    This function modifies the default media volume ID for all          */ 
+/*    formatting.                                                         */ 
+/*                                                                        */ 
+/*                                                                        */ 
+/*  INPUT                                                                 */ 
+/*                                                                        */ 
+/*    new_volume_id                         New media volume Id value     */ 
+/*                                                                        */ 
+/*  OUTPUT                                                                */ 
+/*                                                                        */ 
+/*    Completion Status                                                   */ 
+/*                                                                        */ 
+/*  CALLS                                                                 */ 
+/*                                                                        */ 
+/*    None                                                                */ 
+/*                                                                        */ 
+/*  CALLED BY                                                             */ 
+/*                                                                        */ 
+/*    Application Code                                                    */ 
+/*                                                                        */ 
+/*  RELEASE HISTORY                                                       */ 
+/*                                                                        */ 
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*  03-02-2021     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1.5  */
+/*                                                                        */
+/**************************************************************************/
+UINT  fx_media_format_volume_id_set(ULONG new_volume_id)
+{
+
+    /* Simply copy the new media volume ID into the default location.  */
+    _fx_media_format_volume_id =  new_volume_id;
+
+    /* Return success.  */
+    return(FX_SUCCESS);
+}
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_open.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_open.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_open.c	(revision 30)
@@ -0,0 +1,1064 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_media.h"
+#include "fx_utility.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_media_open                                      PORTABLE C      */
+/*                                                           6.2.0        */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function opens the specified media with the supplied device    */
+/*    driver.  The specified media must conform to the FAT compatible     */
+/*    file format, which is verified during the media open process.  In   */
+/*    addition, the supplied FileX device driver must also conform to     */
+/*    the FileX device driver specification.                              */
+/*                                                                        */
+/*    The FAT boot sector (512 bytes) that is verified by this            */
+/*    function must look like the following:                              */
+/*                                                                        */
+/*          Byte Offset         Meaning             Size                  */
+/*                                                                        */
+/*            0x000         Jump Instructions        3                    */
+/*            0x003         OEM Name                 8                    */
+/*            0x00B        *Bytes per Sector         2                    */
+/*            0x00D        *Sectors per Cluster      1                    */
+/*            0x00E        *Reserved Sectors         2                    */
+/*            0x010        *Number of FATs           1                    */
+/*            0x011        *Max Root Dir Entries     2                    */
+/*            0x013        *Number of Sectors        2                    */
+/*            0x015         Media Type               1                    */
+/*            0x016        *Sectors per FAT          2                    */
+/*            0x018        *Sectors per Track        2                    */
+/*            0x01A        *Number of Heads          2                    */
+/*            0x01C        *Hidden Sectors           4                    */
+/*            0x020        *Huge Sectors             4                    */
+/*            0x024         Drive Number             1                    */
+/*            0x025         Reserved                 1                    */
+/*            0x026         Boot Signature           1                    */
+/*            0x027         Volume ID                4                    */
+/*            0x02B         Volume Label             11                   */
+/*            0x036         File System Type         8                    */
+/*             ...              ...                 ...                   */
+/*            0x1FE       **Signature (0x55aa)       2                    */
+/*                                                                        */
+/*            * Denotes which elements of the boot record                 */
+/*              FileX uses.                                               */
+/*                                                                        */
+/*            **Denotes the element is checked by the I/O                 */
+/*              driver.  This eliminates the need for a minimum           */
+/*              512-byte buffer for FileX.                                */
+/*                                                                        */
+/*  Note: All values above are in little endian format, i.e. the LSB is   */
+/*        in the lowest address.                                          */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    media_name                            Pointer to media name string  */
+/*    media_driver                          Media driver entry function   */
+/*    driver_info_ptr                       Optional information pointer  */
+/*                                            supplied to media driver    */
+/*    memory_ptr                            Pointer to memory used by the */
+/*                                            FileX for this media.       */
+/*    memory_size                           Size of media memory - must   */
+/*                                            at least 512 bytes and      */
+/*                                            one sector size.            */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    I/O Driver                                                          */
+/*    _fx_utility_exFAT_bitmap_initialize   Initialize exFAT bitmap       */
+/*    _fx_utility_16_unsigned_read          Read 16-bit unsigned value    */
+/*    _fx_utility_32_unsigned_read          Read 32-bit unsigned value    */
+/*    _fx_utility_logical_sector_flush      Invalidate log sector cache   */
+/*    _fx_media_boot_info_extract           Extract media information     */
+/*    _fx_utility_FAT_entry_read            Pickup FAT entry contents     */
+/*    tx_mutex_create                       Create protection mutex       */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s), and      */
+/*                                            added conditional to        */
+/*                                            disable force memset,       */
+/*                                            build options and cache,    */
+/*                                            resulting in version 6.1    */
+/*  01-31-2022     William E. Lamie         Modified comment(s), fixed    */
+/*                                            errors without cache,       */
+/*                                            resulting in version 6.1.10 */
+/*  10-31-2022     Tiejun Zhou              Modified comment(s),          */
+/*                                            fixed memory buffer when    */
+/*                                            cache is disabled,          */
+/*                                            resulting in version 6.2.0  */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_media_open(FX_MEDIA *media_ptr, CHAR *media_name,
+                     VOID (*media_driver)(FX_MEDIA *), VOID *driver_info_ptr,
+                     VOID *memory_ptr, ULONG memory_size)
+{
+
+FX_MEDIA_PTR      tail_ptr;
+ULONG             cluster_number;
+ULONG             FAT_entry, FAT_sector, FAT_read_sectors;
+ULONG             i, j;
+#ifndef FX_DISABLE_CACHE
+FX_CACHED_SECTOR *cache_entry_ptr;
+#endif /* FX_DISABLE_CACHE */
+UINT              status;
+UINT              additional_info_sector;
+UCHAR            *original_memory_ptr;
+ULONG             bytes_in_buffer;
+FX_INT_SAVE_AREA
+
+
+#ifndef FX_DISABLE_BUILD_OPTIONS
+    /* Reference the version ID and option words to ensure they are linked in.  */
+    if ((_fx_system_build_options_1 | _fx_system_build_options_2 | _fx_system_build_options_3) == 0 ||
+        _fx_version_id[0] == 0)
+    {
+
+        /* We should never get here!  */
+        return(FX_NOT_IMPLEMENTED);
+    }
+#endif /* FX_DISABLE_BUILD_OPTIONS */
+
+#ifdef FX_DISABLE_FORCE_MEMORY_OPERATION
+    _fx_utility_memory_set((UCHAR *)media_ptr, 0, sizeof(FX_MEDIA));
+#endif /* FX_DISABLE_FORCE_MEMORY_OPERATION */
+#ifdef FX_DISABLE_CACHE
+    media_ptr -> fx_media_memory_buffer_sector = (ULONG64)-1;
+#endif /* FX_DISABLE_CACHE */
+
+    /* Save the basic information in the media control block.  */
+    media_ptr -> fx_media_name =                        media_name;
+    media_ptr -> fx_media_driver_entry =                media_driver;
+    media_ptr -> fx_media_memory_buffer =               (UCHAR *)memory_ptr;
+    media_ptr -> fx_media_memory_size =                 memory_size;
+#ifndef FX_DISABLE_FORCE_MEMORY_OPERATION
+    media_ptr -> fx_media_disable_burst_cache =         FX_FALSE;
+    media_ptr -> fx_media_FAT_type =                    0;
+#endif /* FX_DISABLE_FORCE_MEMORY_OPERATION */
+
+    /* Save the original memory pointer.  */
+    original_memory_ptr =  (UCHAR *)memory_ptr;
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Clear the optional media statistics.  */
+    media_ptr -> fx_media_directory_attributes_reads =  0;
+    media_ptr -> fx_media_directory_attributes_sets =  0;
+    media_ptr -> fx_media_directory_creates =  0;
+    media_ptr -> fx_media_directory_default_gets =  0;
+    media_ptr -> fx_media_directory_default_sets =  0;
+    media_ptr -> fx_media_directory_deletes =  0;
+    media_ptr -> fx_media_directory_first_entry_finds =  0;
+    media_ptr -> fx_media_directory_first_full_entry_finds =  0;
+    media_ptr -> fx_media_directory_information_gets =  0;
+    media_ptr -> fx_media_directory_local_path_clears =  0;
+    media_ptr -> fx_media_directory_local_path_gets =  0;
+    media_ptr -> fx_media_directory_local_path_restores =  0;
+    media_ptr -> fx_media_directory_local_path_sets =  0;
+    media_ptr -> fx_media_directory_name_tests =  0;
+    media_ptr -> fx_media_directory_next_entry_finds =  0;
+    media_ptr -> fx_media_directory_next_full_entry_finds =  0;
+    media_ptr -> fx_media_directory_renames =  0;
+    media_ptr -> fx_media_file_allocates =  0;
+    media_ptr -> fx_media_file_attributes_reads =  0;
+    media_ptr -> fx_media_file_attributes_sets =  0;
+    media_ptr -> fx_media_file_best_effort_allocates =  0;
+    media_ptr -> fx_media_file_closes =  0;
+    media_ptr -> fx_media_file_creates =  0;
+    media_ptr -> fx_media_file_deletes =  0;
+    media_ptr -> fx_media_file_opens =  0;
+    media_ptr -> fx_media_file_reads =  0;
+    media_ptr -> fx_media_file_relative_seeks =  0;
+    media_ptr -> fx_media_file_renames =  0;
+    media_ptr -> fx_media_file_seeks =  0;
+    media_ptr -> fx_media_file_truncates =  0;
+    media_ptr -> fx_media_file_truncate_releases =  0;
+    media_ptr -> fx_media_file_writes =  0;
+    media_ptr -> fx_media_aborts =  0;
+    media_ptr -> fx_media_flushes =  0;
+    media_ptr -> fx_media_reads =  0;
+    media_ptr -> fx_media_writes =  0;
+    media_ptr -> fx_media_directory_entry_reads =  0;
+    media_ptr -> fx_media_directory_entry_writes =  0;
+    media_ptr -> fx_media_directory_searches =  0;
+#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
+    media_ptr -> fx_media_directory_search_cache_hits =  0;
+#endif
+    media_ptr -> fx_media_directory_free_searches =  0;
+    media_ptr -> fx_media_fat_entry_reads =  0;
+    media_ptr -> fx_media_fat_entry_writes =  0;
+    media_ptr -> fx_media_fat_entry_cache_read_hits =  0;
+    media_ptr -> fx_media_fat_entry_cache_read_misses =  0;
+    media_ptr -> fx_media_fat_entry_cache_write_hits =  0;
+    media_ptr -> fx_media_fat_entry_cache_write_misses =  0;
+    media_ptr -> fx_media_fat_cache_flushes =  0;
+    media_ptr -> fx_media_fat_sector_reads =  0;
+    media_ptr -> fx_media_fat_sector_writes =  0;
+    media_ptr -> fx_media_logical_sector_reads =  0;
+    media_ptr -> fx_media_logical_sector_writes =  0;
+    media_ptr -> fx_media_logical_sector_cache_read_hits =  0;
+    media_ptr -> fx_media_logical_sector_cache_read_misses =  0;
+    media_ptr -> fx_media_driver_read_requests =  0;
+    media_ptr -> fx_media_driver_write_requests =  0;
+    media_ptr -> fx_media_driver_boot_read_requests =  0;
+    media_ptr -> fx_media_driver_boot_write_requests =  0;
+    media_ptr -> fx_media_driver_release_sectors_requests =  0;
+    media_ptr -> fx_media_driver_flush_requests =  0;
+#endif
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    media_ptr -> fx_media_fault_tolerant_enabled = FX_FALSE;
+    media_ptr -> fx_media_fault_tolerant_state = 0;
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_MEDIA_OPEN, media_ptr, media_driver, memory_ptr, memory_size, FX_TRACE_MEDIA_EVENTS, 0, 0)
+
+    /* Initialize the supplied media I/O driver.  First, build the
+       initialize driver request.  */
+    media_ptr -> fx_media_driver_request =              FX_DRIVER_INIT;
+    media_ptr -> fx_media_driver_status =               FX_IO_ERROR;
+    media_ptr -> fx_media_driver_info =                 driver_info_ptr;
+    media_ptr -> fx_media_driver_write_protect =        FX_FALSE;
+    media_ptr -> fx_media_driver_free_sector_update =   FX_FALSE;
+    media_ptr -> fx_media_driver_data_sector_read =     FX_FALSE;
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_INIT, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+    /* Call the specified I/O driver with the initialize request.  */
+    (media_ptr -> fx_media_driver_entry) (media_ptr);
+
+    /* Determine if the I/O driver initialized successfully.  */
+    if (media_ptr -> fx_media_driver_status != FX_SUCCESS)
+    {
+
+        /* Return the driver error status.  */
+        return(FX_IO_ERROR);
+    }
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of driver boot read requests.  */
+    media_ptr -> fx_media_driver_boot_read_requests++;
+#endif
+
+    /* Read the boot sector from the device.  Build the read boot sector
+       command.  */
+    media_ptr -> fx_media_driver_request =          FX_DRIVER_BOOT_READ;
+    media_ptr -> fx_media_driver_status =           FX_IO_ERROR;
+    media_ptr -> fx_media_driver_buffer =           memory_ptr;
+    media_ptr -> fx_media_driver_sectors =          1;
+    media_ptr -> fx_media_driver_sector_type =      FX_BOOT_SECTOR;
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_BOOT_READ, media_ptr, memory_ptr, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+    /* Invoke the driver to read the boot sector.  */
+    (media_ptr -> fx_media_driver_entry) (media_ptr);
+
+    /* Determine if the boot sector was read correctly. */
+    if (media_ptr -> fx_media_driver_status != FX_SUCCESS)
+    {
+
+        /* Build the "uninitialize" I/O driver request.  */
+        media_ptr -> fx_media_driver_request =      FX_DRIVER_UNINIT;
+        media_ptr -> fx_media_driver_status =       FX_IO_ERROR;
+
+        /* If trace is enabled, insert this event into the trace buffer.  */
+        FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_UNINIT, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+        /* Call the specified I/O driver with the uninitialize request.  */
+        (media_ptr -> fx_media_driver_entry) (media_ptr);
+
+        /* Return the boot sector error status.  */
+        return(FX_BOOT_ERROR);
+    }
+
+    /* Extract and validate the media parameters from the boot sector.  */
+    if (_fx_media_boot_info_extract(media_ptr) != FX_SUCCESS)
+    {
+
+        /* Build the "uninitialize" I/O driver request.  */
+        media_ptr -> fx_media_driver_request =      FX_DRIVER_UNINIT;
+        media_ptr -> fx_media_driver_status =       FX_IO_ERROR;
+
+        /* If trace is enabled, insert this event into the trace buffer.  */
+        FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_UNINIT, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+        /* Call the specified I/O driver with the uninitialize request.  */
+        (media_ptr -> fx_media_driver_entry) (media_ptr);
+
+        /* Return the invalid media error status.  */
+        return(FX_MEDIA_INVALID);
+    }
+
+    /* Pickup the additional info sector number. This will only be used in FAT32 situations.  */
+    additional_info_sector =  _fx_utility_16_unsigned_read(&media_ptr -> fx_media_driver_buffer[48]);
+
+    /* Is there at least one?  */
+    if (memory_size < media_ptr -> fx_media_bytes_per_sector)
+    {
+
+        /* Build the "uninitialize" I/O driver request.  */
+        media_ptr -> fx_media_driver_request =      FX_DRIVER_UNINIT;
+        media_ptr -> fx_media_driver_status =       FX_IO_ERROR;
+
+        /* If trace is enabled, insert this event into the trace buffer.  */
+        FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_UNINIT, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+        /* Call the specified I/O driver with the uninitialize request.  */
+        (media_ptr -> fx_media_driver_entry) (media_ptr);
+
+        /* Error in the buffer size supplied by user.  */
+        return(FX_BUFFER_ERROR);
+    }
+
+#ifndef FX_DISABLE_CACHE
+    /* Determine how many logical sectors can be cached with user's supplied
+       buffer area - there must be at least enough for one sector!  */
+    media_ptr -> fx_media_sector_cache_size =  memory_size / media_ptr -> fx_media_bytes_per_sector;
+
+    /* If trace is enabled, register this object.  */
+    FX_TRACE_OBJECT_REGISTER(FX_TRACE_OBJECT_TYPE_MEDIA, media_ptr, media_name, FX_MAX_FAT_CACHE, media_ptr -> fx_media_sector_cache_size)
+    
+    /* Adjust the internal cache to fit the fixed number of sector cache control blocks
+       built into the media control block.  */
+    if (media_ptr -> fx_media_sector_cache_size > FX_MAX_SECTOR_CACHE)
+    {
+
+        /* Adjust the number of cache sectors downward.  If this is insufficient,
+           the FX_MAX_SECTOR_CACHE constant in FX_API.H must be changed and the FileX
+           library must be rebuilt.  */
+        media_ptr -> fx_media_sector_cache_size =  FX_MAX_SECTOR_CACHE;
+    }
+
+    /* Otherwise, everything is okay.  Initialize the data structures for managing the
+       logical sector cache.  */
+    i =  (UINT)media_ptr -> fx_media_sector_cache_size;
+    cache_entry_ptr =  media_ptr -> fx_media_sector_cache;
+    while (i--)
+    {
+
+        /* Initialize each of the cache entries.  */
+        cache_entry_ptr -> fx_cached_sector_memory_buffer =  (UCHAR *)memory_ptr;
+        cache_entry_ptr -> fx_cached_sector =                (~(ULONG64)0);
+        cache_entry_ptr -> fx_cached_sector_buffer_dirty =   FX_FALSE;
+        cache_entry_ptr -> fx_cached_sector_valid =          FX_FALSE;
+        cache_entry_ptr -> fx_cached_sector_next_used =      cache_entry_ptr + 1;
+
+        /* Move to the next cache sector entry.  */
+        cache_entry_ptr++;
+
+        /* Update the memory pointer to the next buffer slot.  */
+        memory_ptr =  (VOID *)(((UCHAR *)memory_ptr) + media_ptr -> fx_media_bytes_per_sector);
+    }
+
+    /* Backup to the last cache entry to set its next pointer to NULL.  */
+    cache_entry_ptr--;
+    cache_entry_ptr -> fx_cached_sector_next_used =  FX_NULL;
+
+    /* Remember the last memory address used by the caching logic.  */
+    media_ptr -> fx_media_sector_cache_end =  ((UCHAR *)memory_ptr) - 1;
+
+    /* Setup the head pointer of the list.  */
+    media_ptr -> fx_media_sector_cache_list_ptr =  media_ptr -> fx_media_sector_cache;
+
+    /* Setup the bit map that keeps track of the valid hashed cache logical sectors.  */
+    media_ptr -> fx_media_sector_cache_hashed_sector_valid =  0;
+
+    /* Clear the counter of the number of outstanding dirty sectors.  */
+    media_ptr -> fx_media_sector_cache_dirty_count =  0;
+
+    /* Determine if the logical sector cache should be managed by the hash function
+       instead of the linear search. The cache must be a power of 2 that is between the
+       minimum and maximum cache size.  */
+    if ((media_ptr -> fx_media_sector_cache_size >= FX_SECTOR_CACHE_HASH_ENABLE) &&
+        ((media_ptr -> fx_media_sector_cache_size ^ (media_ptr -> fx_media_sector_cache_size - 1)) ==
+         (media_ptr -> fx_media_sector_cache_size | (media_ptr -> fx_media_sector_cache_size - 1))))
+    {
+
+
+        /* Set the logical sector cache hash flag. When this flag is set, the logical
+           sector cache is accessed with a hash function instead of a linear search.  */
+        media_ptr -> fx_media_sector_cache_hashed =  FX_TRUE;
+        media_ptr -> fx_media_sector_cache_hash_mask =
+            ((media_ptr -> fx_media_sector_cache_size / FX_SECTOR_CACHE_DEPTH) - 1);
+    }
+    else
+    {
+
+        /* Clear the logical sector cache flag.  */
+        media_ptr -> fx_media_sector_cache_hashed =  FX_FALSE;
+    }
+#else
+    media_ptr -> fx_media_memory_buffer = memory_ptr;
+#endif /* FX_DISABLE_CACHE */
+
+#ifndef FX_DISABLE_FORCE_MEMORY_OPERATION
+    /* Initialize the FAT cache entry array.  */
+    for (i = 0; i < FX_MAX_FAT_CACHE; i++)
+    {
+
+        /* Clear entry in the FAT cache.  */
+        media_ptr -> fx_media_fat_cache[i].fx_fat_cache_entry_cluster =   0;
+        media_ptr -> fx_media_fat_cache[i].fx_fat_cache_entry_value   =   0;
+        media_ptr -> fx_media_fat_cache[i].fx_fat_cache_entry_dirty   =   0;
+    }
+
+    /* Initialize the secondary FAT update map.  */
+    for (i = 0; i < FX_FAT_MAP_SIZE; i++)
+    {
+
+        /* Clear bit map entry for secondary FAT update.  */
+        media_ptr -> fx_media_fat_secondary_update_map[i] =  0;
+    }
+#endif /* FX_DISABLE_FORCE_MEMORY_OPERATION */
+
+#ifdef FX_ENABLE_EXFAT
+    if (media_ptr -> fx_media_FAT_type != FX_exFAT)
+    {
+#endif /* FX_ENABLE_EXFAT */
+
+        /* Root_sector_start has been computed */
+        media_ptr -> fx_media_root_sector_start =  media_ptr -> fx_media_reserved_sectors +
+            (media_ptr -> fx_media_number_of_FATs *
+             media_ptr -> fx_media_sectors_per_FAT);
+
+        /* Calculate the number of directory sectors.  */
+        media_ptr -> fx_media_root_sectors =
+            ((media_ptr -> fx_media_root_directory_entries * FX_DIR_ENTRY_SIZE) +
+             media_ptr -> fx_media_bytes_per_sector - 1) /
+            media_ptr -> fx_media_bytes_per_sector;
+
+        /* Calculate the starting data sector.  */
+        media_ptr -> fx_media_data_sector_start =  media_ptr -> fx_media_root_sector_start +
+            media_ptr -> fx_media_root_sectors;
+
+        /* Calculate the total number of clusters.  */
+        media_ptr -> fx_media_total_clusters =  (ULONG)((media_ptr -> fx_media_total_sectors - media_ptr -> fx_media_data_sector_start) /
+                                                            media_ptr -> fx_media_sectors_per_cluster);
+
+        /* Determine if a 12-bit FAT is in use.  */
+        if (media_ptr -> fx_media_total_clusters < FX_12_BIT_FAT_SIZE)
+        {
+
+            /* Yes, 12-bit FAT is present.  Set flag accordingly.  */
+            media_ptr -> fx_media_12_bit_FAT = FX_TRUE;
+            media_ptr -> fx_media_32_bit_FAT = FX_FALSE;
+#ifdef FX_ENABLE_EXFAT
+            media_ptr -> fx_media_FAT_type = FX_FAT12;
+#endif /* FX_ENABLE_EXFAT */
+
+            /* No additional information sector in FAT12.  */
+            media_ptr -> fx_media_FAT32_additional_info_sector =  0;
+
+            /* Set FAT last and FAT reserved. */
+            media_ptr -> fx_media_fat_reserved = FX_RESERVED_1;
+            media_ptr -> fx_media_fat_last = FX_LAST_CLUSTER_2;
+        }
+        else if (media_ptr -> fx_media_total_clusters < FX_16_BIT_FAT_SIZE)
+        {
+
+            /* A 16-bit FAT is present.  Set flag accordingly.  */
+            media_ptr -> fx_media_12_bit_FAT =  FX_FALSE;
+            media_ptr -> fx_media_32_bit_FAT =  FX_FALSE;
+#ifdef FX_ENABLE_EXFAT
+            media_ptr -> fx_media_FAT_type = FX_FAT16;
+#endif /* FX_ENABLE_EXFAT */
+
+            /* No additional information sector in FAT16.  */
+            media_ptr -> fx_media_FAT32_additional_info_sector =  0;
+
+            /* Set FAT last and FAT reserved. */
+            media_ptr -> fx_media_fat_reserved = FX_RESERVED_1;
+            media_ptr -> fx_media_fat_last = FX_LAST_CLUSTER_2;
+        }
+        else
+        {
+
+            /* Yes, a 32-bit FAT is present.  */
+            media_ptr -> fx_media_12_bit_FAT =  FX_FALSE;
+            media_ptr -> fx_media_32_bit_FAT =  FX_TRUE;
+#ifdef FX_ENABLE_EXFAT
+            media_ptr -> fx_media_FAT_type = FX_FAT32;
+#endif /* FX_ENABLE_EXFAT */
+
+            /* Save the additional information sector FAT32. This was read from the boot
+               sector earlier in this routine. */
+            media_ptr -> fx_media_FAT32_additional_info_sector =  additional_info_sector;
+
+            /* Set FAT last and FAT reserved. */
+            media_ptr -> fx_media_fat_reserved = FX_RESERVED_1_32;
+            media_ptr -> fx_media_fat_last = FX_LAST_CLUSTER_2_32;
+        }
+#ifdef FX_ENABLE_EXFAT
+    }
+    else
+    {
+
+        /* Set FAT last and FAT reserved. */
+        media_ptr -> fx_media_fat_reserved = FX_RESERVED_1_exFAT;
+        media_ptr -> fx_media_fat_last = FX_LAST_CLUSTER_exFAT;
+    }
+#endif /* FX_ENABLE_EXFAT */
+
+    /* Determine if a 32-bit FAT is present. If so, calculate the size of the root directory (since
+       it is variable in FAT32.  */
+#ifdef FX_ENABLE_EXFAT
+    if (media_ptr -> fx_media_32_bit_FAT == FX_TRUE || 
+        (media_ptr -> fx_media_FAT_type == FX_exFAT))
+#else
+    if (media_ptr -> fx_media_32_bit_FAT == FX_TRUE)
+#endif /* FX_ENABLE_EXFAT */
+    {
+#ifdef FX_ENABLE_EXFAT
+        if (media_ptr -> fx_media_32_bit_FAT == FX_TRUE)
+        {
+#endif /* FX_ENABLE_EXFAT */
+
+            /* Root First cluster starts from at least cluster 2, or higher. */
+            if (media_ptr -> fx_media_root_cluster_32 < FX_FAT_ENTRY_START)
+            {
+                return(FX_MEDIA_INVALID);
+            }
+
+            /* Calculate logical number of root dir sector.  */
+            media_ptr -> fx_media_root_sector_start = media_ptr -> fx_media_data_sector_start +
+                (media_ptr -> fx_media_root_cluster_32 - FX_FAT_ENTRY_START) *
+                media_ptr -> fx_media_sectors_per_cluster;
+#ifdef FX_ENABLE_EXFAT
+        }
+#endif /* FX_ENABLE_EXFAT */
+
+        /* Calculate maximum possible value for fx_media_root_directory_entries */
+        i = 0;
+        for (cluster_number = media_ptr -> fx_media_root_cluster_32;;)
+        {
+
+            status =  _fx_utility_FAT_entry_read(media_ptr, cluster_number, &FAT_entry);
+            i++;
+            /* Determine if the read was successful.  */
+            if (status != FX_SUCCESS)
+            {
+
+                /* Build the "uninitialize" I/O driver request.  */
+                media_ptr -> fx_media_driver_request =      FX_DRIVER_UNINIT;
+                media_ptr -> fx_media_driver_status =       FX_IO_ERROR;
+
+                /* If trace is enabled, insert this event into the trace buffer.  */
+                FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_UNINIT, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+                /* Call the specified I/O driver with the uninitialize request.  */
+                (media_ptr -> fx_media_driver_entry) (media_ptr);
+
+                return(FX_FAT_READ_ERROR);
+            }
+
+            if ((cluster_number == FAT_entry) || (i > media_ptr -> fx_media_total_clusters))
+            {
+
+                /* Build the "uninitialize" I/O driver request.  */
+                media_ptr -> fx_media_driver_request =      FX_DRIVER_UNINIT;
+                media_ptr -> fx_media_driver_status =       FX_IO_ERROR;
+
+                /* If trace is enabled, insert this event into the trace buffer.  */
+                FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_UNINIT, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+                /* Call the specified I/O driver with the uninitialize request.  */
+                (media_ptr -> fx_media_driver_entry) (media_ptr);
+
+                return(FX_FAT_READ_ERROR);
+            }
+            if (FAT_entry >= FX_RESERVED_1_32)
+            {
+                break;
+            }
+            cluster_number = FAT_entry;
+        }
+
+        /* Calculate the number of directory entries.  */
+        media_ptr -> fx_media_root_directory_entries =  (i * media_ptr -> fx_media_sectors_per_cluster *
+                                                         media_ptr -> fx_media_bytes_per_sector) / FX_DIR_ENTRY_SIZE;
+    }
+
+#ifndef FX_DISABLE_FORCE_MEMORY_OPERATION
+    /* Calculate the number of available clusters.  */
+    media_ptr -> fx_media_available_clusters =  0;
+
+    /* Set the cluster search start to an invalid value.  */
+    media_ptr -> fx_media_cluster_search_start =  0;
+#endif /* FX_DISABLE_FORCE_MEMORY_OPERATION */
+
+    /* Determine if there is 32-bit FAT additional information sector. */
+    if (media_ptr -> fx_media_FAT32_additional_info_sector)
+    {
+
+    UCHAR *buffer_ptr;
+    ULONG  signature;
+
+
+        /* Yes, read the FAT32 additional information sector to get the available cluster count and
+           the hint for the first available cluster.  */
+
+#ifndef FX_DISABLE_CACHE
+        /* Setup a pointer to the first cached entry's buffer.  */
+        buffer_ptr =  (media_ptr -> fx_media_sector_cache_list_ptr) -> fx_cached_sector_memory_buffer;
+
+        /* Invalidate this cache entry.  */
+        (media_ptr -> fx_media_sector_cache_list_ptr) -> fx_cached_sector =  (~((ULONG64) 0));
+        (media_ptr -> fx_media_sector_cache_list_ptr) -> fx_cached_sector_valid =  FX_FALSE;
+#else
+        buffer_ptr =  media_ptr -> fx_media_memory_buffer;
+        media_ptr -> fx_media_memory_buffer_sector = (ULONG64)-1;
+#endif /* FX_DISABLE_CACHE */
+
+        /* Read the FAT32 additional information sector from the device.  */
+        media_ptr -> fx_media_driver_request =          FX_DRIVER_READ;
+        media_ptr -> fx_media_driver_status =           FX_IO_ERROR;
+        media_ptr -> fx_media_driver_buffer =           buffer_ptr;
+        media_ptr -> fx_media_driver_logical_sector =   media_ptr -> fx_media_FAT32_additional_info_sector;
+        media_ptr -> fx_media_driver_sectors =          1;
+        media_ptr -> fx_media_driver_sector_type =      FX_DIRECTORY_SECTOR;
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+        /* Increment the number of driver read sector(s) requests.  */
+        media_ptr -> fx_media_driver_read_requests++;
+#endif
+
+        /* If trace is enabled, insert this event into the trace buffer.  */
+        FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_READ, media_ptr, media_ptr -> fx_media_FAT32_additional_info_sector, 1, buffer_ptr, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+        /* Invoke the driver to read the FAT32 additional information sector.  */
+        (media_ptr -> fx_media_driver_entry) (media_ptr);
+
+        /* Determine if the FAT32 sector was read correctly. */
+        if (media_ptr -> fx_media_driver_status == FX_SUCCESS)
+        {
+
+            /* Yes, setup a pointer into the FAT32 additional information sector.  */
+            buffer_ptr =  media_ptr -> fx_media_driver_buffer;
+
+            /* Pickup the first signature long word.  */
+            signature =  _fx_utility_32_unsigned_read(&buffer_ptr[0]);
+
+            /* Determine if the signature is correct.  */
+            if (signature == 0x41615252)
+            {
+
+                /* Yes, the first signature is correct, now pickup the next signature.  */
+                signature =  _fx_utility_32_unsigned_read(&buffer_ptr[484]);
+
+                /* Determine if this signature is correct.  */
+                if (signature == 0x61417272)
+                {
+
+                    /* Yes, we have a good FAT32 additional information sector.  */
+
+                    /* Pickup the current available cluster count on the media.  */
+                    media_ptr -> fx_media_available_clusters =  _fx_utility_32_unsigned_read(&buffer_ptr[488]);
+
+                    /* Initialize the last reported available cluster count to the same value.  */
+                    media_ptr -> fx_media_FAT32_additional_info_last_available =  media_ptr -> fx_media_available_clusters;
+
+                    /* Pickup the hint for the starting free cluster search.  */
+                    media_ptr -> fx_media_cluster_search_start =  _fx_utility_32_unsigned_read(&buffer_ptr[492]);
+
+                    /* Perform a quick sanity check on the available cluster count and the starting free
+                       cluster search.  */
+                    if ((media_ptr -> fx_media_available_clusters > media_ptr -> fx_media_total_clusters) ||
+                        (media_ptr -> fx_media_cluster_search_start > media_ptr -> fx_media_total_clusters + FX_FAT_ENTRY_START) ||
+                        (media_ptr -> fx_media_cluster_search_start < FX_FAT_ENTRY_START))
+                    {
+
+                        /* Something is wrong, clear the available cluster count and search so the regular processing
+                           is used.  */
+                        media_ptr -> fx_media_available_clusters =    0;
+                        media_ptr -> fx_media_cluster_search_start =  0;
+
+                        /* We don't invalidate the additional info sector here because only the data is bad.  */
+                    }
+                }
+                else
+                {
+
+                    /* Signature is bad, invalidate the additional info sector.  */
+                    media_ptr -> fx_media_FAT32_additional_info_sector =  0;
+                }
+            }
+            else
+            {
+
+                /* Signature is bad, invalidate the additional info sector.  */
+                media_ptr -> fx_media_FAT32_additional_info_sector =  0;
+            }
+        }
+        else
+        {
+
+            /* IO error trying to read additional information sector, invalidate the additional info sector.  */
+            media_ptr -> fx_media_FAT32_additional_info_sector =  0;
+        }
+    }
+
+    /* Search the media to find the first available cluster as well as the total
+       available clusters.  */
+
+    /* Determine what type of FAT is present.  */
+    if (media_ptr -> fx_media_12_bit_FAT)
+    {
+
+        /* A 12-bit FAT is present.  Utilize the FAT entry read utility to pickup
+           each FAT entry's contents.  */
+
+        /* Loop to read each cluster entry in the first FAT.  */
+        for (cluster_number =  FX_FAT_ENTRY_START;
+             cluster_number < (media_ptr -> fx_media_total_clusters) + FX_FAT_ENTRY_START;
+             cluster_number++)
+        {
+
+            /* Read a FAT entry.  */
+            status =  _fx_utility_FAT_entry_read(media_ptr, cluster_number, &FAT_entry);
+
+            /* Determine if the read was successful.  */
+            if (status != FX_SUCCESS)
+            {
+
+                /* Build the "uninitialize" I/O driver request.  */
+                media_ptr -> fx_media_driver_request =      FX_DRIVER_UNINIT;
+                media_ptr -> fx_media_driver_status =       FX_IO_ERROR;
+
+                /* If trace is enabled, insert this event into the trace buffer.  */
+                FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_UNINIT, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+                /* Call the specified I/O driver with the uninitialize request.  */
+                (media_ptr -> fx_media_driver_entry) (media_ptr);
+
+                return(FX_FAT_READ_ERROR);
+            }
+
+            /* Now determine if the FAT entry is available.  */
+            if (FAT_entry == FX_FREE_CLUSTER)
+            {
+
+                /* Increment the number of available clusters.  */
+                media_ptr -> fx_media_available_clusters++;
+
+                /* Determine if the starting free cluster has been found yet.  */
+                if (media_ptr -> fx_media_cluster_search_start == 0)
+                {
+
+                    /* Remember the first free cluster to start further searches from.  */
+                    media_ptr -> fx_media_cluster_search_start =  cluster_number;
+                }
+            }
+        }
+    }
+#ifdef FX_ENABLE_EXFAT
+    else if ((media_ptr -> fx_media_available_clusters == 0)
+             && (media_ptr -> fx_media_FAT_type != FX_exFAT))
+#else
+    else if (media_ptr -> fx_media_available_clusters == 0)
+#endif /* FX_ENABLE_EXFAT */
+    {
+
+        /* A 16 or 32-bit FAT is present. Read directly into the logical sector
+           cache memory to optimize I/O on larger devices. Since we are looking for
+           values of zero, endian issues are not important.  */
+
+        /* Invalidate the current logical sector cache.  */
+        _fx_utility_logical_sector_flush(media_ptr, ((ULONG64) 1), (ULONG64) (media_ptr -> fx_media_total_sectors), FX_TRUE);
+
+        /* Reset the memory pointer.  */
+        media_ptr -> fx_media_memory_buffer =  original_memory_ptr;
+
+        /* Loop through all FAT sectors in the primary FAT.  The first two entries are
+           examined in this loop, but they are always unavailable.  */
+        cluster_number =  0;
+#ifndef FX_DISABLE_CACHE
+        for (i = 0; i < media_ptr -> fx_media_sectors_per_FAT; i = i + media_ptr -> fx_media_sector_cache_size)
+        {
+
+            /* Calculate the starting next FAT sector.  */
+            FAT_sector =  media_ptr -> fx_media_reserved_sectors + i;
+
+            /* Calculate how many sectors to read.  */
+            FAT_read_sectors =  media_ptr -> fx_media_sectors_per_FAT - i;
+
+            /* Determine if there is not enough memory to read the remaining FAT sectors.  */
+            if (FAT_read_sectors > media_ptr -> fx_media_sector_cache_size)
+            {
+                FAT_read_sectors =  media_ptr -> fx_media_sector_cache_size;
+            }
+#else
+        for (i = 0; i < media_ptr -> fx_media_sectors_per_FAT; i++)
+        {
+
+            /* Calculate the starting next FAT sector.  */
+            FAT_sector =  media_ptr -> fx_media_reserved_sectors + i;
+
+            /* Calculate how many sectors to read.  */
+            FAT_read_sectors =  1;
+#endif /* FX_DISABLE_CACHE */
+
+            /* Read the FAT sectors directly from the driver.  */
+            media_ptr -> fx_media_driver_request =          FX_DRIVER_READ;
+            media_ptr -> fx_media_driver_status =           FX_IO_ERROR;
+            media_ptr -> fx_media_driver_buffer =           media_ptr -> fx_media_memory_buffer;
+            media_ptr -> fx_media_driver_logical_sector =   FAT_sector;
+            media_ptr -> fx_media_driver_sectors =          FAT_read_sectors;
+            media_ptr -> fx_media_driver_sector_type =      FX_FAT_SECTOR;
+
+            /* If trace is enabled, insert this event into the trace buffer.  */
+            FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_READ, media_ptr, FAT_sector, FAT_read_sectors, media_ptr -> fx_media_memory_buffer, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+            /* Invoke the driver to read the FAT sectors.  */
+            (media_ptr -> fx_media_driver_entry) (media_ptr);
+
+            /* Determine if the read was successful.  */
+            if (media_ptr -> fx_media_driver_status != FX_SUCCESS)
+            {
+
+                /* Build the "uninitialize" I/O driver request.  */
+                media_ptr -> fx_media_driver_request =      FX_DRIVER_UNINIT;
+                media_ptr -> fx_media_driver_status =       FX_IO_ERROR;
+
+                /* If trace is enabled, insert this event into the trace buffer.  */
+                FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_UNINIT, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+                /* Call the specified I/O driver with the uninitialize request.  */
+                (media_ptr -> fx_media_driver_entry) (media_ptr);
+
+                return(FX_FAT_READ_ERROR);
+            }
+
+            /* Calculate the number of bytes in the buffer.  */
+            bytes_in_buffer =  (media_ptr -> fx_media_bytes_per_sector * FAT_read_sectors);
+
+            /* Walk through the sector cache memory to search for available clusters and the first
+               available if not already found.  */
+            for (j = 0; j < bytes_in_buffer;)
+            {
+
+                /* Check for a 32-bit FAT.  */
+                if (media_ptr -> fx_media_32_bit_FAT)
+                {
+
+                    /* Pickup 32-bit FAT entry.  */
+                    FAT_entry =  *((ULONG *)&(media_ptr -> fx_media_memory_buffer[j]));
+
+                    /* Advance to next FAT entry.  */
+                    j = j + 4;
+                }
+                else
+                {
+
+                    /* Process a 16-bit FAT entry.  */
+                    FAT_entry =  (((ULONG)(media_ptr -> fx_media_memory_buffer[j])) & 0xFF) |
+                        ((((ULONG)(media_ptr -> fx_media_memory_buffer[j + 1])) & 0xFF) << 8);
+
+                    /* Advance to next FAT entry.  */
+                    j =  j + 2;
+                }
+
+                /* Determine if the FAT entry is free.  */
+                if (FAT_entry == FX_FREE_CLUSTER)
+                {
+
+                    /* Entry is free, increment available clusters.  */
+                    media_ptr -> fx_media_available_clusters++;
+
+                    /* Determine if the starting free cluster has been found yet.  */
+                    if (media_ptr -> fx_media_cluster_search_start == 0)
+                    {
+
+                        /* Remember the first free cluster to start further searches from.  */
+                        media_ptr -> fx_media_cluster_search_start =  cluster_number;
+                    }
+                }
+
+                /* Increment the cluster number.  */
+                cluster_number++;
+
+                /* Determine if we have reviewed all FAT entries.  */
+                if (cluster_number >= (media_ptr -> fx_media_total_clusters + FX_FAT_ENTRY_START))
+                {
+
+                    /* Yes, we have looked at all the FAT entries.  */
+
+                    /* Ensure that the outer loop terminates as well.  */
+                    i = media_ptr -> fx_media_sectors_per_FAT;
+                    break;
+                }
+            }
+        }
+    }
+#ifdef FX_ENABLE_EXFAT
+    else if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+        status = _fx_utility_exFAT_bitmap_initialize(media_ptr);
+
+        if ((FX_SUCCESS         != status)  &&
+            (FX_NO_MORE_SPACE   != status))
+        {
+            return(status);
+        }
+    }
+#endif /* FX_ENABLE_EXFAT */
+
+    /* If there were no free clusters, just set the search pointer to the
+       first cluster number.  */
+    if (media_ptr -> fx_media_cluster_search_start == 0)
+    {
+        media_ptr -> fx_media_cluster_search_start =  FX_FAT_ENTRY_START;
+    }
+
+    /* Setup the current working directory fields to default to the root
+       directory.  */
+    media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_name =
+        media_ptr -> fx_media_default_path.fx_path_name_buffer;
+    media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_short_name[0] =  0;
+    media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_name[0] =        0;
+    media_ptr -> fx_media_default_path.fx_path_string[0] =                      (CHAR)0;
+    media_ptr -> fx_media_default_path.fx_path_string[FX_MAXIMUM_PATH - 1] =      (CHAR)0;
+    media_ptr -> fx_media_default_path.fx_path_current_entry =                         0;
+
+#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
+
+    /* Invalidate the previously found directory entry.  */
+    media_ptr -> fx_media_last_found_name[0] =  0;
+#endif
+
+#ifndef FX_DISABLE_FORCE_MEMORY_OPERATION
+    /* Initialize the opened file linked list and associated counter.  */
+    media_ptr -> fx_media_opened_file_list =      FX_NULL;
+    media_ptr -> fx_media_opened_file_count =     0;
+#endif /* FX_DISABLE_FORCE_MEMORY_OPERATION */
+
+    /* Create the media protection structure if FX_SINGLE_THREAD is not
+       defined.  */
+#ifndef FX_SINGLE_THREAD
+
+#ifndef FX_DONT_CREATE_MUTEX
+
+    /* Create ThreadX mutex for protection.  */
+    tx_mutex_create(&(media_ptr -> fx_media_protect), "FileX Media Mutex", TX_NO_INHERIT);
+#endif
+
+#endif
+
+#ifdef FX_DONT_CREATE_MUTEX
+
+    /* Load the media ID field in the media control block.  This allows the FX_PROTECT
+       call to succeed.  */
+    media_ptr -> fx_media_id =  (ULONG)FX_MEDIA_ID;
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+#endif
+
+    /* Lockout interrupts.  */
+    FX_DISABLE_INTS
+
+    /* At this point, the media has been opened successfully.  Place the
+       media on the linked list of currently opened media.  */
+
+    /* Load the media ID field in the media control block.  */
+    media_ptr -> fx_media_id =  (ULONG)FX_MEDIA_ID;
+
+    /* Place the thread on the list of opened media.  First,
+       check for an empty list.  */
+    if (_fx_system_media_opened_ptr)
+    {
+
+        /* Pickup tail pointer.  */
+        tail_ptr =  _fx_system_media_opened_ptr -> fx_media_opened_previous;
+
+        /* Place the new media in the list.  */
+        _fx_system_media_opened_ptr -> fx_media_opened_previous =  media_ptr;
+        tail_ptr -> fx_media_opened_next =  media_ptr;
+
+        /* Setup this media's opened links.  */
+        media_ptr -> fx_media_opened_previous =  tail_ptr;
+        media_ptr -> fx_media_opened_next =      _fx_system_media_opened_ptr;
+    }
+    else
+    {
+
+        /* The opened media list is empty.  Add the media to empty list.  */
+        _fx_system_media_opened_ptr =           media_ptr;
+        media_ptr -> fx_media_opened_next =     media_ptr;
+        media_ptr -> fx_media_opened_previous = media_ptr;
+    }
+
+    /* Increment the opened media counter.  */
+    _fx_system_media_opened_count++;
+
+    /* Invoke media open callback. */
+    if (media_ptr -> fx_media_open_notify)
+    {
+        media_ptr -> fx_media_open_notify(media_ptr);
+    }
+
+    /* Restore interrupts.  */
+    FX_RESTORE_INTS
+
+#ifdef FX_DONT_CREATE_MUTEX
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+#endif
+
+    /* Return a successful status.  */
+    return(FX_SUCCESS);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_open_notify_set.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_open_notify_set.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_open_notify_set.c	(revision 30)
@@ -0,0 +1,82 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_media.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_media_open_notify_set                           PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function sets the notify function called when media is open.   */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    media_open_notify                     Notify function called when   */
+/*                                            media is open               */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    FX_SUCCESS                                                          */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_media_open_notify_set(FX_MEDIA *media_ptr, VOID (*media_open_notify)(FX_MEDIA *media))
+{
+
+    /* Set the notify function. */
+    media_ptr -> fx_media_open_notify = media_open_notify;
+
+    /* Return successful status.  */
+    return(FX_SUCCESS);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_read.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_read.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_read.c	(revision 30)
@@ -0,0 +1,127 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_media.h"
+#include "fx_utility.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_media_read                                      PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function reads the specified raw logical sector from the       */
+/*    specified media.                                                    */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    logical_sector                        Logical sector to read        */
+/*    buffer_ptr                            Pointer to caller's buffer    */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_logical_sector_read       Logical sector read utility   */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_media_read(FX_MEDIA *media_ptr, ULONG logical_sector, VOID *buffer_ptr)
+{
+
+UINT                   status;
+
+#ifdef TX_ENABLE_EVENT_TRACE
+TX_TRACE_BUFFER_ENTRY *trace_event;
+ULONG                  trace_timestamp;
+#endif
+
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of times this service has been called.  */
+    media_ptr -> fx_media_reads++;
+#endif
+
+    /* Check the media to make sure it is open.  */
+    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
+    {
+
+        /* Return the media not opened error.  */
+        return(FX_MEDIA_NOT_OPEN);
+    }
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_MEDIA_READ, media_ptr, logical_sector, buffer_ptr, 0, FX_TRACE_MEDIA_EVENTS, &trace_event, &trace_timestamp)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+    /* Read the logical sector.  */
+    status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) logical_sector, buffer_ptr, ((ULONG) 1), FX_DATA_SECTOR);
+
+#ifdef TX_ENABLE_EVENT_TRACE
+
+    /* Check for successful status.  */
+    if (status == FX_SUCCESS)
+    {
+
+        /* Update the trace event with the bytes read.  */
+        FX_TRACE_EVENT_UPDATE(trace_event, trace_timestamp, FX_TRACE_MEDIA_READ, 0, 0, 0, media_ptr -> fx_media_bytes_per_sector)
+    }
+#endif
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_space_available.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_space_available.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_space_available.c	(revision 30)
@@ -0,0 +1,107 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_media.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_media_space_available                           PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function returns the number of bytes available in the          */
+/*    specified media.                                                    */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    available_bytes_ptr                   Pointer to available bytes    */
+/*                                            destination                 */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*    _fx_media_extended_space_available    Actual space available service*/
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_media_space_available(FX_MEDIA *media_ptr, ULONG *available_bytes_ptr)
+{
+
+UINT    status;
+ULONG64 available_bytes;
+
+    /* Call actual media space available service.  */
+    status = _fx_media_extended_space_available(media_ptr, &available_bytes);
+
+    /* Check status.  */
+    if (status == FX_SUCCESS)
+    {
+
+        /* Determine if more than 4GB available.  */
+        if (available_bytes > 0x00000000FFFFFFFF)
+        {
+
+            /* Yes, we must have more than 4GB available... report the maximum we can fit
+               in 32bits, which is 4GB.  */
+            *available_bytes_ptr = 0xFFFFFFFF;
+        }
+        else
+        {
+            *available_bytes_ptr = (ULONG)(available_bytes);
+        }
+    }
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_volume_get.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_volume_get.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_volume_get.c	(revision 30)
@@ -0,0 +1,92 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_directory.h"
+#include "fx_media.h"
+#include "fx_utility.h"
+#ifdef FX_ENABLE_EXFAT
+#include "fx_directory_exFAT.h"
+#endif /* FX_ENABLE_EXFAT */
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_media_volume_get                                PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function reads the volume name stored in the media's boot      */
+/*    record or root directory.                                           */
+/*                                                                        */
+/*    Note, this API is deprecated as fx_media_volume_get_extended should */
+/*    be used. The maximum written size to volume_name could be 12.       */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    volume_name                           Pointer to destination for    */
+/*                                            the volume name (maximum    */
+/*                                            11 characters + NULL)       */
+/*    volume_source                         Source of volume              */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_media_volume_get_extended         Actual media volume get       */
+/*                                            service                     */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_media_volume_get(FX_MEDIA *media_ptr, CHAR *volume_name, UINT volume_source)
+{
+
+    /* Call the extended version with 12 bytes volume name length.  */
+    return(_fx_media_volume_get_extended(media_ptr, volume_name, 12, volume_source));
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_volume_get_extended.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_volume_get_extended.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_volume_get_extended.c	(revision 30)
@@ -0,0 +1,380 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_directory.h"
+#include "fx_media.h"
+#include "fx_utility.h"
+#ifdef FX_ENABLE_EXFAT
+#include "fx_directory_exFAT.h"
+#endif /* FX_ENABLE_EXFAT */
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_media_volume_get_extended                       PORTABLE C      */
+/*                                                           6.1.11       */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function reads the volume name stored in the media's boot      */
+/*    record or root directory.                                           */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    volume_name                           Pointer to destination for    */
+/*                                            the volume name (maximum    */
+/*                                            11 characters + NULL)       */
+/*    volume_name_buffer_length             Buffer length for volume_name */
+/*    volume_source                         Source of volume              */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_logical_sector_read       Read directory sector         */
+/*    _fx_directory_entry_read              Directory entry read          */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*  04-25-2022     Bhupendra Naphade        Modified comment(s), and      */
+/*                                            updated check for           */
+/*                                            volume name,                */
+/*                                            resulting in version 6.1.11 */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_media_volume_get_extended(FX_MEDIA *media_ptr, CHAR *volume_name, UINT volume_name_buffer_length, UINT volume_source)
+{
+
+UINT         status, offset;
+ULONG        i;
+INT          j;
+
+#ifdef FX_ENABLE_EXFAT
+ULONG        character_count;
+#endif /* FX_ENABLE_EXFAT */
+FX_DIR_ENTRY dir_entry;
+
+
+    /* Clear the volume name.  */
+    volume_name[0] =  FX_NULL;
+
+    /* Check the media to make sure it is open.  */
+    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
+    {
+
+        /* Return the media not opened error.  */
+        return(FX_MEDIA_NOT_OPEN);
+    }
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_MEDIA_VOLUME_GET, media_ptr, volume_name, volume_source, 0, FX_TRACE_MEDIA_EVENTS, 0, 0)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+#ifdef FX_ENABLE_EXFAT
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+        volume_source = FX_DIRECTORY_SECTOR;
+    }
+#endif /* FX_ENABLE_EXFAT */
+
+    /* Ensure the volume name is NULL initially.  */
+    volume_name[0] =  FX_NULL;
+
+    if (volume_source == FX_DIRECTORY_SECTOR)
+    {
+
+        /* Setup pointer to media name buffer.  */
+        dir_entry.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer;
+
+        /* Clear the short name string.  */
+        dir_entry.fx_dir_entry_short_name[0] =  0;
+
+        /* Attempt to find the volume name in the root directory.  */
+        i =  0;
+        do
+        {
+
+            /* Read an entry from the root directory.  */
+            status =  _fx_directory_entry_read(media_ptr, FX_NULL, &i, &dir_entry);
+
+            /* Check for error status.  */
+            if (status != FX_SUCCESS)
+            {
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* Return to caller.  */
+                return(status);
+            }
+
+            /* Check for a volume name.  */
+#ifdef FX_ENABLE_EXFAT
+            if (((media_ptr -> fx_media_FAT_type == FX_exFAT) && ((dir_entry.fx_dir_entry_attributes & FX_VOLUME) || (dir_entry.fx_dir_entry_type == FX_EXFAT_DIR_ENTRY_TYPE_VOLUME_LABEL))) 
+                    || ((media_ptr -> fx_media_FAT_type != FX_exFAT) && (dir_entry.fx_dir_entry_attributes & FX_VOLUME) && ((UCHAR)dir_entry.fx_dir_entry_name[0] != (UCHAR)FX_DIR_ENTRY_FREE)))
+#else
+            if ((dir_entry.fx_dir_entry_attributes & FX_VOLUME) && ((UCHAR)dir_entry.fx_dir_entry_name[0] != (UCHAR)FX_DIR_ENTRY_FREE))
+#endif /* FX_ENABLE_EXFAT */
+            {
+
+                /* Yes, we have found a previously set volume name.  */
+                break;
+            }
+
+            /* Move to next directory entry.  */
+            i++;
+        } while (i < media_ptr -> fx_media_root_directory_entries);
+
+        /* Determine if a volume entry has been found.  */
+        if (i < media_ptr -> fx_media_root_directory_entries)
+        {
+
+            /* Read the logical directory sector.  */
+            status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) dir_entry.fx_dir_entry_log_sector,
+                                                      media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
+
+            /* Determine if an error occurred.  */
+            if (status != FX_SUCCESS)
+            {
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* Return error code.  */
+                return(status);
+            }
+
+            /* Offset to volume label entry.  */
+            offset = dir_entry.fx_dir_entry_byte_offset;
+
+#ifdef FX_ENABLE_EXFAT
+            if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+            {
+
+                /* Read character count of volume label.  */
+                character_count = media_ptr -> fx_media_memory_buffer[offset + FX_EXFAT_CHAR_COUNT];
+
+                /* Check if the buffer is too short for the name.  */
+                if (character_count >= volume_name_buffer_length)
+                {
+
+                    /* Buffer too short, return error.  */
+                    status =  FX_BUFFER_ERROR;
+
+                    /* Set character count to fit for the buffer.  */
+                    character_count = volume_name_buffer_length - 1;
+                }
+
+                /* Move to volume label field.  */
+                offset += FX_EXFAT_VOLUME_LABEL;
+
+                for (i = 0; i < character_count; i++)
+                {
+
+                    /* Read one character of volume label.  */
+                    volume_name[i] = (CHAR)_fx_utility_16_unsigned_read(&media_ptr -> fx_media_memory_buffer[offset]);
+
+                    /* Move to next character.  */
+                    offset += 2;
+                }
+
+                /* NULL terminate the volume name.  */
+                volume_name[i] =  FX_NULL;
+            }
+            else
+            {
+#endif /* FX_ENABLE_EXFAT */
+
+                /* Skip trailing space characters of volume name. */
+                for (j = 10; j >= 0; j--)
+                {
+
+                    /* Check for space character.  */
+                    if (media_ptr -> fx_media_memory_buffer[offset + (UINT)j] != (UCHAR)' ')
+                    {
+
+                        /* Last character found. */
+                        break;
+                    }
+                }
+
+                /* Check if the buffer is too short for the name.  */
+                if (j >= (INT)volume_name_buffer_length - 1)
+                {
+
+                    /* Buffer too short, return error.  */
+                    status =  FX_BUFFER_ERROR;
+
+                    /* Set character count to fit for the buffer.  */
+                    j = (INT)volume_name_buffer_length - 2;
+                }
+
+                /* NULL terminate the volume name.  */
+                volume_name[j + 1] =  FX_NULL;
+
+                /* Pickup the remaining characters of the volume name from the boot sector.  */
+                for (; j >= 0; j--)
+                {
+
+                    /* Pickup byte of volume name.  */
+                    volume_name[j] =  (CHAR)media_ptr -> fx_media_memory_buffer[offset + (UINT)j];
+                }
+#ifdef FX_ENABLE_EXFAT
+            }
+#endif /* FX_ENABLE_EXFAT */
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* Return the completion status.  */
+            return(status);
+        }
+    }
+
+    /* Read volume name from boot record.  */
+    /* Read the logical directory sector 0 - we just do this to get a memory_buffer pointer */
+    status =  _fx_utility_logical_sector_read(media_ptr, ((ULONG64) 0),
+                                              media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DATA_SECTOR);
+
+    /* Check the return status.  */
+    if (status != FX_SUCCESS)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the error status.  */
+        return(status);
+    }
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of driver read boot sector requests.  */
+    media_ptr -> fx_media_driver_boot_read_requests++;
+#endif
+
+    /* Build the driver request to read the boot record.  */
+    media_ptr -> fx_media_driver_request =      FX_DRIVER_BOOT_READ;
+    media_ptr -> fx_media_driver_status =       FX_IO_ERROR;
+    media_ptr -> fx_media_driver_buffer =       media_ptr -> fx_media_memory_buffer;
+    media_ptr -> fx_media_driver_sectors =      1;
+    media_ptr -> fx_media_driver_sector_type =  FX_BOOT_SECTOR;
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_BOOT_READ, media_ptr, media_ptr -> fx_media_memory_buffer, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+    /* Invoke the driver to read the boot sector.  */
+    (media_ptr -> fx_media_driver_entry) (media_ptr);
+
+    /* Determine if the request is successful.  */
+    if (media_ptr -> fx_media_driver_status)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* An error occurred in the driver.  */
+        return(media_ptr -> fx_media_driver_status);
+    }
+
+    /* Calculate the offset to the volume name based on the type of FAT.  */
+    if (media_ptr -> fx_media_32_bit_FAT)
+    {
+
+        /* FAT32 offset to volume name.  */
+        offset =  FX_VOLUME_LABEL_32;
+    }
+    else
+    {
+
+        /* FAT12/16 offset to volume name.  */
+        offset =  FX_VOLUME_LABEL;
+    }
+
+    /* Skip trailing space characters of volume name. */
+    for (j = 10; j >= 0; j--)
+    {
+
+        /* Check for space character.  */
+        if (media_ptr -> fx_media_memory_buffer[offset + (UINT)j] != (UCHAR)' ')
+        {
+
+            /* Last character found. */
+            break;
+        }
+    }
+    
+    /* Check if the buffer is too short for the name.  */
+    if (j >= (INT)volume_name_buffer_length - 1)
+    {
+
+        /* Buffer too short, return error.  */
+        status =  FX_BUFFER_ERROR;
+
+        /* Set character count to fit for the buffer.  */
+        j = (INT)volume_name_buffer_length - 2;
+    }
+
+    /* NULL terminate the volume name.  */
+    volume_name[j + 1] =  FX_NULL;
+
+    /* Pickup the remaining characters of the volume name from the boot sector.  */
+    for (; j >= 0; j--)
+    {
+
+        /* Pickup byte of volume name.  */
+        volume_name[j] =  (CHAR)media_ptr -> fx_media_memory_buffer[offset + (UINT)j];
+    }
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* Return the completion status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_volume_set.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_volume_set.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_volume_set.c	(revision 30)
@@ -0,0 +1,564 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_directory.h"
+#include "fx_media.h"
+#include "fx_utility.h"
+#ifdef FX_ENABLE_EXFAT
+#include "fx_directory_exFAT.h"
+#endif /* FX_ENABLE_EXFAT */
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_media_volume_set                                PORTABLE C      */
+/*                                                           6.1.7        */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function sets the volume name to the name supplied by the      */
+/*    caller.                                                             */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    volume_name                           New volume name               */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_entry_read              Read a directory entry        */
+/*    _fx_utility_logical_sector_read       Read directory sector         */
+/*    _fx_utility_logical_sector_write      Write directory sector        */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*  06-02-2021     Bhupendra Naphade        Modified comment(s),updated   */
+/*                                            the initialization of       */
+/*                                            dir_entry for exFAT format, */
+/*                                            resulting in version 6.1.7  */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_media_volume_set(FX_MEDIA *media_ptr, CHAR *volume_name)
+{
+
+ULONG        i, j;
+FX_DIR_ENTRY dir_entry, dir_entry1;
+UINT         status, offset;
+UCHAR       *work_ptr;
+CHAR         alpha;
+
+
+    /* Check the media to make sure it is open.  */
+    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
+    {
+
+        /* Return the media not opened error.  */
+        return(FX_MEDIA_NOT_OPEN);
+    }
+
+    dir_entry.fx_dir_entry_log_sector = 0;
+    dir_entry.fx_dir_entry_byte_offset = 0;
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_MEDIA_VOLUME_SET, media_ptr, volume_name, 0, 0, FX_TRACE_MEDIA_EVENTS, 0, 0)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+#ifdef FX_ENABLE_EXFAT
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+
+        /* Setup pointer to media name buffer.  */
+        dir_entry.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer;
+
+        /* Clear the short name string.  */
+        dir_entry.fx_dir_entry_short_name[0] =  0;
+
+        /* Attempt to find the volume name in the root directory.  */
+        i =  0;
+        do
+        {
+
+            /* Read an entry from the root directory.  */
+            status =  _fx_directory_entry_read(media_ptr, FX_NULL, &i, &dir_entry);
+
+            /* Check for error status.  */
+            if (status != FX_SUCCESS)
+            {
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* Return to caller.  */
+                return(status);
+            }
+
+            /* Check for a volume name.  */
+            if (dir_entry.fx_dir_entry_type == FX_EXFAT_DIR_ENTRY_TYPE_VOLUME_LABEL)
+            {
+
+                /* Yes, we have found a previously set volume name.  */
+                break;
+            }
+
+            /* Move to next directory entry.  */
+            i++;
+        } while (i < media_ptr -> fx_media_root_directory_entries);
+
+        /* Determine if a volume entry has been found.  */
+        if (i == media_ptr -> fx_media_root_directory_entries)
+        {
+
+            /* Volume entry not found, attempt to find a free entry in the root directory.  */
+            i =  0;
+            do
+            {
+
+                /* Read an entry from the root directory.  */
+                status =  _fx_directory_entry_read(media_ptr, FX_NULL, &i, &dir_entry);
+
+                /* Check for error status.  */
+                if (status != FX_SUCCESS)
+                {
+
+                    /* Release media protection.  */
+                    FX_UNPROTECT
+
+                    /* Return to caller.  */
+                    return(status);
+                }
+
+                /* Check for a volume name.  */
+                if (dir_entry.fx_dir_entry_type == FX_EXFAT_DIR_ENTRY_TYPE_FREE)
+                {
+
+                    /* Yes, we have found a free directory entry.  */
+                    break;
+                }
+
+                /* Move to next directory entry.  */
+                i++;
+            } while (i < media_ptr -> fx_media_root_directory_entries);
+
+            /* Determine if a free entry has been found.  */
+            if (i == media_ptr -> fx_media_root_directory_entries)
+            {
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* No existing volume name was found, return an error.  */
+                return(FX_NOT_FOUND);
+            }
+        }
+
+        /* Read the logical directory sector.  */
+        status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) dir_entry.fx_dir_entry_log_sector,
+                                                  media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
+
+        /* Determine if an error occurred.  */
+        if (status != FX_SUCCESS)
+        {
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* Return error code.  */
+            return(status);
+        }
+
+        /* Offset to volume label field.  */
+        offset = dir_entry.fx_dir_entry_byte_offset + FX_EXFAT_VOLUME_LABEL;
+
+        /* Loop to store the volume name.  */
+        for (i = 0; volume_name[i]; i++)
+        {
+
+            /* Have we reached the end?  */
+            if (i == 11)
+            {
+
+                break;
+            }
+
+            /* Pickup volume name byte.  */
+            alpha =  volume_name[i];
+
+            /* Store a byte of the volume name.  */
+            _fx_utility_16_unsigned_write(&media_ptr -> fx_media_memory_buffer[offset], (UINT)alpha);
+
+            /* Move to next character.  */
+            offset += 2;
+        }
+
+        /* Offset to character count field.  */
+        offset = dir_entry.fx_dir_entry_byte_offset;
+
+        /* Store volume label entry type.  */
+        media_ptr -> fx_media_memory_buffer[offset] = FX_EXFAT_DIR_ENTRY_TYPE_VOLUME_LABEL;
+
+        /* Store the character count.  */
+        media_ptr -> fx_media_memory_buffer[offset + FX_EXFAT_CHAR_COUNT] = (UCHAR)i;
+
+        /* Write the directory sector to the media.  */
+        status =  _fx_utility_logical_sector_write(media_ptr, (ULONG64) dir_entry.fx_dir_entry_log_sector,
+                                                   media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
+    }
+    else
+    {
+#endif /* FX_ENABLE_EXFAT */
+
+        /* First, check for an invalid volume name.  */
+        if (volume_name[0] == 0)
+        {
+
+            /* Yes, volume name is invalid.  Return an error.  */
+            return(FX_INVALID_NAME);
+        }
+
+        /* Read the logical directory sector 0 - we just do this to get a memory_buffer pointer */
+        status =  _fx_utility_logical_sector_read(media_ptr, ((ULONG64) 0),
+                                                  media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DATA_SECTOR);
+
+        /* Check the read status.  */
+        if (status != FX_SUCCESS)
+        {
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* Return the error status.  */
+            return(status);
+        }
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+        /* Increment the number of driver read boot sector requests.  */
+        media_ptr -> fx_media_driver_boot_read_requests++;
+#endif
+
+        /* Build a driver request to read the boot record.  */
+        media_ptr -> fx_media_driver_request =      FX_DRIVER_BOOT_READ;
+        media_ptr -> fx_media_driver_status =       FX_IO_ERROR;
+        media_ptr -> fx_media_driver_buffer =       media_ptr -> fx_media_memory_buffer;
+        media_ptr -> fx_media_driver_sectors =      1;
+        media_ptr -> fx_media_driver_sector_type =  FX_BOOT_SECTOR;
+
+        /* If trace is enabled, insert this event into the trace buffer.  */
+        FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_BOOT_READ, media_ptr, media_ptr -> fx_media_memory_buffer, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+        /* Invoke the driver to read the boot sector.  */
+        (media_ptr -> fx_media_driver_entry) (media_ptr);
+
+        /* Determine if the request is successful.  */
+        if (media_ptr -> fx_media_driver_status)
+        {
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* An error occurred in the driver.  */
+            return(media_ptr -> fx_media_driver_status);
+        }
+
+        /* Calculate the offset based on the FAT present.  */
+        if (media_ptr -> fx_media_32_bit_FAT)
+        {
+
+            /* FAT32 is present.  */
+            offset =  FX_VOLUME_LABEL_32;
+        }
+        else
+        {
+
+            /* FAT12/16 is present.  */
+            offset =  FX_VOLUME_LABEL;
+        }
+
+        /* Loop to store the volume name.  */
+        for (i = 0; volume_name[i]; i++)
+        {
+
+            /* Have we reached the end?  */
+            if (i == 11)
+            {
+
+                break;
+            }
+
+            /* Pickup volume name byte.  */
+            alpha =  volume_name[i];
+
+            /* Determine if alpha needs to be converted to upper case.  */
+            if ((alpha >= 'a') && (alpha <= 'z'))
+            {
+
+                /* Convert alpha to upper case.  */
+                alpha =  (CHAR)((INT)alpha - 0x20);
+            }
+
+            /* Store a byte of the volume name.  */
+            media_ptr -> fx_media_memory_buffer[offset + i] =  (UCHAR)alpha;
+        }
+
+        /* Now pad with spaces.  */
+        for (; i < 11; i++)
+        {
+
+            /* Append space character to volume name.  */
+            media_ptr -> fx_media_memory_buffer[offset + i] =  0x20;
+        }
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+        /* Increment the number of driver write boot sector requests.  */
+        media_ptr -> fx_media_driver_boot_write_requests++;
+#endif
+
+        /* Write the boot sector with the new volume name.  */
+        media_ptr -> fx_media_driver_request =      FX_DRIVER_BOOT_WRITE;
+        media_ptr -> fx_media_driver_status =       FX_IO_ERROR;
+        media_ptr -> fx_media_driver_buffer =       media_ptr -> fx_media_memory_buffer;
+        media_ptr -> fx_media_driver_sectors =      1;
+        media_ptr -> fx_media_driver_sector_type =  FX_BOOT_SECTOR;
+
+        /* Set the system write flag since we are writing the boot sector.  */
+        media_ptr -> fx_media_driver_system_write =  FX_TRUE;
+
+        /* If trace is enabled, insert this event into the trace buffer.  */
+        FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_BOOT_WRITE, media_ptr, media_ptr -> fx_media_memory_buffer, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+        /* Invoke the driver to write the boot sector.  */
+        (media_ptr -> fx_media_driver_entry) (media_ptr);
+
+        /* Clear the system write flag.  */
+        media_ptr -> fx_media_driver_system_write =  FX_FALSE;
+
+        /* Determine if the request is successful.  */
+        if (media_ptr -> fx_media_driver_status)
+        {
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* An error occurred in the driver.  */
+            return(media_ptr -> fx_media_driver_status);
+        }
+
+        /* Setup pointer to media name buffer.  */
+        dir_entry1.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer;
+
+        /* Clear the short name string.  */
+        dir_entry1.fx_dir_entry_short_name[0] =  0;
+
+        /* Now we need to find the copy of the volume name in the root directory.  */
+        i =  0;
+        j =  media_ptr -> fx_media_root_directory_entries + 1;
+        do
+        {
+
+            /* Read an entry from the root directory.  */
+            status =  _fx_directory_entry_read(media_ptr, FX_NULL, &i, &dir_entry1);
+
+            /* Check for error status.  */
+            if (status != FX_SUCCESS)
+            {
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* Return to caller.  */
+                return(status);
+            }
+
+            /* Determine if this is an empty entry.  */
+            if ((dir_entry1.fx_dir_entry_name[0] == (CHAR)FX_DIR_ENTRY_FREE) && (dir_entry1.fx_dir_entry_short_name[0] == 0))
+            {
+
+                /* Yes, this is free entry.  Is it the first?  */
+                if (i < j)
+                {
+
+                    /* Yes, first free entry - remember it.  */
+                    dir_entry =  dir_entry1;
+                    j =  i;
+                }
+            }
+            /* Determine if the directory entries are exhausted.  */
+            else if (dir_entry1.fx_dir_entry_name[0] == FX_DIR_ENTRY_DONE)
+            {
+
+                /* Yes, this we are at the end of the directory.  Have there
+                been any other free entries?  */
+                if (i < j)
+                {
+
+                    /* No, we need to remember this as the free entry.  */
+                    dir_entry =  dir_entry1;
+                    j =  i;
+                }
+                break;
+            }
+            /* Check for a volume name.  */
+            else if (dir_entry1.fx_dir_entry_attributes & FX_VOLUME)
+            {
+
+                /* Yes, we have found a previously set volume name - use this entry.  */
+                dir_entry =  dir_entry1;
+                j =  i;
+                break;
+            }
+
+            /* Move to next directory entry.  */
+            i++;
+        } while (i < media_ptr -> fx_media_root_directory_entries);
+
+        /* Determine if a volume entry was not found and there are no more empty slots.  */
+        if (i == media_ptr -> fx_media_root_directory_entries)
+        {
+
+            /* Determine if there was a free or previous volume name.  */
+            if (j == (media_ptr -> fx_media_root_directory_entries + 1))
+            {
+        
+                /* No, nothing was available in the root directory.  */
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* No, existing volume name or space in the root directly was found, return an error.  */
+                return(FX_MEDIA_INVALID);
+            }
+        }
+
+        /* Now set the volume name and attribute.  */
+
+        /* Read the logical directory sector.  */
+        status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) dir_entry.fx_dir_entry_log_sector,
+                                                  media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_BOOT_SECTOR);
+
+        /* Check the status of reading the directory entry. */
+        if (status != FX_SUCCESS)
+        {
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* Return the error status.  */
+            return(status);
+        }
+
+        /* Calculate pointer into directory buffer.  */
+        work_ptr =  media_ptr -> fx_media_memory_buffer +
+            (UINT)dir_entry.fx_dir_entry_byte_offset;
+
+        /* Copy the volume name into the directory entry.  */
+        for (i = 0; volume_name[i]; i++)
+        {
+
+            /* Have we reached the end?  */
+            if (i == 11)
+            {
+
+                break;
+            }
+
+            /* Pickup volume name byte.  */
+            alpha =  volume_name[i];
+
+            /* Determine if alpha needs to be converted to upper case.  */
+            if ((alpha >= 'a') && (alpha <= 'z'))
+            {
+
+                /* Convert alpha to upper case.  */
+                alpha =  (CHAR)((INT)alpha - 0x20);
+            }
+
+            /* Store volume name.  */
+            work_ptr[i] =  (UCHAR)alpha;
+        }
+
+        /* Pad with space characters.  */
+        for (; i < 11; i++)
+        {
+            work_ptr[i] =  0x20;
+        }
+
+        /* Set the appropriate attributes.  */
+        work_ptr[11] =  FX_VOLUME | FX_ARCHIVE;
+
+        /* Set the other parts of the volume entry.  */
+
+        /* Clear the hi word of cluster.  */
+        work_ptr[20] =  0;
+        work_ptr[21] =  0;
+
+        /* Clear the low word of cluster.  */
+        work_ptr[26] =  0;
+        work_ptr[27] =  0;
+
+        /* Clear the file size.  */
+        work_ptr[28] =  0;
+        work_ptr[29] =  0;
+        work_ptr[30] =  0;
+        work_ptr[31] =  0;
+
+        /* Write the directory sector to the media.  */
+        status =  _fx_utility_logical_sector_write(media_ptr, (ULONG64) dir_entry.fx_dir_entry_log_sector,
+                                                   media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
+#ifdef FX_ENABLE_EXFAT
+    }
+#endif /* FX_ENABLE_EXFAT */
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* Return the status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_write.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_write.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_media_write.c	(revision 30)
@@ -0,0 +1,138 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_media.h"
+#include "fx_utility.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_media_write                                     PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function writes the specified raw logical sector to the        */
+/*    specified media.                                                    */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    logical_sector                        Logical sector to read        */
+/*    buffer_ptr                            Pointer to caller's buffer    */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_logical_sector_write      Write logical sector utility  */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_media_write(FX_MEDIA *media_ptr, ULONG logical_sector, VOID *buffer_ptr)
+{
+
+UINT                   status;
+
+#ifdef TX_ENABLE_EVENT_TRACE
+TX_TRACE_BUFFER_ENTRY *trace_event;
+ULONG                  trace_timestamp;
+#endif
+
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of times this service has been called.  */
+    media_ptr -> fx_media_writes++;
+#endif
+
+    /* Check the media to make sure it is open.  */
+    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
+    {
+
+        /* Return the media not opened error.  */
+        return(FX_MEDIA_NOT_OPEN);
+    }
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_MEDIA_WRITE, media_ptr, logical_sector, buffer_ptr, 0, FX_TRACE_MEDIA_EVENTS, &trace_event, &trace_timestamp)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+    /* Check for write protect at the media level (set by driver).  */
+    if (media_ptr -> fx_media_driver_write_protect)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return write protect error.  */
+        return(FX_WRITE_PROTECT);
+    }
+
+    /* Write the logical sector.  */
+    status =  _fx_utility_logical_sector_write(media_ptr, (ULONG64) logical_sector, buffer_ptr, ((ULONG) 1), FX_DATA_SECTOR);
+
+#ifdef TX_ENABLE_EVENT_TRACE
+
+    /* Check for successful status.  */
+    if (status == FX_SUCCESS)
+    {
+
+        /* Update the trace event with the bytes written.  */
+        FX_TRACE_EVENT_UPDATE(trace_event, trace_timestamp, FX_TRACE_MEDIA_WRITE, 0, 0, 0, media_ptr -> fx_media_bytes_per_sector)
+    }
+#endif
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_partition_offset_calculate.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_partition_offset_calculate.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_partition_offset_calculate.c	(revision 30)
@@ -0,0 +1,683 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */ 
+/** FileX Component                                                       */ 
+/**                                                                       */
+/**   Application Utility                                                 */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_utility.h"
+
+
+/* Define internal data structures.  */
+
+typedef struct FX_MEDIA_PARTITION_STRUCT
+{
+    ULONG fx_media_part_start;    
+    ULONG fx_media_part_size;
+} FX_MEDIA_PARTITION;
+
+/* Define internal partition constants. */
+
+#ifndef FX_MAX_PARTITION_COUNT
+#define FX_MAX_PARTITION_COUNT              16
+#endif /* FX_MAX_PARTITION_COUNT */
+
+#define FX_PARTITION_TABLE_OFFSET           446
+#define FX_PARTITION_ENTRY_SIZE             16
+#define FX_PARTITION_TYPE_OFFSET            4
+#define FX_PARTITION_LBA_OFFSET             8
+#define FX_PARTITION_SECTORS_OFFSET         12
+
+#define FX_PARTITION_TYPE_FREE              0x00
+#define FX_PARTITION_TYPE_EXTENDED          0x05
+#define FX_PARTITION_TYPE_EXTENDED_LBA      0x0F
+
+
+/* Define function prototypes for the partition table parsing application
+   utility.  */
+
+UINT    _fx_partition_offset_calculate(void  *partition_sector, UINT partition,
+                                     ULONG *partition_start, ULONG *partition_size);
+UINT    _fx_utility_partition_get(FX_MEDIA_PARTITION *partition_table, 
+                                UINT *count, ULONG sector, UCHAR *sector_buffer);
+UINT    _fx_partition_offset_calculate_extended(FX_MEDIA *media_ptr, void  *partition_sector, UINT partition,
+                                     ULONG *partition_start, ULONG *partition_size);
+
+/**************************************************************************/ 
+/*                                                                        */ 
+/*  FUNCTION                                               RELEASE        */ 
+/*                                                                        */ 
+/*    _fx_partition_offset_calculate                      PORTABLE C      */ 
+/*                                                           6.1.6        */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */ 
+/*    This function calculates the sector offset to the specified         */ 
+/*    partition.  The buffer containing the partition table is also       */ 
+/*    supplied to this function.  If the buffer supplied is a boot        */ 
+/*    record (which could be the case in non-partition systems), this     */ 
+/*    function returns an offset of zero, the total sectors, and a        */ 
+/*    successful status indicating that the buffer supplied is the boot   */ 
+/*    record.  Otherwise, if a partition is found, this function returns  */ 
+/*    the sector offset to its boot record along with a successful        */ 
+/*    status. If the specified partition is not found or the buffer is    */ 
+/*    not a partition table or boot record, this function returns an      */ 
+/*    error.                                                              */ 
+/*                                                                        */ 
+/*    Note: Empty partitions have a FX_SUCCESS return code, however their */ 
+/*          starting sector is FX_NULL and the size returned is 0.        */ 
+/*                                                                        */ 
+/*  INPUT                                                                 */ 
+/*                                                                        */ 
+/*    partition_sector                      Pointer to buffer containing  */ 
+/*                                            either the partition table  */ 
+/*                                            or the boot sector          */ 
+/*    partition                             Desired partition             */ 
+/*    partition_start                       Return partition start        */ 
+/*    partition_size                        Return partition size         */ 
+/*                                                                        */ 
+/*  OUTPUT                                                                */ 
+/*                                                                        */ 
+/*    return status                                                       */ 
+/*                                                                        */ 
+/*  CALLS                                                                 */ 
+/*                                                                        */ 
+/*     _fx_utility_partition_get            Actual partition parsing      */ 
+/*                                            routine                     */ 
+/*                                                                        */ 
+/*  CALLED BY                                                             */ 
+/*                                                                        */ 
+/*    Application Driver                                                  */ 
+/*                                                                        */ 
+/*  RELEASE HISTORY                                                       */ 
+/*                                                                        */ 
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*  04-02-2021     William E. Lamie         Modified comment(s),          */
+/*                                            ignored signature check for */
+/*                                            no partition situation,     */
+/*                                            resulting in version 6.1.6  */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_partition_offset_calculate(void  *partition_sector, UINT partition,
+                                     ULONG *partition_start, ULONG *partition_size)
+{
+    
+FX_MEDIA_PARTITION  partition_table[4];
+UINT                count;
+ULONG64             total_sectors;
+UCHAR               *partition_sector_ptr;
+
+
+    /* Setup working pointer and initialize count.  */
+    partition_sector_ptr =  partition_sector;
+    count =  0;
+
+    /* Check for a real boot sector instead of a partition table.  */
+    if ((partition_sector_ptr[0] == 0xe9) || ((partition_sector_ptr[0] == 0xeb) && (partition_sector_ptr[2] == 0x90)))    
+    {
+    
+        /* Yes, a real boot sector could be present.  */  
+
+        /* See if there are good values for sectors per FAT.  */
+        if (partition_sector_ptr[0x16] || partition_sector_ptr[0x17] || partition_sector_ptr[0x24] || partition_sector_ptr[0x25] || partition_sector_ptr[0x26] || partition_sector_ptr[0x27])
+        {
+
+            /* There are values for sectors per FAT.  */
+
+            /* Determine if there is a total sector count.  */
+            total_sectors =  0;
+
+            if (partition_sector_ptr[0x13] || partition_sector_ptr[0x14])
+            {
+
+                /* Calculate the total sectors, FAT12/16.  */
+                total_sectors =  (((ULONG) partition_sector_ptr[0x14]) << 8) | ((ULONG) partition_sector_ptr[0x13]);
+            }
+            else if (partition_sector_ptr[0x20] || partition_sector_ptr[0x21] || partition_sector_ptr[0x22] || partition_sector_ptr[0x23])
+            {
+
+                /* Calculate the total sectors, FAT32.  */
+                total_sectors =  (((ULONG) partition_sector_ptr[0x23]) << 24) | 
+                                 (((ULONG) partition_sector_ptr[0x22]) << 16) |
+                                 (((ULONG) partition_sector_ptr[0x21]) << 8)  |
+                                 ((ULONG) partition_sector_ptr[0x20]);
+            }       
+
+            /* Determine if there is a total sector count.  */
+            if (total_sectors)
+            {
+
+                if (partition_start != FX_NULL)
+                {
+                    /* Return an offset of 0, size of boot record, and a successful status.  */
+                    *partition_start =  0;
+                }
+
+                /* Determine if the total sectors is required.  */
+                if (partition_size != FX_NULL)
+                {
+
+                    /* Return the total sectors.  */
+                    *partition_size =  (ULONG)(total_sectors & 0xFFFFFFFF);
+                }
+
+                /* Return success!  */
+                return(FX_SUCCESS);
+            }
+        }
+#ifdef FX_ENABLE_EXFAT
+        /* See if there are good values for sectors per exFAT.  */
+        else if (partition_sector_ptr[0x0b] == 0 && partition_sector_ptr[0x0c] == 0)
+        {
+            /* There are values for sectors per exFAT.  */
+
+            /* Calculate the total sectors.  */
+            total_sectors = _fx_utility_64_unsigned_read(&partition_sector_ptr[FX_EF_VOLUME_LENGTH]);
+
+            /* Determine if there is a total sector count.  */
+            if (total_sectors)
+            {
+
+                if (partition_start != FX_NULL)
+                {
+                    /* Return an offset of 0, size of boot record, and a successful status.  */
+                    *partition_start =  0;
+                }
+
+                /* Determine if the total sectors is required.  */
+                if (partition_size != FX_NULL)
+                {
+
+                    if (total_sectors > 0xFFFFFFFF)
+                    {
+
+                        /* Overflow. Just return not found. */
+                        return(FX_NOT_FOUND);
+                    }
+
+                    /* Return the total sectors.  */
+                    *partition_size =  (ULONG)(total_sectors & 0xFFFFFFFF);
+                }
+
+                /* Return success!  */
+                return(FX_SUCCESS);
+            }
+        }
+#endif /* FX_ENABLE_EXFAT */
+    }
+
+    /* Check signature to make sure the buffer is valid.  */
+    if ((partition_sector_ptr[510] != 0x55) || (partition_sector_ptr[511] != 0xAA))
+    {
+
+        /* Invalid, return an error.  */
+        return(FX_NOT_FOUND);
+    }
+    
+    /* Not bootable, look for specific partition.  */
+    _fx_utility_partition_get(partition_table, &count, 0, partition_sector_ptr);
+
+    /* Determine if return value is valid.  */
+    if (partition >= count)
+    {
+
+        /* No, return an error.  */
+        return(FX_NOT_FOUND);
+    }
+
+    /* Return the partition starting sector, if non-NULL.  */
+    if (partition_start != FX_NULL)
+    {
+        *partition_start =  partition_table[partition].fx_media_part_start;
+    }
+
+    /* Return the partition size, if non-NULL.  */
+    if (partition_size != FX_NULL)
+    {
+        *partition_size =  partition_table[partition].fx_media_part_size;
+    }
+
+    /* Return successful completion.  */
+    return(FX_SUCCESS);
+}
+
+
+/**************************************************************************/ 
+/*                                                                        */ 
+/*  FUNCTION                                               RELEASE        */ 
+/*                                                                        */ 
+/*    _fx_utility_partition_get                           PORTABLE C      */ 
+/*                                                           6.1.6        */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */ 
+/*    This function parses the partition sector and completes the         */ 
+/*    supplied partition entry structure.                                 */ 
+/*                                                                        */ 
+/*  INPUT                                                                 */ 
+/*                                                                        */ 
+/*    partition_table                       Pointer to partition table    */ 
+/*    count                                 Number of partitions found    */ 
+/*    sector                                Base sector                   */ 
+/*    sector_buffer                         Buffer containing partition   */ 
+/*                                            table                       */ 
+/*                                                                        */ 
+/*  OUTPUT                                                                */ 
+/*                                                                        */ 
+/*    return status                                                       */ 
+/*                                                                        */ 
+/*  CALLS                                                                 */ 
+/*                                                                        */ 
+/*    None                                                                */ 
+/*                                                                        */ 
+/*  CALLED BY                                                             */ 
+/*                                                                        */ 
+/*    _fx_partition_offset_calculate        Calculate partition offset    */ 
+/*                                                                        */ 
+/*  RELEASE HISTORY                                                       */ 
+/*                                                                        */ 
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*  04-02-2021     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1.6  */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_utility_partition_get(FX_MEDIA_PARTITION *partition_table, 
+                                UINT *count, ULONG sector, UCHAR *sector_buffer)
+{
+
+UINT    i;
+ULONG   base_sector, value;
+
+    /* This parameter has not been supported yet. */
+    FX_PARAMETER_NOT_USED(sector); 
+
+    /* Initialize base sector.  */
+    base_sector =  0;
+
+    for(i = 446; i <= 494; i+=16)
+    {
+        if (sector_buffer[i + 4] == 0) /* no partition entry here */
+        {
+
+            partition_table[*count].fx_media_part_start = 0;
+            partition_table[*count].fx_media_part_size  = 0;
+        }
+        else
+        {
+
+            value =  (ULONG) sector_buffer[i + 8]; /* little endian start value */
+            value =  (((ULONG) sector_buffer[i + 9]) << 8) | value;
+            value =  (((ULONG) sector_buffer[i + 10]) << 16) | value;
+            value =  (((ULONG) sector_buffer[i + 11]) << 24) | value;
+            partition_table[*count].fx_media_part_start = value + base_sector;
+
+            value =  (ULONG) sector_buffer[i + 12]; /* little endian size value */
+            value =  (((ULONG) sector_buffer[i + 13]) << 8) | value;
+            value =  (((ULONG) sector_buffer[i + 14]) << 16) | value;
+            value =  (((ULONG) sector_buffer[i + 15]) << 24) | value;
+            partition_table[*count].fx_media_part_size = value;
+        }
+
+        (*count)++;
+    }
+
+    /* Return success.  */
+    return(FX_SUCCESS);
+}
+
+/**************************************************************************/ 
+/*                                                                        */ 
+/*  FUNCTION                                               RELEASE        */ 
+/*                                                                        */ 
+/*    _fx_partition_offset_calculate_extended             PORTABLE C      */ 
+/*                                                           6.2.0        */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    Xiuwen Cai, Microsoft Corporation                                   */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */ 
+/*    This function calculates the sector offset to the specified         */ 
+/*    partition.  The buffer containing the partition table is also       */ 
+/*    supplied to this function.  If the buffer supplied is a boot        */ 
+/*    record (which could be the case in non-partition systems), this     */ 
+/*    function returns an offset of zero, the total sectors, and a        */ 
+/*    successful status indicating that the buffer supplied is the boot   */ 
+/*    record.  Otherwise, if a partition is found, this function returns  */ 
+/*    the sector offset to its boot record along with a successful        */ 
+/*    status. If the specified partition is not found or the buffer is    */ 
+/*    not a partition table or boot record, this function returns an      */ 
+/*    error.                                                              */ 
+/*                                                                        */ 
+/*    Note: Empty partitions have a FX_NOT_FOUND return code.             */
+/*      Use partition index 0 to 3 for primary partition and index 4 to   */
+/*      FX_MAX_PARTITION_COUNT for extended partition.                    */
+/*                                                                        */ 
+/*  INPUT                                                                 */ 
+/*                                                                        */ 
+/*    media_ptr                             Media control block pointer   */
+/*    partition_sector                      Pointer to buffer containing  */ 
+/*                                            either the partition table  */ 
+/*                                            or the boot sector          */ 
+/*    partition                             Desired partition             */ 
+/*    partition_start                       Return partition start        */ 
+/*    partition_size                        Return partition size         */ 
+/*                                                                        */ 
+/*  OUTPUT                                                                */ 
+/*                                                                        */ 
+/*    return status                                                       */ 
+/*                                                                        */ 
+/*  CALLS                                                                 */ 
+/*                                                                        */ 
+/*    _fx_utility_16_unsigned_read          Read a USHORT from memory     */
+/*    _fx_utility_32_unsigned_read          Read a ULONG from memory      */
+/*    _fx_utility_64_unsigned_read          Read a ULONG64 from memory    */
+/*    Media driver                                                        */
+/*                                                                        */ 
+/*  CALLED BY                                                             */ 
+/*                                                                        */ 
+/*    Application Driver                                                  */ 
+/*                                                                        */ 
+/*  RELEASE HISTORY                                                       */ 
+/*                                                                        */ 
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  10-31-2022     Xiuwen Cai               Initial Version 6.2.0        */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_partition_offset_calculate_extended(FX_MEDIA *media_ptr, void  *partition_sector, UINT partition,
+                                     ULONG *partition_start, ULONG *partition_size)
+{
+    
+ULONG64             total_sectors;
+UCHAR               *partition_sector_ptr;
+UCHAR               partition_type;
+UINT                i;
+ULONG               base_sector;
+ULONG               base_sector_extended;
+
+
+    /* Setup working pointer.  */
+    partition_sector_ptr =  partition_sector;
+
+    /* Check for a real boot sector instead of a partition table.  */
+    if ((partition_sector_ptr[0] == 0xe9) || ((partition_sector_ptr[0] == 0xeb) && (partition_sector_ptr[2] == 0x90)))    
+    {
+    
+        /* Yes, a real boot sector could be present.  */  
+
+        /* See if there are good values for sectors per FAT.  */
+        if (partition_sector_ptr[0x16] || partition_sector_ptr[0x17] || partition_sector_ptr[0x24] || partition_sector_ptr[0x25] || partition_sector_ptr[0x26] || partition_sector_ptr[0x27])
+        {
+
+            /* There are values for sectors per FAT.  */
+
+            /* Get the total sectors, FAT12/16.  */
+            total_sectors =  _fx_utility_16_unsigned_read(&partition_sector_ptr[FX_SECTORS]);
+
+            if (total_sectors == 0)
+            {
+
+                /* Get the total sectors, FAT32.  */
+                total_sectors = _fx_utility_32_unsigned_read(&partition_sector_ptr[FX_HUGE_SECTORS]);
+            }       
+
+            /* Determine if there is a total sector count.  */
+            if (total_sectors)
+            {
+
+                if (partition_start != FX_NULL)
+                {
+                    /* Return an offset of 0, size of boot record, and a successful status.  */
+                    *partition_start =  0;
+                }
+
+                /* Determine if the total sectors is required.  */
+                if (partition_size != FX_NULL)
+                {
+
+                    /* Return the total sectors.  */
+                    *partition_size =  (ULONG)(total_sectors & 0xFFFFFFFF);
+                }
+
+                /* Return success!  */
+                return(FX_SUCCESS);
+            }
+        }
+#ifdef FX_ENABLE_EXFAT
+        /* See if there are good values for sectors per exFAT.  */
+        else if (partition_sector_ptr[0x0b] == 0 && partition_sector_ptr[0x0c] == 0)
+        {
+            /* There are values for sectors per exFAT.  */
+
+            /* Calculate the total sectors.  */
+            total_sectors = _fx_utility_64_unsigned_read(&partition_sector_ptr[FX_EF_VOLUME_LENGTH]);
+
+            /* Determine if there is a total sector count.  */
+            if (total_sectors)
+            {
+
+                if (partition_start != FX_NULL)
+                {
+                    /* Return an offset of 0, size of boot record, and a successful status.  */
+                    *partition_start =  0;
+                }
+
+                /* Determine if the total sectors is required.  */
+                if (partition_size != FX_NULL)
+                {
+
+                    if (total_sectors > 0xFFFFFFFF)
+                    {
+
+                        /* Overflow. Just return not found. */
+                        return(FX_NOT_FOUND);
+                    }
+
+                    /* Return the total sectors.  */
+                    *partition_size =  (ULONG)(total_sectors & 0xFFFFFFFF);
+                }
+
+                /* Return success!  */
+                return(FX_SUCCESS);
+            }
+        }
+#endif /* FX_ENABLE_EXFAT */
+    }
+
+    /* Check signature to make sure the buffer is valid.  */
+    if ((partition_sector_ptr[510] != FX_SIG_BYTE_1) || (partition_sector_ptr[511] != FX_SIG_BYTE_2))
+    {
+
+        /* Invalid, return an error.  */
+        return(FX_NOT_FOUND);
+    }
+    
+    /* Not bootable, look for specific partition.  */
+
+    /* Check if primary partitions are addressed.  */
+    if (partition < 4)
+    {
+
+        /* Get partition type.  */
+        partition_type =  partition_sector_ptr[FX_PARTITION_TABLE_OFFSET + partition * FX_PARTITION_ENTRY_SIZE + FX_PARTITION_TYPE_OFFSET];
+
+        /* Check if there is a vaild partition.  */
+        if (partition_type != FX_PARTITION_TYPE_FREE)
+        {
+
+            /* Return the partition starting sector, if non-NULL.  */
+            if (partition_start != FX_NULL)
+            {
+                *partition_start = _fx_utility_32_unsigned_read(&partition_sector_ptr[FX_PARTITION_TABLE_OFFSET + partition * FX_PARTITION_ENTRY_SIZE + FX_PARTITION_LBA_OFFSET]);
+            }
+
+            /* Return the partition size, if non-NULL.  */
+            if (partition_size != FX_NULL)
+            {
+                *partition_size =  _fx_utility_32_unsigned_read(&partition_sector_ptr[FX_PARTITION_TABLE_OFFSET + partition * FX_PARTITION_ENTRY_SIZE + FX_PARTITION_SECTORS_OFFSET]);
+            }
+
+            /* Return success!  */
+            return(FX_SUCCESS);
+        }
+        else
+        {
+
+            /* Not partition here.  */
+            return(FX_NOT_FOUND);            
+        }
+    }
+
+    /* Check for invalid parameter.  */
+    if (partition > FX_MAX_PARTITION_COUNT)
+    {
+
+        /* Return error.  */
+        return(FX_NOT_FOUND);     
+    }
+
+    base_sector = 0;
+
+    /* Loop to find the extended partition table.  */
+    for(i = FX_PARTITION_TABLE_OFFSET; i <= FX_PARTITION_TABLE_OFFSET + 3 * FX_PARTITION_ENTRY_SIZE; i += FX_PARTITION_ENTRY_SIZE)
+    {
+
+        /* Get partition type.  */
+        partition_type =  partition_sector_ptr[i + FX_PARTITION_TYPE_OFFSET];
+        if (partition_type == FX_PARTITION_TYPE_EXTENDED || partition_type == FX_PARTITION_TYPE_EXTENDED_LBA)
+        {
+            base_sector =  _fx_utility_32_unsigned_read(&partition_sector_ptr[i + FX_PARTITION_LBA_OFFSET]);
+            break;
+        }
+    }
+
+    if (base_sector == 0)
+    {
+
+        /* No extended partition.  */
+        return(FX_NOT_FOUND);        
+    }
+    
+    base_sector_extended = base_sector;
+
+    for (i = 4; i <= partition; i++)
+    {
+
+        /* Read the partition sector from the device.  Build the read sector
+            command.  */
+        media_ptr -> fx_media_driver_request =          FX_DRIVER_READ;
+        media_ptr -> fx_media_driver_status =           FX_IO_ERROR;
+        media_ptr -> fx_media_driver_buffer =           partition_sector_ptr;
+        media_ptr -> fx_media_driver_logical_sector =   base_sector;
+        media_ptr -> fx_media_driver_sectors =          1;
+        media_ptr -> fx_media_driver_sector_type =      FX_UNKNOWN_SECTOR;
+        media_ptr -> fx_media_hidden_sectors =          0;
+
+        /* Invoke the driver to read the sector.  */
+        (media_ptr -> fx_media_driver_entry) (media_ptr);
+
+        /* Determine if the sector was read correctly. */
+        if (media_ptr -> fx_media_driver_status != FX_SUCCESS)
+        {
+
+            /* Return error.  */
+            return(FX_IO_ERROR);
+        }
+
+        /* Check signature to make sure the sector is valid.  */
+        if ((partition_sector_ptr[510] != FX_SIG_BYTE_1) || (partition_sector_ptr[511] != FX_SIG_BYTE_2))
+        {
+
+            /* Invalid, return an error.  */
+            return(FX_NOT_FOUND);
+        }
+
+        /* Determine if this is the desired partition.  */
+        if (i == partition)
+        {
+
+            /* Get partition type.  */
+            partition_type =  partition_sector_ptr[FX_PARTITION_TABLE_OFFSET + FX_PARTITION_TYPE_OFFSET];
+            if (partition_type != FX_PARTITION_TYPE_FREE)
+            {
+
+                /* Return the partition starting sector, if non-NULL.  */
+                if (partition_start != FX_NULL)
+                {
+                    *partition_start = _fx_utility_32_unsigned_read(&partition_sector_ptr[FX_PARTITION_TABLE_OFFSET + FX_PARTITION_LBA_OFFSET]) + base_sector;
+                }
+
+                /* Return the partition size, if non-NULL.  */
+                if (partition_size != FX_NULL)
+                {
+                    *partition_size =  _fx_utility_32_unsigned_read(&partition_sector_ptr[FX_PARTITION_TABLE_OFFSET + FX_PARTITION_SECTORS_OFFSET]);
+                }
+
+                /* Return success!  */
+                return(FX_SUCCESS);
+            }
+            else
+            {
+                /* Not partition here.  */
+                return(FX_NOT_FOUND);            
+            }
+        }
+        else
+        {
+
+            /* Get partition type.  */
+            partition_type =  partition_sector_ptr[FX_PARTITION_TABLE_OFFSET + FX_PARTITION_ENTRY_SIZE + FX_PARTITION_TYPE_OFFSET];
+            if (partition_type == FX_PARTITION_TYPE_EXTENDED || partition_type == FX_PARTITION_TYPE_EXTENDED_LBA)
+            {
+
+                /* Update sector number for next partition table.  */
+                base_sector =  _fx_utility_32_unsigned_read(&partition_sector_ptr[FX_PARTITION_TABLE_OFFSET + FX_PARTITION_ENTRY_SIZE + FX_PARTITION_LBA_OFFSET]) + base_sector_extended;
+            }
+            else
+            {
+                /* No valid partition, get out of the loop.  */
+                break;
+            }
+        }
+
+    }
+
+    /* Return error.  */
+    return(FX_NOT_FOUND);    
+}
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_system_date_get.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_system_date_get.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_system_date_get.c	(revision 30)
@@ -0,0 +1,119 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   System                                                              */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_system_date_get                                 PORTABLE C      */
+/*                                                           6.1.7        */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function returns the current contents of the system date in    */
+/*    the fields specified by the caller.                                 */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    year                                  Pointer to year               */
+/*    month                                 Pointer to month              */
+/*    day                                   Pointer to day                */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    FX_SUCCESS                                                          */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*  06-02-2021     William E. Lamie         Modified comment(s),          */
+/*                                            checked null pointer,       */
+/*                                            resulting in version 6.1.7  */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_system_date_get(UINT *year, UINT *month, UINT *day)
+{
+
+UINT date;
+
+
+    /* Get a copy of the current date.  */
+    date =  _fx_system_date;
+
+    /* Check to see if the year is required.  */
+    if (year)
+    {
+
+        /* Pickup the year.  */
+        *year =  ((date >> FX_YEAR_SHIFT) & FX_YEAR_MASK) + FX_BASE_YEAR;
+    }
+
+    /* Check to see if the month is required.  */
+    if (month)
+    {
+
+        /* Pickup the month.  */
+        *month =  (date >> FX_MONTH_SHIFT) & FX_MONTH_MASK;
+    }
+
+    /* Check to see if the day is required.  */
+    if (day)
+    {
+
+        /* Pickup the day.  */
+        *day =  date & FX_DAY_MASK;
+    }
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    if (year && month && day)
+    {
+        FX_TRACE_IN_LINE_INSERT(FX_TRACE_SYSTEM_DATE_GET, *year, *month, *day, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+    }
+
+    /* Return successful status.  */
+    return(FX_SUCCESS);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_system_date_set.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_system_date_set.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_system_date_set.c	(revision 30)
@@ -0,0 +1,88 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   System                                                              */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_system_date_set                                 PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function sets the system date to the date specified by the     */
+/*    caller.                                                             */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    year                                  Year (1980-2107)              */
+/*    month                                 Month (1-12)                  */
+/*    day                                   Day (1-28/29/30/31)           */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    FX_SUCCESS                                                          */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_system_date_set(UINT year, UINT month, UINT day)
+{
+
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_SYSTEM_DATE_SET, year, month, day, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+    /* Set the system date.  */
+    _fx_system_date =  ((year - FX_BASE_YEAR) << FX_YEAR_SHIFT) |
+        (month << FX_MONTH_SHIFT) | day;
+
+    /* Return successful status.  */
+    return(FX_SUCCESS);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_system_initialize.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_system_initialize.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_system_initialize.c	(revision 30)
@@ -0,0 +1,207 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   System                                                              */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Locate FileX control component data in this file.  */
+
+#define FX_SYSTEM_INIT
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_system_initialize                               PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function initializes the various control data structures for   */
+/*    the FileX System component.                                         */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    tx_timer_create                       Create system timer           */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Initialization                                          */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s), and      */
+/*                                            added conditional to        */
+/*                                            disable build options,      */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+VOID  _fx_system_initialize(VOID)
+{
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_SYSTEM_INITIALIZE, 0, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+    /* Initialize the head pointer of the opened media list and the
+       number of opened media.  */
+    _fx_system_media_opened_ptr =       FX_NULL;
+    _fx_system_media_opened_count =     0;
+
+    /* Initialize the time and date fields with their default values.  */
+    _fx_system_date =   FX_INITIAL_DATE;
+    _fx_system_time =   FX_INITIAL_TIME;
+
+    /* Initialize the sector and FAT cache sizes.  */
+    _fx_system_media_max_sector_cache =  FX_MAX_SECTOR_CACHE;
+    _fx_system_media_max_fat_cache =     FX_MAX_FAT_CACHE;
+
+    /* Create the FileX system timer.  This is responsible for updating
+       the specified date and time at the rate specified by
+       FX_UPDATE_RATE_IN_TICKS.  Note that the timer is not necessary for
+       regular FileX operation - it is only needed for accurate system
+       date and time stamps on files.  */
+
+#ifndef FX_NO_TIMER
+    tx_timer_create(&_fx_system_timer, "FileX System Timer", _fx_system_timer_entry, FX_TIMER_ID,
+                    FX_UPDATE_RATE_IN_TICKS, FX_UPDATE_RATE_IN_TICKS, TX_AUTO_ACTIVATE);
+#endif
+
+#ifndef FX_DISABLE_BUILD_OPTIONS
+    /* Setup the build options variables.  */
+
+    /* Setup the first build options variable.  */
+    if (FX_MAX_LONG_NAME_LEN > 0xFF)
+    {
+        _fx_system_build_options_1 =  _fx_system_build_options_1 | (((ULONG)0xFF) << 24);
+    }
+    else
+    {
+        _fx_system_build_options_1 =  _fx_system_build_options_1 | (((ULONG)(FX_MAX_LONG_NAME_LEN & 0xFF)) << 24);
+    }
+    if (FX_MAX_LAST_NAME_LEN > 0xFF)
+    {
+        _fx_system_build_options_1 =  _fx_system_build_options_1 | (((ULONG)0xFF) << 16);
+    }
+    else
+    {
+        _fx_system_build_options_1 =  _fx_system_build_options_1 | (((ULONG)(FX_MAX_LAST_NAME_LEN & 0xFF)) << 24);
+    }
+
+#ifdef FX_NO_TIMER
+    _fx_system_build_options_1 = _fx_system_build_options_1 | (((ULONG)1) << 10);
+#endif
+#ifdef FX_SINGLE_THREAD
+    _fx_system_build_options_1 = _fx_system_build_options_1 | (((ULONG)1) << 9);
+#endif
+#ifdef FX_DONT_UPDATE_OPEN_FILES
+    _fx_system_build_options_1 = _fx_system_build_options_1 | (((ULONG)1) << 8);
+#endif
+#ifdef FX_MEDIA_DISABLE_SEARCH_CACHE
+    _fx_system_build_options_1 = _fx_system_build_options_1 | (((ULONG)1) << 7);
+#endif
+#ifdef FX_MEDIA_STATISTICS_DISABLE
+    _fx_system_build_options_1 = _fx_system_build_options_1 | (((ULONG)1) << 6);
+#endif
+
+#ifdef FX_SINGLE_OPEN_LEGACY
+    _fx_system_build_options_1 = _fx_system_build_options_1 | (((ULONG)1) << 4);
+#endif
+#ifdef FX_RENAME_PATH_INHERIT
+    _fx_system_build_options_1 = _fx_system_build_options_1 | (((ULONG)1) << 3);
+#endif
+#ifdef FX_NO_LOCAL_PATH
+    _fx_system_build_options_1 = _fx_system_build_options_1 | (((ULONG)1) << 2);
+#endif
+#ifdef FX_FAULT_TOLERANT_DATA
+    _fx_system_build_options_1 = _fx_system_build_options_1 | (((ULONG)1) << 1);
+#endif
+#ifdef FX_FAULT_TOLERANT
+    _fx_system_build_options_1 = _fx_system_build_options_1 | ((ULONG)1);
+#endif
+
+    /* Setup the second build options variable.  */
+    if (FX_MAX_SECTOR_CACHE > ((ULONG)0xFFFF))
+    {
+        _fx_system_build_options_2 =  _fx_system_build_options_2 | (((ULONG)0xFFFF) << 16);
+    }
+    else
+    {
+        _fx_system_build_options_2 =  _fx_system_build_options_2 | (((ULONG)FX_MAX_SECTOR_CACHE) << 16);
+    }
+    if (FX_FAT_MAP_SIZE > 0xFF)
+    {
+        _fx_system_build_options_2 =  _fx_system_build_options_2 | (((ULONG)0xFF) << 8);
+    }
+    else
+    {
+        _fx_system_build_options_2 =  _fx_system_build_options_2 | (((ULONG)FX_FAT_MAP_SIZE) << 8);
+    }
+    if (FX_MAX_FAT_CACHE > 0xFF)
+    {
+        _fx_system_build_options_2 =  _fx_system_build_options_2 | ((ULONG)0xFF);
+    }
+    else
+    {
+        _fx_system_build_options_2 =  _fx_system_build_options_2 | ((ULONG)FX_MAX_FAT_CACHE);
+    }
+
+    /* Setup the third build options variable.  */
+    if (FX_UPDATE_RATE_IN_SECONDS > 0xFF)
+    {
+        _fx_system_build_options_3 =  _fx_system_build_options_3 | (((ULONG)0xFF) << 16);
+    }
+    else
+    {
+        _fx_system_build_options_3 =  _fx_system_build_options_3 | (((ULONG)FX_UPDATE_RATE_IN_SECONDS) << 16);
+    }
+    if (FX_UPDATE_RATE_IN_TICKS > ((ULONG)0xFFFF))
+    {
+        _fx_system_build_options_3 =  _fx_system_build_options_3 | ((ULONG)0xFFFF);
+    }
+    else
+    {
+        _fx_system_build_options_3 =  _fx_system_build_options_3 | ((ULONG)FX_UPDATE_RATE_IN_TICKS);
+    }
+#endif /* FX_DISABLE_BUILD_OPTIONS */
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_system_time_get.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_system_time_get.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_system_time_get.c	(revision 30)
@@ -0,0 +1,119 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   System                                                              */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_system_time_get                                 PORTABLE C      */
+/*                                                           6.1.7        */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function returns the current contents of the system time in    */
+/*    the fields specified by the caller.                                 */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    hour                                  Pointer to hour               */
+/*    minute                                Pointer to minute             */
+/*    second                                Pointer to second             */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    FX_SUCCESS                                                          */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*  06-02-2021     William E. Lamie         Modified comment(s),          */
+/*                                            checked null pointer,       */
+/*                                            resulting in version 6.1.7  */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_system_time_get(UINT *hour, UINT *minute, UINT *second)
+{
+
+UINT time;
+
+
+    /* Get a copy of the current system time.  */
+    time =  _fx_system_time;
+
+    /* Check to see if the hour is required.  */
+    if (hour)
+    {
+
+        /* Pickup the hour.  */
+        *hour =  (time >> FX_HOUR_SHIFT) & FX_HOUR_MASK;
+    }
+
+    /* Check to see if the minute is required.  */
+    if (minute)
+    {
+
+        /* Pickup the minute.  */
+        *minute =  (time >> FX_MINUTE_SHIFT) & FX_MINUTE_MASK;
+    }
+
+    /* Check to see if the second is required.  */
+    if (second)
+    {
+
+        /* Pickup the second.  */
+        *second =  (time & FX_SECOND_MASK) * 2;
+    }
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    if (hour && minute && second)
+    {
+        FX_TRACE_IN_LINE_INSERT(FX_TRACE_SYSTEM_TIME_GET, *hour, *minute, *second, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+    }
+
+    /* Return successful status.  */
+    return(FX_SUCCESS);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_system_time_set.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_system_time_set.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_system_time_set.c	(revision 30)
@@ -0,0 +1,88 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   System                                                              */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_system_time_set                                 PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function set the system time to the value specified by the     */
+/*    caller.                                                             */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    hour                                  Hour (0-23)                   */
+/*    minute                                Minute (0-59)                 */
+/*    second                                Second (0-59)                 */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    FX_SUCCESS                                                          */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_system_time_set(UINT hour, UINT minute, UINT second)
+{
+
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_SYSTEM_TIME_SET, hour, minute, second, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+    /* Set the new system time.  */
+    _fx_system_time  =  (hour << FX_HOUR_SHIFT) |
+        (minute << FX_MINUTE_SHIFT) | (second / 2);
+
+    /* Return successful status.  */
+    return(FX_SUCCESS);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_system_timer_entry.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_system_timer_entry.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_system_timer_entry.c	(revision 30)
@@ -0,0 +1,343 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   System                                                              */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_system_timer_entry                              PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function is FileX system timer function.  It is called at the  */
+/*    rate specified by FX_UPDATE_RATE_IN_SECONDS and is responsible for  */
+/*    maintaining both the system date and time.                          */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    id                                    Not used                      */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Initialization                                          */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+VOID    _fx_system_timer_entry(ULONG id)
+{
+
+UINT second;
+UINT minute;
+UINT hour;
+UINT day;
+UINT month;
+UINT year;
+
+
+    /* Determine if the ID is valid.  */
+    if (id == FX_TIMER_ID)
+    {
+
+        /* Break the current date time into separate fields for easier work!  */
+        second =  (_fx_system_time & FX_SECOND_MASK) * 2;
+        minute =  (_fx_system_time >> FX_MINUTE_SHIFT) & FX_MINUTE_MASK;
+        hour =    (_fx_system_time >> FX_HOUR_SHIFT) & FX_HOUR_MASK;
+        day =     _fx_system_date & FX_DAY_MASK;
+        month =   (_fx_system_date >> FX_MONTH_SHIFT) & FX_MONTH_MASK;
+        year =    ((_fx_system_date >> FX_YEAR_SHIFT) & FX_YEAR_MASK) + FX_BASE_YEAR;
+
+        /* Now apply the "second" update.  */
+        second =  second + FX_UPDATE_RATE_IN_SECONDS;
+
+        /* Determine if we need to adjust the minute field.  */
+        if (second > FX_MAXIMUM_SECOND)
+        {
+
+            /* Yes, we need to adjust the minute field.  */
+            minute =  minute + second / 60;
+            second =  second % 60;
+
+            /* Determine if we need to adjust the hour field.  */
+            if (minute > FX_MAXIMUM_MINUTE)
+            {
+
+                /* Yes, we need to adjust the hour field.  */
+                hour =    hour + minute / 60;
+                minute =  minute % 60;
+
+                /* Determine if we need to adjust the day field.  */
+                if (hour > FX_MAXIMUM_HOUR)
+                {
+
+                    /* Yes, we need to adjust the day field.  */
+                    hour =  0;
+                    day++;
+
+                    /* Determine if we need to adjust the month field.  */
+                    switch (month)
+                    {
+
+                    case 1:                 /* January  */
+                    {
+
+                        /* Check for end of the month.  */
+                        if (day > 31)
+                        {
+
+                            /* Move to next month.  */
+                            day = 1;
+                            month++;
+                        }
+                        break;
+                    }
+
+                    case 2:                 /* February  */
+                    {
+
+                        /* Check for leap year.  We don't need to check for leap
+                           century her (century years divisible by 400) since 2000
+                           is and this FAT format only supports years to 2107. */
+                        if ((year % 4) == 0)
+                        {
+
+                            /* Leap year in February... check for 29 days
+                               instead of 28.  */
+                            if (day > 29)
+                            {
+
+                                /* Adjust the month.  */
+                                day =  1;
+                                month++;
+                            }
+                        }
+                        else
+                        {
+
+                            if (day > 28)
+                            {
+
+                                /* Adjust the month.  */
+                                day = 1;
+                                month++;
+                            }
+                        }
+                        break;
+                    }
+
+                    case 3:                 /* March  */
+                    {
+
+                        /* Check for end of the month.  */
+                        if (day > 31)
+                        {
+
+                            /* Move to next month.  */
+                            day = 1;
+                            month++;
+                        }
+                        break;
+                    }
+
+                    case 4:                 /* April  */
+                    {
+
+                        /* Check for end of the month.  */
+                        if (day > 30)
+                        {
+
+                            /* Move to next month.  */
+                            day = 1;
+                            month++;
+                        }
+                        break;
+                    }
+
+                    case 5:                 /* May  */
+                    {
+
+                        /* Check for end of the month.  */
+                        if (day > 31)
+                        {
+
+                            /* Move to next month.  */
+                            day = 1;
+                            month++;
+                        }
+                        break;
+                    }
+
+                    case 6:                 /* June */
+                    {
+
+                        /* Check for end of the month.  */
+                        if (day > 30)
+                        {
+
+                            /* Move to next month.  */
+                            day = 1;
+                            month++;
+                        }
+                        break;
+                    }
+
+                    case 7:                 /* July */
+                    {
+
+                        /* Check for end of the month.  */
+                        if (day > 31)
+                        {
+
+                            /* Move to next month.  */
+                            day = 1;
+                            month++;
+                        }
+                        break;
+                    }
+
+                    case 8:                 /* August */
+                    {
+
+                        /* Check for end of the month.  */
+                        if (day > 31)
+                        {
+
+                            /* Move to next month.  */
+                            day = 1;
+                            month++;
+                        }
+                        break;
+                    }
+
+                    case 9:                 /* September */
+                    {
+
+                        /* Check for end of the month.  */
+                        if (day > 30)
+                        {
+
+                            /* Move to next month.  */
+                            day = 1;
+                            month++;
+                        }
+                        break;
+                    }
+
+                    case 10:                /* October */
+                    {
+
+                        /* Check for end of the month.  */
+                        if (day > 31)
+                        {
+
+                            /* Move to next month.  */
+                            day = 1;
+                            month++;
+                        }
+                        break;
+                    }
+
+                    case 11:                /* November */
+                    {
+
+                        /* Check for end of the month.  */
+                        if (day > 30)
+                        {
+
+                            /* Move to next month.  */
+                            day = 1;
+                            month++;
+                        }
+                        break;
+                    }
+
+                    case 12:                /* December */
+                    {
+
+                        /* Check for end of the month.  */
+                        if (day > 31)
+                        {
+
+                            /* Move to next month.  */
+                            day = 1;
+                            month = 1;
+
+                            /* Also move to next year.  */
+                            year++;
+
+                            /* Check for a year that exceeds the representation
+                               in this format.  */
+                            if (year > FX_MAXIMUM_YEAR)
+                            {
+                                return;
+                            }
+                        }
+                        break;
+                    }
+
+                    default:                /* Invalid month!  */
+
+                        return;             /* Skip updating date/time!  */
+                    }
+                }
+            }
+        }
+
+        /* Now apply the new setting to the internal representation.  */
+
+        /* Set the system date.  */
+        _fx_system_date =  ((year - FX_BASE_YEAR) << FX_YEAR_SHIFT) |
+                            (month << FX_MONTH_SHIFT) | day;
+
+        /* Set the new system time.  */
+        _fx_system_time  =  (hour << FX_HOUR_SHIFT) |
+                            (minute << FX_MINUTE_SHIFT) | (second / 2);
+    }
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_unicode_directory_create.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_unicode_directory_create.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_unicode_directory_create.c	(revision 30)
@@ -0,0 +1,291 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Unicode                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_unicode.h"
+#include "fx_directory.h"
+#include "fx_utility.h"
+#ifdef FX_ENABLE_FAULT_TOLERANT
+#include "fx_fault_tolerant.h"
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_unicode_directory_create                        PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function creates the specified unicode directory.              */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Pointer to media              */
+/*    source_unicode_name                   Pointer to source unicode name*/
+/*    source_unicode_length                 Unicode name length           */
+/*    short_name                            Designated short name         */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    Completion Status                                                   */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_search                  Search directory              */
+/*    _fx_unicode_directory_entry_change    Change unicode file name      */
+/*    _fx_unicode_directory_search          Search for unicode name       */
+/*    _fx_directory_create                  Create a directory            */
+/*    _fx_fault_tolerant_transaction_start  Start fault tolerant          */
+/*                                            transaction                 */
+/*    _fx_fault_tolerant_transaction_end    End fault tolerant transaction*/
+/*    _fx_fault_tolerant_recover            Recover FAT chain             */
+/*    _fx_fault_tolerant_reset_log_file     Reset the log file            */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_unicode_directory_create(FX_MEDIA *media_ptr, UCHAR *source_unicode_name, ULONG source_unicode_length, CHAR *short_name)
+{
+
+FX_DIR_ENTRY dir_entry;
+UINT         i, status;
+ULONG        temp_length;
+UCHAR        destination_shortname[13];
+
+
+    /* Setup pointer to media name buffer.  */
+    dir_entry.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
+
+    /* Clear the short name string.  */
+    dir_entry.fx_dir_entry_short_name[0] =  FX_NULL;
+
+    /* Set destination shortname to null.  */
+    destination_shortname[0] =  FX_NULL;
+
+    /* Clear the return short name.  */
+    short_name[0] =  FX_NULL;
+
+    /* Check the media to make sure it is open.  */
+    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
+    {
+
+        /* Return the media not opened error.  */
+        return(FX_MEDIA_NOT_OPEN);
+    }
+
+#ifdef FX_ENABLE_EXFAT
+    /* Check if media format is exFAT.  */
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+
+        /* Return the not implemented error.  */
+        return(FX_NOT_IMPLEMENTED);
+    }
+#endif
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_UNICODE_DIRECTORY_CREATE, media_ptr, source_unicode_name, source_unicode_length, short_name, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
+
+    /* Protect media.  */
+    FX_PROTECT
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    /* Start transaction. */
+    _fx_fault_tolerant_transaction_start(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Check for write protect at the media level (set by driver).  */
+    if (media_ptr -> fx_media_driver_write_protect)
+    {
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return write protect error.  */
+        return(FX_WRITE_PROTECT);
+    }
+
+    /* Setup temporary length.  */
+    temp_length =  source_unicode_length;
+
+    /* Determine if the destination directory is already present.  */
+    status =  _fx_unicode_directory_search(media_ptr, &dir_entry, destination_shortname, sizeof(destination_shortname), source_unicode_name, &temp_length, 0);
+
+    /* Determine if the search was successful.  */
+    if (status == FX_SUCCESS)
+    {
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the error code.  */
+        return(FX_ALREADY_CREATED);
+    }
+
+    /* Okay, at this point we need to create a new long directory name that has enough space for the
+       eventual unicode directory name.  */
+
+    /* Copy the characters from the unicode directory name and make sure they are
+       within the ASCII range.  */
+    _fx_unicode_temp_long_file_name[0] =  'z';
+    for (i = 1; i < source_unicode_length; i++)
+    {
+
+        /* Build temporary long file name.  */
+        _fx_unicode_temp_long_file_name[i] =  (UCHAR)((INT)'0' + (i % 9));
+    }
+    _fx_unicode_temp_long_file_name[i] =  FX_NULL;
+
+    /* Loop to try different temp long file names... if necessary.  */
+    do
+    {
+
+        /* Create a new directory with the temp long file name.  */
+        status =  _fx_directory_create(media_ptr, (CHAR *)_fx_unicode_temp_long_file_name);
+
+        /* Determine if there was an error.  */
+        if (status == FX_ALREADY_CREATED)
+        {
+
+            /* Adjust the name slightly and try again!  */
+            _fx_unicode_temp_long_file_name[0]--;
+
+            /* Determine if it is outside the lower case boundary.  */
+            if (_fx_unicode_temp_long_file_name[0] < 0x61)
+            {
+                break;
+            }
+        }
+    } while (status == FX_ALREADY_CREATED);
+
+    /* Determine if there was an error.  */
+    if (status)
+    {
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return error.  */
+        return(status);
+    }
+
+    /* Setup pointer to media name buffer.  */
+    dir_entry.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
+
+    /* Clear the short name string.  */
+    dir_entry.fx_dir_entry_short_name[0] =  0;
+
+    /* Search the system for the supplied file name.  */
+    status =  _fx_directory_search(media_ptr, (CHAR *)_fx_unicode_temp_long_file_name, &dir_entry, FX_NULL, FX_NULL);
+
+    /* Determine if the search was successful.  */
+    if (status != FX_SUCCESS)
+    {
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the error status.  */
+        return(status);
+    }
+
+    /* We can now change the temporary long file name with the destination unicode name.  */
+    status =  _fx_unicode_directory_entry_change(media_ptr, &dir_entry,  source_unicode_name, source_unicode_length);
+
+    /* Was this successful?  */
+    if (status == FX_SUCCESS)
+    {
+
+        /* Yes, copy the short file name to the destination.  */
+        /* The new short name only have 8 characters, since we didn't include a dot in temp_long_file_name. */
+        for (i = 0; i < FX_DIR_NAME_SIZE; i++)
+        {
+
+            /* Copy a character.  */
+            short_name[i] =  dir_entry.fx_dir_entry_short_name[i];
+
+            /* Are we done?  */
+            if (short_name[i] == FX_NULL)
+            {
+                break;
+            }
+        }
+    }
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    /* Check for a bad status.  */
+    if (status != FX_SUCCESS)
+    {
+
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the bad status.  */
+        return(status);
+    }
+
+    /* End transaction. */
+    status = _fx_fault_tolerant_transaction_end(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Release the protection.  */
+    FX_UNPROTECT
+
+    /* Return completion status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_unicode_directory_entry_change.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_unicode_directory_entry_change.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_unicode_directory_entry_change.c	(revision 30)
@@ -0,0 +1,390 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Unicode                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_unicode.h"
+#include "fx_utility.h"
+#ifdef FX_ENABLE_FAULT_TOLERANT
+#include "fx_fault_tolerant.h"
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_unicode_directory_entry_change                  PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function changes the unicode name of a directory entry.        */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Pointer to media              */
+/*    entry_ptr                             Directory entry               */
+/*    unicode_name                          Destination unicode name      */
+/*    unicode_name_length                   Unicode name size             */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    Completion Status                                                   */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_FAT_entry_read            Read a FAT entry              */
+/*    _fx_utility_logical_sector_read       Read a logical sector         */
+/*    _fx_utility_logical_sector_write      Write a logical sector        */
+/*    _fx_fault_tolerant_add_dir_log        Add directory redo log        */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Unicode Utilities                                                   */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_unicode_directory_entry_change(FX_MEDIA *media_ptr, FX_DIR_ENTRY *entry_ptr, UCHAR *unicode_name, ULONG unicode_name_length)
+{
+
+UCHAR *work_ptr, *sector_base_ptr;
+UINT   status;
+UINT   i, j, k, u, card, lfn_entries;
+UCHAR  eof_marker;
+ULONG  logical_sector, relative_sector;
+ULONG  byte_offset;
+ULONG  cluster, next_cluster;
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+UCHAR *changed_ptr;
+UINT   changed_size;
+ULONG  changed_offset;
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of directory entry write requests.  */
+    media_ptr -> fx_media_directory_entry_writes++;
+#endif
+
+    /* Pickup the byte offset of the entry.  */
+    byte_offset = entry_ptr -> fx_dir_entry_byte_offset;
+
+    /* Pickup the logical sector of the entry.  */
+    logical_sector = (ULONG)entry_ptr -> fx_dir_entry_log_sector;
+
+    /* Figure out where what cluster we are in.  */
+    if (logical_sector >= (ULONG)(media_ptr -> fx_media_data_sector_start))
+    {
+
+        /* Calculate the cluster that this logical sector is in.  */
+        cluster =  (logical_sector - media_ptr -> fx_media_data_sector_start) / (media_ptr -> fx_media_sectors_per_cluster) + FX_FAT_ENTRY_START;
+
+        /* Calculate the relative cluster.  */
+        relative_sector =  logical_sector -  (((ULONG)media_ptr -> fx_media_data_sector_start) +
+                                              (((ULONG)cluster - FX_FAT_ENTRY_START) *
+                                               ((ULONG)media_ptr -> fx_media_sectors_per_cluster)));
+    }
+    else
+    {
+
+        /* Clear the cluster and the relative sector.  */
+        cluster =  0;
+        relative_sector =  0;
+    }
+
+    /* Read the logical directory sector.  */
+    status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) entry_ptr -> fx_dir_entry_log_sector,
+                                              media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
+
+    /* Determine if an error occurred.  */
+    if (status != FX_SUCCESS)
+    {
+
+        /* Return the error status.  */
+        return(status);
+    }
+
+    /* Setup a pointer into the buffer.  */
+    sector_base_ptr = (UCHAR *)media_ptr -> fx_media_memory_buffer;
+    work_ptr =  sector_base_ptr + (UINT)entry_ptr -> fx_dir_entry_byte_offset;
+
+    /* Initialize the unicode index.  */
+    u =  0;
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    /* Initialize data for fault tolerant. */
+    changed_ptr = work_ptr;
+    changed_size = 0;
+    changed_offset = entry_ptr -> fx_dir_entry_byte_offset;
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Check for a valid long name.  */
+    if ((0x40 & (*work_ptr)))
+    {
+
+        /* Get the lower 5 bit containing the cardinality.  */
+        card = (*work_ptr & (UCHAR)0x1f);
+        lfn_entries =  card;
+
+        /* Loop through the file name.  */
+        for (j = 0; j < lfn_entries; j++)
+        {
+
+            /* Clear the eof marker.  */
+            eof_marker =  0;
+
+            /* Loop through file name fields.  */
+            for (i = 1, k = (26 * (card - 1)) & 0xFFFFFFFF; i < FX_DIR_ENTRY_SIZE; i += 2)
+            {
+
+                /* Process relative to specific fields.  */
+                if ((i == 11) || (i == 26))
+                {
+                    continue;
+                }
+
+                if (i == 13)
+                {
+                    i = 12;
+                    continue;
+                }
+
+                /* Determine if the EOF marker is present.  */
+                if (eof_marker)
+                {
+
+                    work_ptr[i] = eof_marker;
+                    work_ptr[i + 1] = eof_marker;
+                }
+                else if (k < (unicode_name_length * 2))
+                {
+
+                    work_ptr[i] = unicode_name[k];
+                    work_ptr[i + 1] = unicode_name[k + 1];
+                    u =  u + 2;
+                }
+                else if (k == (unicode_name_length * 2))
+                {
+
+                    work_ptr[i] = 0;
+                    work_ptr[i + 1] =  0;
+
+                    /* end of name, pad with 0xff.  */
+                    eof_marker =  (UCHAR)0xff;
+                }
+
+                k =  k + 2;
+            }
+
+            /* Decrement the card.  */
+            card--;
+
+            /* Setup pointers for the name write.  */
+            work_ptr += FX_DIR_ENTRY_SIZE;
+            byte_offset += FX_DIR_ENTRY_SIZE;
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+            /* Update changed_size. */
+            changed_size += FX_DIR_ENTRY_SIZE;
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+            /* Determine if the write is within the current sector.   */
+            if (byte_offset >= media_ptr -> fx_media_bytes_per_sector)
+            {
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                if (media_ptr -> fx_media_fault_tolerant_enabled)
+                {
+
+                    /* Redirect this request to log file. */
+                    status = _fx_fault_tolerant_add_dir_log(media_ptr, (ULONG64) logical_sector, changed_offset, changed_ptr, changed_size);
+                }
+                else
+                {
+
+                    /* Write the current sector out.  */
+                    status =  _fx_utility_logical_sector_write(media_ptr, (ULONG64) logical_sector,
+                                                               sector_base_ptr, ((ULONG) 1), FX_DIRECTORY_SECTOR);
+                }
+
+
+                /* Determine if an error occurred.  */
+                if (status != FX_SUCCESS)
+                {
+
+                    /* Return the error status.  */
+                    return(status);
+                }
+#else /* FX_ENABLE_FAULT_TOLERANT */
+
+                /* Write the current sector out.  */
+                /* Note: Since the sector is in the cache after a sector read, therefore _fx_utility_logical_sector_write
+                   always returns success when FX_ENABLE_FAULT_TOLERANT is not defined.  In other words, the checking
+                   on the return value is needed only when FX_ENABLE_FAULT_TOLERANT is defined. */
+                _fx_utility_logical_sector_write(media_ptr, (ULONG64) logical_sector,
+                                                 sector_base_ptr, ((ULONG) 1), FX_DIRECTORY_SECTOR);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+                /* Determine if we are in the root directory.  */
+                if (logical_sector >= (ULONG)(media_ptr -> fx_media_data_sector_start))
+                {
+
+                    /* Determine the next sector of the directory entry.  */
+                    if (relative_sector < (media_ptr -> fx_media_sectors_per_cluster - 1))
+                    {
+
+                        /* More sectors in this cluster.  */
+
+                        /* Simply increment the logical sector.  */
+                        logical_sector++;
+
+                        /* Increment the relative sector.  */
+                        relative_sector++;
+                    }
+                    else
+                    {
+
+                        /* We need to move to the next cluster.  */
+
+                        /* Pickup the next cluster.  */
+                        status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
+
+                        /* Check for I/O error.  */
+                        if (status != FX_SUCCESS)
+                        {
+
+                            /* Return error code.  */
+                            return(status);
+                        }
+
+                        /* Copy next cluster to the current cluster.  */
+                        cluster =  next_cluster;
+
+                        /* Check the value of the new cluster - it must be a valid cluster number
+                           or something is really wrong!  */
+                        if ((cluster < FX_FAT_ENTRY_START) || (cluster > media_ptr -> fx_media_fat_reserved))
+                        {
+
+                            /* Send error message back to caller.  */
+                            return(FX_FILE_CORRUPT);
+                        }
+
+                        /* Setup the relative sector (this is zero for subsequent cluster.  */
+                        relative_sector =  0;
+
+                        /* Calculate the next logical sector.  */
+                        logical_sector =   ((ULONG)media_ptr -> fx_media_data_sector_start) +
+                            (((ULONG)cluster - FX_FAT_ENTRY_START) *
+                             ((ULONG)media_ptr -> fx_media_sectors_per_cluster));
+                    }
+                }
+                else
+                {
+
+                    /* Increment the logical sector.  */
+                    logical_sector++;
+
+                    /* Determine if the logical sector is valid.  */
+                    if (logical_sector >= (ULONG)(media_ptr -> fx_media_data_sector_start))
+                    {
+
+                        /* We have exceeded the root directory.  */
+
+                        /* Send error message back to caller.  */
+                        return(FX_FILE_CORRUPT);
+                    }
+                }
+
+                /* Read the next logical sector.  */
+                status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) logical_sector,
+                                                          media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
+
+                /* Determine if an error occurred.  */
+                if (status != FX_SUCCESS)
+                {
+
+                    /* Return the error status.  */
+                    return(status);
+                }
+
+                /* Move to the next sector buffer.  */
+                sector_base_ptr = media_ptr -> fx_media_memory_buffer;
+
+                /* Setup new buffer pointers.  */
+                byte_offset =  0;
+                work_ptr = sector_base_ptr;
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+                /* Initialize data for fault tolerant. */
+                changed_ptr = work_ptr;
+                changed_size = 0;
+                changed_offset = 0;
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+            }
+        }
+    }
+
+    /* Check for an error!  */
+    if (u != (unicode_name_length * 2))
+    {
+
+        /* Return an error!  */
+        return(FX_FILE_CORRUPT);
+    }
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    if (media_ptr -> fx_media_fault_tolerant_enabled)
+    {
+
+        /* Redirect this request to log file. */
+        status = _fx_fault_tolerant_add_dir_log(media_ptr, (ULONG64) logical_sector, changed_offset, changed_ptr, changed_size);
+    }
+    else
+    {
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Write the directory sector to the media.  */
+        status =  _fx_utility_logical_sector_write(media_ptr, (ULONG64) logical_sector,
+                                                   sector_base_ptr, ((ULONG) 1), FX_DIRECTORY_SECTOR);
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    }
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+    
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_unicode_directory_entry_read.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_unicode_directory_entry_read.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_unicode_directory_entry_read.c	(revision 30)
@@ -0,0 +1,748 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Unicode                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_unicode.h"
+#include "fx_utility.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_unicode_directory_entry_read                    PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function reads a unicode directory entry.                      */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Pointer to media              */
+/*    source_dir                            Pointer to source directory   */
+/*    entry_ptr                             Entry index in the directory  */
+/*    destination_ptr                       Destination directory         */
+/*    unicode_name                          Destination unicode name      */
+/*    unicode_size                          Destination unicode name size */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    Completion Status                                                   */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_FAT_entry_read            Read a FAT entry              */
+/*    _fx_utility_logical_sector_read       Read a logical sector         */
+/*    _fx_utility_16_unsigned_read          Read a 2-byte value           */
+/*    _fx_utility_32_unsigned_read          Read a 4-byte value           */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Unicode Utilities                                                   */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_unicode_directory_entry_read(FX_MEDIA *media_ptr, FX_DIR_ENTRY *source_dir,
+                                       ULONG *entry_ptr, FX_DIR_ENTRY *destination_ptr,
+                                       UCHAR *unicode_name, ULONG *unicode_size)
+{
+
+UINT   i, j, k, card, dotflag, get_short_name;
+UINT   number_of_lfns;
+UINT   status;
+ULONG  cluster, next_cluster = 0;
+UINT   relative_cluster;
+UINT   relative_sector;
+ULONG  logical_sector;
+ULONG  byte_offset;
+ULONG  bytes_per_cluster;
+UCHAR *read_ptr;
+CHAR  *short_name_ptr;
+ULONG  entry = *entry_ptr;
+UINT   u;
+
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of directory entry read requests.  */
+    media_ptr -> fx_media_directory_entry_reads++;
+#endif
+
+    /* Calculate the byte offset of this directory entry.  */
+    byte_offset =  entry * FX_DIR_ENTRY_SIZE;
+
+    /* Determine if a sub-directory or FAT32 root directory is specified.  */
+    if ((source_dir) || (media_ptr -> fx_media_32_bit_FAT))
+    {
+
+        /* Yes, a sub-directory is present.  */
+
+        /* Calculate the number of bytes per cluster.  */
+        bytes_per_cluster =  ((ULONG)media_ptr -> fx_media_bytes_per_sector) *
+            ((ULONG)media_ptr -> fx_media_sectors_per_cluster);
+
+        /* Check for invalid value.  */
+        if (bytes_per_cluster == 0)
+        {
+
+            /* Invalid media, return error.  */
+            return(FX_MEDIA_INVALID);
+        }
+
+        /* Now determine the relative cluster in the sub-directory file.  */
+        relative_cluster =   (UINT)(byte_offset / bytes_per_cluster);
+
+        /* Calculate the byte offset within the cluster.  */
+        byte_offset =  byte_offset % bytes_per_cluster;
+
+        /* Now figure out the relative sector within the cluster.  */
+        relative_sector =    (UINT)(byte_offset / ((ULONG)media_ptr -> fx_media_bytes_per_sector));
+
+        /* Read the directory sector into the internal memory buffer.  */
+
+        /* Determine if there is a sub-directory.  */
+        if (source_dir)
+        {
+
+            /* Determine if this source directory has valid information from the previous call.  */
+            if ((source_dir -> fx_dir_entry_last_search_cluster) &&
+                (source_dir -> fx_dir_entry_last_search_relative_cluster <= relative_cluster) &&
+                (source_dir -> fx_dir_entry_last_search_log_sector == source_dir -> fx_dir_entry_log_sector) &&
+                (source_dir -> fx_dir_entry_last_search_byte_offset == source_dir -> fx_dir_entry_byte_offset))
+            {
+
+                /* Use the previous information to start the search.  */
+                cluster =  source_dir -> fx_dir_entry_last_search_cluster;
+
+                /* Setup the relative cluster index to the saved relative cluster.  */
+                i =  source_dir -> fx_dir_entry_last_search_relative_cluster;
+
+                /* Clear the search cluster.  It will be updated prior to successful return.  */
+                source_dir -> fx_dir_entry_last_search_cluster =  0;
+            }
+            else
+            {
+
+                /* Nothing from the previous directory read, just setup the starting cluster to the
+                   beginning of the sub-directory.  */
+                cluster =  source_dir -> fx_dir_entry_cluster;
+
+                /* Setup the relative cluster index to zero.  */
+                i =  0;
+            }
+        }
+        else
+        {
+
+            /* No, setup the starting cluster to the FAT32 root cluster.  */
+            cluster =  media_ptr -> fx_media_root_cluster_32;
+
+            /* Setup the relative cluster index to zero.  */
+            i =  0;
+        }
+
+        /* Loop to position to the appropriate cluster.  */
+        while (i < relative_cluster)
+        {
+
+            /* Check the value of the new cluster - it must be a valid cluster number
+               or something is really wrong!  */
+            if ((cluster < FX_FAT_ENTRY_START) || (cluster > media_ptr -> fx_media_fat_reserved))
+            {
+
+                /* Send error message back to caller.  */
+                return(FX_FILE_CORRUPT);
+            }
+
+            /* Read the next cluster.  */
+            status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
+
+            /* There is a potential for loop, but hardly anything can be done */
+
+            /* Check for I/O error.  */
+            if (status != FX_SUCCESS)
+            {
+
+                /* Return error code.  */
+                return(status);
+            }
+
+            /* Setup the actual cluster.  */
+            cluster = next_cluster;
+
+            /* Increment the relative cluster number.  */
+            i++;
+        }
+
+        /* At this point, the directory data sector needs to be read.  */
+        logical_sector =    ((ULONG)media_ptr -> fx_media_data_sector_start) +
+            (((ULONG)cluster - FX_FAT_ENTRY_START) *
+             ((ULONG)media_ptr -> fx_media_sectors_per_cluster)) +
+            relative_sector;
+
+        /* Read the logical directory sector.  */
+        status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) logical_sector,
+                                                  media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
+
+        /* Determine if an error occurred.  */
+        if (status != FX_SUCCESS)
+        {
+
+            /* Return error code.  */
+            return(status);
+        }
+
+        /* Calculate the byte offset within this sector.  */
+        byte_offset =  byte_offset % media_ptr -> fx_media_bytes_per_sector;
+    }
+    else
+    {
+
+        /* Read the entry from the root directory.  */
+
+        /* Determine which sector the requested root directory entry is in.  */
+        logical_sector =  (byte_offset / media_ptr -> fx_media_bytes_per_sector) +
+            (ULONG)media_ptr -> fx_media_root_sector_start;
+
+        /* Read the logical directory sector.  */
+        status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) logical_sector,
+                                                  media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
+
+        /* Determine if an error occurred.  */
+        if (status != FX_SUCCESS)
+        {
+
+            /* Return error code.  */
+            return(status);
+        }
+
+        /* Set the cluster and relative variables (not used in this case) to avoid any compiler
+           warnings.  */
+        relative_cluster =  relative_sector =  cluster =  0;
+
+        /* Now calculate the byte offset into this sector.  */
+        byte_offset =  byte_offset -
+            ((logical_sector - (ULONG)media_ptr -> fx_media_root_sector_start) *
+             media_ptr -> fx_media_bytes_per_sector);
+    }
+
+    /* Setup a pointer into the buffer.  */
+    read_ptr =  (UCHAR *)media_ptr -> fx_media_memory_buffer + (UINT)byte_offset;
+
+    /* Save the logical sector and byte offset in the returned directory entry.  */
+    destination_ptr -> fx_dir_entry_log_sector =       logical_sector;
+    destination_ptr -> fx_dir_entry_byte_offset =      byte_offset;
+
+    /* Clear the short file name information.  */
+    destination_ptr -> fx_dir_entry_long_name_shorted =  0;
+    destination_ptr -> fx_dir_entry_short_name[0]     =  0;
+
+    /* Setup short name pointer.  */
+    short_name_ptr =  destination_ptr -> fx_dir_entry_name;
+
+    /* Initialize the unicode index.  */
+    u =  0;
+
+    /* Check if long file name exists.  */
+    get_short_name =  0;
+    if ((*(read_ptr + 11) == (UCHAR)FX_LONG_NAME) && (*read_ptr != (UCHAR)FX_DIR_ENTRY_FREE))
+    {
+
+        /* Collate the long name. */
+
+
+        /* Save the number of LFN entries.  */
+        number_of_lfns =  (UINT)(*read_ptr & (UCHAR)0x1f);
+
+        if(number_of_lfns == 0)
+        {
+            /* Number of LFN cannot is 1-based.  Therefore it cannot be zero. */
+            return(FX_FILE_CORRUPT);
+        }
+        else 
+        {
+            /* Pickup the file name length.  */
+            i = (number_of_lfns - 1) * FX_LONG_NAME_ENTRY_LEN;
+        }
+
+        /* Check the file name size.  */
+        if (i >= (FX_MAX_LONG_NAME_LEN - 1))
+        {
+
+            /* Name is too big, shorten it.  */
+            get_short_name = 1;
+            destination_ptr -> fx_dir_entry_long_name_shorted =  (UINT)(*read_ptr & (UCHAR)0x1f);
+        }
+        else
+        {
+
+            /* Size of name is fine, save pointer to short file name.  */
+            short_name_ptr = destination_ptr -> fx_dir_entry_short_name;
+
+            /* Loop to make sure the long file name is NULL terminated.  */
+            j = i + FX_LONG_NAME_ENTRY_LEN + 1;
+            do
+            {
+                /* Place a NULL in the long name.  */
+                destination_ptr -> fx_dir_entry_name[i] =  0;
+
+                /* Position to the next entry.  */
+                i++;
+            } while ((i < j) && (i < FX_MAX_LONG_NAME_LEN));
+        }
+
+        /* Loop to pickup the rest of the name.  */
+        do
+        {
+
+            /* Get the lower 5 bit containing the cardinality.  */
+            card = (*read_ptr) & 0x1f;
+
+            if(card == 0)
+            {
+
+                /* Number of LFN starts from one.  Therefore it cannot be zero. */
+                return(FX_FILE_CORRUPT);
+            }
+            else
+            {
+                card = card - 1;
+            }
+            /* For simplicity no checksum or cardinality checking is done */
+            if ((get_short_name == 0) || (u))
+            {
+
+                /* Loop to pickup name.  */
+                for (i = 1, j = 0, k = 0; i < FX_DIR_ENTRY_SIZE; i += 2)
+                {
+
+                    if ((i == 11) || (i == 26))
+                    {
+                        continue;
+                    }
+
+                    /* i = 12, 27 is not generated due to +=2 */
+                    if (i == 13)
+                    {
+                        i = 12;
+                        continue; /* this time next unicode is byte offset 14*/
+                    }
+
+                    /* Determine if there is an actual unicode character present.  */
+                    if (read_ptr[i + 1])
+                    {
+
+                        /* Extended byte is non-zero, make sure both bytes of the unicode entry are not
+                           all ones, since this is a normal case.  */
+                        if ((read_ptr[i + 1] != (UCHAR)0xFF) || (read_ptr[i] != (UCHAR)0xFF))
+                        {
+
+                            /* Name is an actual unicode name, shorten it.  */
+                            get_short_name = 1;
+
+                            /* Save the number of directory entries the LFN has.  This will be
+                               used later when updating the 8.3 portion of the LFN.  */
+                            destination_ptr -> fx_dir_entry_long_name_shorted =  number_of_lfns;
+
+                            /* Setup short name pointer.  */
+                            short_name_ptr =  destination_ptr -> fx_dir_entry_name;
+                        }
+                    }
+
+                    /* Determine if the character is NULL.  */
+                    if (((read_ptr[i] == FX_NULL) && (read_ptr[i + 1] == FX_NULL)) ||
+                        ((read_ptr[i] == (UCHAR)0xFF) && (read_ptr[i + 1] == (UCHAR)0xFF)))
+                    {
+                        continue;
+                    }
+
+                    /* Determine if the name is too big.  */
+                    if ((card * 13 + j) >= (FX_MAX_LONG_NAME_LEN - 1))
+                    {
+
+                        /* Name is actually too big, shorten it.  */
+                        get_short_name =  1;
+
+                        /* Save the number of directory entries the LFN has.  This will be
+                           used later when updating the 8.3 portion of the LFN.  */
+                        destination_ptr -> fx_dir_entry_long_name_shorted =  number_of_lfns;
+
+                        /* Also reposition the short name pointer.  */
+                        short_name_ptr =  destination_ptr -> fx_dir_entry_name;
+
+                        break;
+                    }
+
+                    /* Each entry contains 13 unicode and first byte ASCII, second byte is extended. */
+                    if (get_short_name == 0)
+                    {
+                        destination_ptr -> fx_dir_entry_name[13 * card + j] = (CHAR)read_ptr[i];
+                    }
+
+                    /* Save the potential unicode characters.  */
+                    unicode_name[k + 26 * card + j] =    read_ptr[i];
+                    unicode_name[k + 26 * card + j + 1] =  read_ptr[i + 1];
+                    k++;
+                    u++;
+
+                    j++;
+                }
+            }
+
+            /* Determine if a new sector needs to be read.  */
+            if (byte_offset + FX_DIR_ENTRY_SIZE >= media_ptr -> fx_media_bytes_per_sector)
+            {
+
+                /* Determine if a sub-directory or FAT32 root directory is specified.  */
+                if ((source_dir) || (media_ptr -> fx_media_32_bit_FAT))
+                {
+
+                    /* Determine the next sector of the directory entry.  */
+                    if (relative_sector < (media_ptr -> fx_media_sectors_per_cluster - 1))
+                    {
+
+                        /* More sectors in this cluster.  */
+
+                        /* Simply increment the logical sector.  */
+                        logical_sector++;
+
+                        /* Increment the relative sector.  */
+                        relative_sector++;
+                    }
+                    else
+                    {
+
+                        /* We need to move to the next cluster.  */
+
+                        /* Pickup the next cluster.  */
+                        status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
+
+                        /* Check for I/O error.  */
+                        if (status != FX_SUCCESS)
+                        {
+
+                            /* Return error code.  */
+                            return(status);
+                        }
+
+                        /* Copy next cluster to the current cluster.  */
+                        cluster =  next_cluster;
+
+                        /* Check the value of the new cluster - it must be a valid cluster number
+                           or something is really wrong!  */
+                        if ((cluster < FX_FAT_ENTRY_START) || (cluster > media_ptr -> fx_media_fat_reserved))
+                        {
+
+                            /* Send error message back to caller.  */
+                            return(FX_FILE_CORRUPT);
+                        }
+
+                        /* Now increment the relative cluster.  */
+                        relative_cluster++;
+
+                        /* Setup the relative sector (this is zero for subsequent cluster.  */
+                        relative_sector =  0;
+
+                        /* Calculate the next logical sector.  */
+                        logical_sector =   ((ULONG)media_ptr -> fx_media_data_sector_start) +
+                            (((ULONG)cluster - FX_FAT_ENTRY_START) *
+                             ((ULONG)media_ptr -> fx_media_sectors_per_cluster));
+                    }
+                }
+                else
+                {
+
+                    /* Non-FAT 32 root directory.  */
+
+                    /* Advance to the next sector.  */
+                    logical_sector++;
+
+                    /* Determine if the logical sector is valid.  */
+                    if (logical_sector >= (ULONG)(media_ptr -> fx_media_root_sector_start + media_ptr -> fx_media_root_sectors))
+                    {
+
+                        /* Trying to read past root directory - send error message back to caller.  */
+                        return(FX_FILE_CORRUPT);
+                    }
+                }
+
+                /* Read the new sector.  */
+                status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) logical_sector,
+                                                          media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
+
+                /* Check I/O status.  */
+                if (status != FX_SUCCESS)
+                {
+                    return(status);
+                }
+
+                /* Set the byte offset to 0 for new sector.  */
+                byte_offset = 0;
+            }
+            else
+            {
+
+                /* Calculate the new byte offset.  */
+                byte_offset += FX_DIR_ENTRY_SIZE;
+            }
+
+            /* Calculate the next read pointer.  */
+            read_ptr =  (UCHAR *)media_ptr -> fx_media_memory_buffer + (UINT)byte_offset;
+
+            /* Move to the next entry.  */
+            entry++;
+        } while (card > 0);
+
+        /* Set flag indicating long file name is present.  */
+        destination_ptr -> fx_dir_entry_long_name_present = 1;
+    }
+    else
+    {
+        /* No long file name is present.  */
+        get_short_name = 1;
+    }
+
+    /* Determine if we need to clear the long name flag.  */
+    if (get_short_name == 1)
+    {
+
+        /* Clear the long name flag.  */
+        destination_ptr -> fx_dir_entry_long_name_present =  0;
+    }
+
+    /* Store the unicode name size.  */
+    *unicode_size =  u;
+
+    /* Pickup the short file name.  */
+    short_name_ptr[0] =  0;
+    dotflag =  0;
+    for (i = 0, j = 0; i < (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE); i++)
+    {
+
+        /* Check for a NULL.  */
+        if ((CHAR)read_ptr[i] == 0)
+        {
+            break;
+        }
+
+        /* Check for a dot.  This happens for the first two directory entries, no
+           extra dot is needed.  */
+        if ((CHAR)read_ptr[i] == '.')
+        {
+            dotflag =  2;
+        }
+
+        /* Check for a space.  */
+        if ((CHAR)read_ptr[i] == ' ')
+        {
+            /* Put a dot if a character comes after space.  */
+            if (dotflag == 0)
+            {
+                dotflag =  1;
+            }
+            continue;
+        }
+
+        /* Check for the main short file name size.  */
+        if (i == FX_DIR_NAME_SIZE)
+        {
+            /* Check to see if we need to insert a dot.  */
+            if (dotflag == 0)
+            {
+                dotflag =  1;
+            }
+        }
+
+        /* Check to see if we need to add a dot.  */
+        if (dotflag == 1)
+        {
+            /* Add dot to short file name.  */
+            short_name_ptr[j++] =  '.';
+            dotflag =  2;    /* no more dot for spaces */
+        }
+
+        /* Copy a character.  */
+        short_name_ptr[j] =  (CHAR)read_ptr[i];
+
+        /* Increment size.  */
+        j++;
+    }
+
+    /* Determine if a long file name is present and its associated short file
+       name is actually free.  */
+    if ((destination_ptr -> fx_dir_entry_long_name_present) && (((UCHAR)short_name_ptr[0]) == (UCHAR)FX_DIR_ENTRY_FREE))
+    {
+
+        /* Yes, the short file name is really free even though long file name entries directly precede it.
+           In this case, simply place the free directory marker at the front of the long file name.  */
+        destination_ptr -> fx_dir_entry_name[0] =  (CHAR)FX_DIR_ENTRY_FREE;
+        short_name_ptr[0] =  (CHAR)0;
+    }
+
+    /* Determine if the short name pointer is NULL while the read pointer is
+       non-NULL.  */
+    if ((short_name_ptr[0] == 0) && (read_ptr[0] == ' '))
+    {
+
+        /* This condition can occur with an all blank volume name.  Simply
+           copy the volume name to the short name in this case.  */
+        for (j = 0; j < (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE); j++)
+        {
+
+            /* Copy a byte of the volume name.  */
+            short_name_ptr[j] =  (CHAR)read_ptr[j];
+        }
+    }
+
+    /* Set end of string to null.  */
+    short_name_ptr[j] = 0;
+
+    /* Load up the destination directory entry.  */
+    read_ptr += (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE);
+
+    /* Copy the attribute into the destination.  */
+    destination_ptr -> fx_dir_entry_attributes =  *read_ptr++;
+
+    /* Pickup the reserved byte.  */
+    destination_ptr -> fx_dir_entry_reserved =  *read_ptr++;
+
+    /* Check for an undocumented NT file name feature for optimizing the storage
+       of all lower case file names that otherwise are valid 8.3 file names. The
+       following reserved bit definitions are present:
+
+         BIT3 - set if 8.3 is all in lower case and no extended filename.
+         BIT4 - set for file, clear for directory entry if no extended filename.
+
+       This is true for all NT systems. Prior to NT follows MSDOS FAT documentation and
+       is set to 0x00, all bits cleared. Therefore if BIT3 is set force lowercase.  */
+    if ((get_short_name) && (destination_ptr -> fx_dir_entry_reserved & 0x08))
+    {
+
+        /* Microsoft undocumented NT file name feature... convert short name to lower
+           case.  */
+        for (j = 0; j <= (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE) && (short_name_ptr[j] != 0x00); j++)
+        {
+
+            /* Determine if an upper case character is present.  */
+            if ((short_name_ptr[j] >= 'A') && (short_name_ptr[j] <= 'Z'))
+            {
+
+                /* Yes, an upper case character is present. Force it to lower case.  */
+                short_name_ptr[j] =  (CHAR)((INT)short_name_ptr[j] + 32);
+            }
+        }
+    }
+
+    /* Pickup the created time in milliseconds.  */
+    destination_ptr -> fx_dir_entry_created_time_ms =  *read_ptr++;
+
+    /* Pickup the created time.  */
+    destination_ptr -> fx_dir_entry_created_time =  _fx_utility_16_unsigned_read(read_ptr);
+    read_ptr =  read_ptr + 2;  /* Always 2 bytes */
+
+    /* Pickup the created date.  */
+    destination_ptr -> fx_dir_entry_created_date =  _fx_utility_16_unsigned_read(read_ptr);
+    read_ptr =  read_ptr + 2;  /* Always 2 bytes */
+
+    /* Pickup the last accessed date.  */
+    destination_ptr -> fx_dir_entry_last_accessed_date =  _fx_utility_16_unsigned_read(read_ptr);
+    read_ptr =  read_ptr + 2;  /* Always 2 bytes */
+
+    /* read the upper 2 bytes of starting cluster - required only for 32 bit FAT */
+    if (media_ptr -> fx_media_32_bit_FAT)
+    {
+
+        /* FAT32 only.  */
+        destination_ptr -> fx_dir_entry_cluster =  _fx_utility_16_unsigned_read(read_ptr);
+        destination_ptr -> fx_dir_entry_cluster <<= 16;
+    }
+    else
+    {
+        /* Not required for non FAT32.  */
+        destination_ptr -> fx_dir_entry_cluster =  0;
+    }
+
+    /* Advance the read pointer.  */
+    read_ptr =  read_ptr + 2;  /* Always 2 bytes */
+
+    /* Copy the time into the destination.  */
+    destination_ptr -> fx_dir_entry_time =  _fx_utility_16_unsigned_read(read_ptr);
+    read_ptr =  read_ptr + 2;  /* Always 2 bytes */
+
+    /* Copy the date into the destination.  */
+    destination_ptr -> fx_dir_entry_date =  _fx_utility_16_unsigned_read(read_ptr);
+    read_ptr =  read_ptr + 2;  /* Always 2 bytes */
+
+    /* Copy the starting cluster into the destination.  */
+    destination_ptr -> fx_dir_entry_cluster +=  _fx_utility_16_unsigned_read(read_ptr);
+    read_ptr =  read_ptr + 2;  /* Always 2 bytes */
+
+    /* Copy the file size into the destination.  */
+    destination_ptr -> fx_dir_entry_file_size =  _fx_utility_32_unsigned_read(read_ptr);
+
+    /* Clear the destination search specific fields.  */
+    destination_ptr -> fx_dir_entry_last_search_cluster =           0;
+    destination_ptr -> fx_dir_entry_last_search_relative_cluster =  0;
+    destination_ptr -> fx_dir_entry_last_search_log_sector =        0;
+    destination_ptr -> fx_dir_entry_last_search_byte_offset =       0;
+
+    /* Remember the entry number.  */
+    destination_ptr -> fx_dir_entry_number =  entry;
+
+    /* Return entry number.  */
+    *entry_ptr =  entry;
+
+    /* Determine if we should remember the last cluster and relative cluster.  */
+    if (source_dir)
+    {
+
+        /* Yes, remember the last cluster and relative cluster for a subsequent call
+           to read a directory entry.  */
+        source_dir -> fx_dir_entry_last_search_cluster =           cluster;
+        source_dir -> fx_dir_entry_last_search_relative_cluster =  relative_cluster;
+
+        /* Also remember several other items that are unique to the directory... just to verify that the
+           search information can be used.  */
+        source_dir -> fx_dir_entry_last_search_log_sector =        source_dir -> fx_dir_entry_log_sector;
+        source_dir -> fx_dir_entry_last_search_byte_offset =       source_dir -> fx_dir_entry_byte_offset;
+    }
+
+    /* Return success to the caller.  */
+    return(FX_SUCCESS);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_unicode_directory_rename.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_unicode_directory_rename.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_unicode_directory_rename.c	(revision 30)
@@ -0,0 +1,353 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Unicode                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_unicode.h"
+#include "fx_directory.h"
+#include "fx_utility.h"
+#ifdef FX_ENABLE_FAULT_TOLERANT
+#include "fx_fault_tolerant.h"
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_unicode_directory_rename                        PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function creates the specified unicode directory.              */
+/*    This function first attempts to find the specified directory.       */
+/*    If found, the unicode rename request is valid and the directory     */
+/*    will be changed to the new unicode name. Otherwise, if the directory*/
+/*    is not found, the appropriate error code is returned to the caller. */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Pointer to media              */
+/*    old_unicode_name                      Pointer to old unicode name   */
+/*    old_unicode_length                    Old unicode name length       */
+/*    new_unicode_name                      Pointer to new unicode name   */
+/*    new_unicode_length                    Old unicode name length       */
+/*    new_short_name                        Pointer to new short name     */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    Completion Status                                                   */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_unicode_short_name_get            Get the directory short name  */
+/*    _fx_unicode_directory_search          Search for unicode name       */
+/*    _fx_unicode_directory_entry_change    Change unicode file name      */
+/*    _fx_directory_rename                  Rename the directory          */
+/*    _fx_directory_search                  Search directory              */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_unicode_directory_rename(FX_MEDIA *media_ptr, UCHAR *old_unicode_name, ULONG old_unicode_length,
+                                   UCHAR *new_unicode_name, ULONG new_unicode_length, CHAR *new_short_name)
+{
+
+FX_DIR_ENTRY dir_entry;
+UINT         i, status;
+ULONG        temp_length;
+CHAR         old_dir_short_name[13];
+CHAR         new_dir_short_name[13];
+UCHAR        alpha, beta;
+
+
+    /* Clear the return short name.  */
+    new_short_name[0] =  FX_NULL;
+
+    /* Set shortname to null.  */
+    old_dir_short_name[0] =  FX_NULL;
+    new_dir_short_name[0] =  FX_NULL;
+
+    /* Check the media to make sure it is open.  */
+    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
+    {
+
+        /* Return the media not opened error.  */
+        return(FX_MEDIA_NOT_OPEN);
+    }
+
+#ifdef FX_ENABLE_EXFAT
+    /* Check if media format is exFAT.  */
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+
+        /* Return the not implemented error.  */
+        return(FX_NOT_IMPLEMENTED);
+    }
+#endif
+
+    /* Get the old short name.  */
+    status = _fx_unicode_short_name_get(media_ptr, old_unicode_name, old_unicode_length, &old_dir_short_name[0]);
+
+    /* Determine if the search was successful.  */
+    if (status != FX_SUCCESS)
+    {
+
+        /* Return the error code.  */
+        return(status);
+    }
+
+    /* Protect media.  */
+    FX_PROTECT
+
+    /* Setup temporary length.  */
+    temp_length =  new_unicode_length;
+
+    /* Setup pointer to media name buffer.  */
+    dir_entry.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
+
+    /* Clear the short name string.  */
+    dir_entry.fx_dir_entry_short_name[0] =  FX_NULL;
+
+    /* Determine if the new directory name is already present.  */
+    status =  _fx_unicode_directory_search(media_ptr, &dir_entry, (UCHAR *)new_dir_short_name, sizeof(new_dir_short_name), new_unicode_name, &temp_length, 0);
+
+    /* Determine if the search was successful.  */
+    if (status == FX_SUCCESS)
+    {
+
+        /* Determine if the name length are equal.  */
+        if (old_unicode_length == new_unicode_length)
+        {
+
+            /* Determine if the new name simply has a UNICODE case change. If so, simply let the processing
+               continue.  */
+            i =  0;
+            do
+            {
+
+                /* Pickup an old name and new name character and convert to upper case if necessary.  */
+                alpha =  old_unicode_name[i * 2];
+                if ((alpha >= 'a') && (alpha <= 'z') && (old_unicode_name[i * 2 + 1] == 0))
+                {
+
+                    /* Lower case, convert to upper case!  */
+                    alpha =  (UCHAR)((INT)alpha - 0x20);
+                }
+                beta =   new_unicode_name[i * 2];
+                if ((beta >= 'a') && (beta <= 'z') && (new_unicode_name[i * 2 + 1] == 0))
+                {
+
+                    /* Lower case, convert to upper case!  */
+                    beta =  (UCHAR)((INT)beta - 0x20);
+                }
+
+                /* Now compare the characters.  */
+                if (alpha != beta)
+                {
+
+                    /* Get out of this loop!  */
+                    break;
+                }
+
+                /* Pickup the high bytes. */
+                alpha = old_unicode_name[i * 2 + 1];
+                beta =   new_unicode_name[i * 2 + 1];
+
+                /* Now compare the byte.  */
+                if ((alpha != beta))
+                {
+
+                    /* Get out of this loop!  */
+                    break;
+                }
+
+                /* Move to next character.  */
+                i++;
+            } while (i < old_unicode_length);
+        }
+        else
+        {
+            alpha = 0;
+            beta = 1;
+        }
+
+        /* Now determine if the names match.  */
+        if (alpha != beta)
+        {
+
+            /* Yes, the directory name already exists in the target location.  */
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* Return the error code.  */
+            return(FX_ALREADY_CREATED);
+         }
+    }
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    /* Start transaction. */
+    _fx_fault_tolerant_transaction_start(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Okay, at this point we need to create a new long directory name that has enough space for the
+       eventual unicode directory name.  */
+
+    /* Copy the characters from the unicode directory name and make sure they are
+       within the ASCII range.  */
+    _fx_unicode_temp_long_file_name[0] =  'z';
+    for (i = 1; i < new_unicode_length; i++)
+    {
+
+        /* Build temporary long file name.  */
+        _fx_unicode_temp_long_file_name[i] =  (UCHAR)((UINT)'0' + (i % 9));
+    }
+    _fx_unicode_temp_long_file_name[i] =  FX_NULL;
+
+    /* Loop to try different temp long file names... if necessary.  */
+    do
+    {
+
+        /* Rename the directory name.  */
+        status =  _fx_directory_rename(media_ptr, old_dir_short_name, (CHAR *)_fx_unicode_temp_long_file_name);
+
+        /* Determine if there was an error.  */
+        if (status == FX_ALREADY_CREATED)
+        {
+
+            /* Adjust the name slightly and try again!  */
+            _fx_unicode_temp_long_file_name[0]--;
+
+            /* Determine if it is outside the lower case boundary.  */
+            if (_fx_unicode_temp_long_file_name[0] < 0x61)
+            {
+                break;
+            }
+        }
+    } while (status == FX_ALREADY_CREATED);
+
+    /* Determine if there was an error.  */
+    if (status)
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return error.  */
+        return(status);
+    }
+
+    /* Setup pointer to media name buffer.  */
+    dir_entry.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
+
+    /* Clear the short name string.  */
+    dir_entry.fx_dir_entry_short_name[0] =  FX_NULL;
+
+    /* Search the system for the supplied file name.  */
+    status =  _fx_directory_search(media_ptr, (CHAR *)_fx_unicode_temp_long_file_name, &dir_entry, FX_NULL, FX_NULL);
+
+    /* Determine if the search was successful.  */
+    if (status != FX_SUCCESS)
+    {
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the error status.  */
+        return(status);
+    }
+
+    /* We can now change the temporary long file name with the destination unicode name.  */
+    status = _fx_unicode_directory_entry_change(media_ptr, &dir_entry, new_unicode_name, new_unicode_length);
+
+    /* Determine if the rename was successful.  */
+    if (status == FX_SUCCESS)
+    {
+
+        /* Yes, copy the short file name to the destination.  */
+        /* The new short name only have 8 characters, since we didn't include a dot in temp_long_file_name. */
+        for (i = 0; i < FX_DIR_NAME_SIZE; i++)
+        {
+
+            /* Copy a character.  */
+            new_short_name[i] =  dir_entry.fx_dir_entry_short_name[i];
+
+            /* Are we done?  */
+            if (new_short_name[i] == FX_NULL)
+            {
+                break;
+            }
+        }
+    }
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    /* Check for a bad status.  */
+    if (status != FX_SUCCESS)
+    {
+
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the bad status.  */
+        return(status);
+    }
+
+    /* End transaction. */
+    status = _fx_fault_tolerant_transaction_end(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Release the protection.  */
+    FX_UNPROTECT
+
+    /* Return completion status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_unicode_directory_search.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_unicode_directory_search.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_unicode_directory_search.c	(revision 30)
@@ -0,0 +1,501 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Unicode                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_unicode.h"
+#include "fx_utility.h"
+
+#ifndef FX_NO_LOCAL_PATH
+FX_LOCAL_PATH_SETUP
+#endif
+
+
+/* Define several Unicode working arrays...  This keeps the data structures
+   off the local stack.  */
+
+UCHAR _fx_unicode_temp_long_file_name[FX_MAX_LONG_NAME_LEN];
+UCHAR _fx_unicode_search_name[FX_MAX_LONG_NAME_LEN * 2];
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_unicode_directory_search                        PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function searches for the specified unicode or short name.     */
+/*                                                                        */
+/*    Note: The buffer of short_name and unicode_name must be valid to    */
+/*    fill search result. When short_name is a zero length string, search */
+/*    is based on unicode string (terminated with NULL). If it's found    */
+/*    the short name is written back to buffer of short_name. In this case*/
+/*    unicode_name_buffer_length is ignored and short_name_buffer_length  */
+/*    must not be zero to specify the buffer length. If buffer is too     */
+/*    smallfor the result, overflow characters and NULL-terminator are cut*/
+/*    off. When short_name is a valid string, search is based on          */
+/*    short_name (terminated with NULL). If it's found the unicode name is*/
+/*    written back to buffer of unicode_name. In this case                */
+/*    short_name_buffer_length is ignored and unicode_name_buffer_length  */
+/*    must not be zero to specify the unicode buffer length. If buffer is */
+/*    too small for the result, overflow characters are cut off but       */
+/*    NULL-terminator is kept.                                            */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Pointer to media              */
+/*    short_name                            Pointer to short name         */
+/*    short_name_buffer_length              Buffer length for short name  */
+/*    unicode_name                          Pointer to Unicode name       */
+/*    unicode_name_length                   Unicode name length           */
+/*    unicode_name_buffer_length            Buffer length for Unicode name*/
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    Completion Status                                                   */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_unicode_directory_entry_read      Read a full unicode directory */
+/*                                            entry                       */
+/*    _fx_utility_FAT_entry_read            Read a FAT entry              */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Unicode Utilities                                                   */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_unicode_directory_search(FX_MEDIA *media_ptr, FX_DIR_ENTRY *entry_ptr,
+                                   UCHAR *short_name, ULONG short_name_buffer_length, 
+                                   UCHAR *unicode_name, ULONG *unicode_name_length, ULONG unicode_name_buffer_length)
+{
+
+ULONG         i, j;
+UINT          status, found;
+ULONG         cluster, next_cluster = 0;
+ULONG         directory_size;
+FX_DIR_ENTRY  search_dir;
+FX_DIR_ENTRY *search_dir_ptr;
+ULONG         unicode_search_length;
+ULONG         local_unicode_name_length;
+CHAR          unicode_to_short_name[13];
+CHAR         *short_name_ptr;
+
+
+    /* Setup temp unicode name length.  */
+    local_unicode_name_length =  *unicode_name_length;
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of directory search requests.  */
+    media_ptr -> fx_media_directory_searches++;
+#endif
+
+    /* Set the initial search directory to the current working
+       directory - if there is one.  */
+
+    /* First check for a local path pointer stored in the thread control block.  This
+       is only available in ThreadX Version 4 and above.  */
+#ifndef FX_NO_LOCAL_PATH
+    if (_tx_thread_current_ptr -> tx_thread_filex_ptr)
+    {
+
+        /* Determine if the local directory is not the root directory.  */
+        if (((FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr) -> fx_path_directory.fx_dir_entry_name[0])
+        {
+
+            /* Start at the current working directory of the media.  */
+            search_dir =   ((FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr) -> fx_path_directory;
+
+            /* Set the internal pointer to the search directory as well.  */
+            search_dir_ptr =  &search_dir;
+        }
+        else
+        {
+
+            /* We are searching in the root directory.  */
+            search_dir_ptr =  FX_NULL;
+        }
+    }
+    else
+#endif
+    if (media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_name[0])
+    {
+
+        /* Start at the current working directory of the media.  */
+        search_dir =  media_ptr -> fx_media_default_path.fx_path_directory;
+
+        /* Set the internal pointer to the search directory as well.  */
+        search_dir_ptr =  &search_dir;
+    }
+    else
+    {
+
+        /* The current default directory is the root so just set the
+           search directory pointer to NULL.  */
+        search_dir_ptr =  FX_NULL;
+    }
+
+    /* Calculate the directory size.  */
+    if (search_dir_ptr)
+    {
+
+        /* Ensure that the search directory's last search cluster is cleared.  */
+        search_dir_ptr -> fx_dir_entry_last_search_cluster =  0;
+
+        /* Calculate the directory size by counting the allocated
+           clusters for it.  */
+        i =        0;
+        cluster =  search_dir_ptr -> fx_dir_entry_cluster;
+        while ((cluster >= FX_FAT_ENTRY_START) && (cluster < media_ptr -> fx_media_fat_reserved))
+        {
+
+            /* Increment the cluster count.  */
+            i++;
+
+            /* Read the next FAT entry.  */
+            status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
+
+            /* Check the return status.  */
+            if (status != FX_SUCCESS)
+            {
+
+                /* Return the bad status.  */
+                return(status);
+            }
+
+            /* Check for error situation.  */
+            if ((cluster == next_cluster) || (i > media_ptr -> fx_media_total_clusters))
+            {
+
+                /* Return the bad status.  */
+                return(FX_FAT_READ_ERROR);
+            }
+
+            cluster = next_cluster;
+        }
+
+        /* Now we can calculate the directory size.  */
+        directory_size =  (((ULONG)media_ptr -> fx_media_bytes_per_sector) *
+                           ((ULONG)media_ptr -> fx_media_sectors_per_cluster) * i) /
+                           (ULONG)FX_DIR_ENTRY_SIZE;
+
+        /* Also save this in the directory entry so we don't have to
+           calculate it later.  */
+        search_dir_ptr -> fx_dir_entry_file_size =  directory_size;
+    }
+    else
+    {
+
+        /* Directory size is the number of entries in the root directory.  */
+        directory_size =  (ULONG)media_ptr -> fx_media_root_directory_entries;
+    }
+
+    /* Determine if we are searching for a short file name or a unicode file name.  */
+    if (short_name[0] == 0)
+    {
+
+        /* If the unicode name fit into short name length, covert the Unicode to ASCII if possible.  */
+        if (local_unicode_name_length <= 13)
+        {
+            for (j = 0; j < local_unicode_name_length; j++)
+            {
+                if ((unicode_name[j * 2] <= 0x7F) && (unicode_name[j * 2 + 1] == 0))
+                {
+
+                    unicode_to_short_name[j] = (CHAR)unicode_name[j * 2];
+                    if ((unicode_to_short_name[j] >= 'a') && (unicode_to_short_name[j] <= 'z'))
+                    {
+
+                        /* Lower case, convert to upper case!  */
+                        unicode_to_short_name[j] =  (CHAR)((INT)unicode_to_short_name[j] - 0x20);
+                    }
+                }
+                else
+                {
+                    unicode_to_short_name[0] = 0;
+                    break;
+                }
+            }
+        }
+        else
+        {
+            unicode_to_short_name[0] = 0;
+        }
+    }
+    else
+    {
+        unicode_to_short_name[0] = 0;
+    }
+
+    /* Loop through entries in the directory.  Yes, this is a
+       linear search!  */
+    i =      0;
+    do
+    {
+
+        /* Read an entry from the directory.  */
+        status =  _fx_unicode_directory_entry_read(media_ptr, search_dir_ptr, &i, entry_ptr, &_fx_unicode_search_name[0], &unicode_search_length);
+        i++;
+
+        /* Check for error status.  */
+        if (status != FX_SUCCESS)
+        {
+            return(status);
+        }
+
+        /* Determine if this is an empty entry.  */
+        if (((UCHAR)entry_ptr -> fx_dir_entry_name[0] == (UCHAR)FX_DIR_ENTRY_FREE) && (entry_ptr -> fx_dir_entry_short_name[0] == 0))
+        {
+            continue;
+        }
+
+        /* Determine if this is the last directory entry.  */
+        if ((UCHAR)entry_ptr -> fx_dir_entry_name[0] == (UCHAR)FX_DIR_ENTRY_DONE)
+        {
+            break;
+        }
+
+        /* Determine if there is a short name to match.  */
+        if (unicode_to_short_name[0])
+        {
+
+            /* Get the short name pointer.  */
+            if (entry_ptr -> fx_dir_entry_short_name[0])
+            {
+                short_name_ptr =  entry_ptr -> fx_dir_entry_short_name;
+            }
+            else
+            {
+                short_name_ptr =  entry_ptr -> fx_dir_entry_name;
+            }
+
+            for (j = 0; j < local_unicode_name_length; j++)
+            {
+
+                /* Compare characters.  */
+                if (short_name_ptr[j] != unicode_to_short_name[j])
+                {
+                    break;
+                }
+            }
+            if (j == local_unicode_name_length)
+            {
+
+                /* Only the 1st 13 bytes or the buffer length is copied, whichever is smaller.  */
+                if (short_name_buffer_length > 13)
+                {
+                    short_name_buffer_length = 13;
+                }
+
+                /* The names match, copy the short name into the destination.  */
+                for (j = 0; j < short_name_buffer_length; j++)
+                {
+                    short_name[j] = (UCHAR)short_name_ptr[j];
+                }
+
+                /* Return success to caller.  */
+                return(FX_SUCCESS);
+            }
+        }
+
+        /* Determine if this is not a unicode name.  */
+        if (unicode_search_length == 0)
+        {
+            continue;
+        }
+
+        /* Determine if we are searching for a short file name or a unicode file name.  */
+        if (short_name[0])
+        {
+
+            /* We have a short name and need a unicode name.  Compare the short name against the short name in
+               the directory entry for a match.  */
+            found =  FX_TRUE;
+            for (j = 0; j < 12; j++)
+            {
+
+                /* Compare characters...  */
+                if (entry_ptr -> fx_dir_entry_short_name[0])
+                {
+
+                    /* Yes, the return name is in the short name field... compare against it!  */
+                    if (short_name[j] != (UCHAR)entry_ptr -> fx_dir_entry_short_name[j])
+                    {
+
+                        found = FX_FALSE;
+                        break;
+                    }
+                }
+                else
+                {
+
+                    /* No, the return name is in the name field... compare against it!  */
+                    if (short_name[j] != (UCHAR)entry_ptr -> fx_dir_entry_name[j])
+                    {
+
+                        found = FX_FALSE;
+                        break;
+                    }
+                }
+
+                /* Are we done?  */
+                if (short_name[j] == (UCHAR)FX_NULL)
+                {
+                    break;
+                }
+            }
+
+            /* One final compare to see if we have a match.  */
+            if ((found == FX_FALSE) || ((j == 12) && (short_name[12] != 0)))
+            {
+                continue;
+            }
+
+            /* A match was found so copy the unicode name and length and return.  */
+            /* Copy the length.  */
+            *unicode_name_length =  unicode_search_length;
+            
+            /* Check if the name fit in the buffer.  */
+            if (unicode_name_buffer_length < (unicode_search_length + 1) * 2)
+            {
+                unicode_search_length = (unicode_name_buffer_length - 2) / 2;
+            }
+
+            /* Copy the unicode name.   */
+            for (j = 0; j < unicode_search_length * 2; j++)
+            {
+
+                /* Copy one unicode character to the destination...  */
+                unicode_name[j] =  _fx_unicode_search_name[j];
+            }
+
+            /* Make sure there is a NULL in the destination.  */
+            unicode_name[j] =    (UCHAR)0;
+            unicode_name[j + 1] =  (UCHAR)0;
+
+
+
+            /* Return successful completion.  */
+            return(FX_SUCCESS);
+        }
+        else
+        {
+
+            /* Determine if this is the correct unicode name.  */
+            if (unicode_search_length != local_unicode_name_length)
+            {
+                continue;
+            }
+
+            /* Compare the unicode search name with the requested unicode name.  */
+            for (j = 0; j < (local_unicode_name_length * 2); j = j + 2)
+            {
+
+                /* Compare bytes of each unicode name.  */
+                if (unicode_name[j] != _fx_unicode_search_name[j])
+                {
+
+                    /* Not match, Check if the character is in ASCII range.  */
+                    if ((_fx_unicode_search_name[j + 1] == 0) && (unicode_name[j + 1] == 0))
+                    {
+
+                        /* Check if it is case mismatch.  */
+                        if ((unicode_name[j]) >= 'a' && (unicode_name[j] <= 'z'))
+                        {
+                            if ((unicode_name[j] - 0x20) == _fx_unicode_search_name[j])
+                            {
+                                continue;
+                            }
+                        }
+                        if ((_fx_unicode_search_name[j]) >= 'a' && (_fx_unicode_search_name[j] <= 'z'))
+                        {
+                            if ((_fx_unicode_search_name[j] - 0x20) == unicode_name[j])
+                            {
+                                continue;
+                            }
+                        }
+                    }
+
+                    break;
+                }
+
+                /* Compare the next byte.  */
+                if (unicode_name[j + 1] != _fx_unicode_search_name[j + 1])
+                {
+                    break;
+                }
+            }
+
+            /* Determine if the names do not match.  */
+            if (j != (local_unicode_name_length * 2))
+            {
+                continue;
+            }
+
+            /* Otherwise, the names match, copy the short name into the destination.  */
+            /* Only the 1st 13 bytes or the buffer length is copied, whichever is smaller.  */
+            if (short_name_buffer_length > 13)
+            {
+                short_name_buffer_length = 13;
+            }
+            for (j = 0; j < short_name_buffer_length; j++)
+            {
+
+                /* Copy a character.  */
+                if (entry_ptr -> fx_dir_entry_short_name[0])
+                {
+                    short_name[j] =  (UCHAR)entry_ptr -> fx_dir_entry_short_name[j];
+                }
+                else
+                {
+                    short_name[j] =  (UCHAR)entry_ptr -> fx_dir_entry_name[j];
+                }
+            }
+
+            /* Return success to caller.  */
+            return(FX_SUCCESS);
+        }
+    } while (i < directory_size);
+
+    /* Return not found.  */
+    return(FX_NOT_FOUND);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_unicode_file_create.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_unicode_file_create.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_unicode_file_create.c	(revision 30)
@@ -0,0 +1,292 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Unicode                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_unicode.h"
+#include "fx_directory.h"
+#include "fx_file.h"
+#include "fx_utility.h"
+#ifdef FX_ENABLE_FAULT_TOLERANT
+#include "fx_fault_tolerant.h"
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_unicode_file_create                             PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function creates the specified unicode name.                   */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Pointer to media              */
+/*    source_unicode_name                   Pointer to source unicode name*/
+/*    source_unicode_length                 Unicode name length           */
+/*    short_name                            Designated short name         */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    Completion Status                                                   */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_search                  Search directory              */
+/*    _fx_unicode_directory_entry_change    Change unicode file name      */
+/*    _fx_unicode_directory_search          Search for unicode name       */
+/*    _fx_file_create                       Create a file                 */
+/*    _fx_fault_tolerant_transaction_start  Start fault tolerant          */
+/*                                            transaction                 */
+/*    _fx_fault_tolerant_transaction_end    End fault tolerant transaction*/
+/*    _fx_fault_tolerant_recover            Recover FAT chain             */
+/*    _fx_fault_tolerant_reset_log_file     Reset the log file            */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_unicode_file_create(FX_MEDIA *media_ptr, UCHAR *source_unicode_name, ULONG source_unicode_length, CHAR *short_name)
+{
+
+FX_DIR_ENTRY dir_entry;
+UINT         i, status;
+ULONG        temp_length;
+UCHAR        destination_shortname[13];
+
+
+    /* Setup pointer to media name buffer.  */
+    dir_entry.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
+
+    /* Clear the short name string.  */
+    dir_entry.fx_dir_entry_short_name[0] =  FX_NULL;
+
+    /* Set destination shortname to null.  */
+    destination_shortname[0] =  FX_NULL;
+
+    /* Clear the return short name.  */
+    short_name[0] =  FX_NULL;
+
+    /* Check the media to make sure it is open.  */
+    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
+    {
+
+        /* Return the media not opened error.  */
+        return(FX_MEDIA_NOT_OPEN);
+    }
+
+#ifdef FX_ENABLE_EXFAT
+    /* Check if media format is exFAT.  */
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+
+        /* Return the not implemented error.  */
+        return(FX_NOT_IMPLEMENTED);
+    }
+#endif
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_UNICODE_FILE_CREATE, media_ptr, source_unicode_name, source_unicode_length, short_name, FX_TRACE_FILE_EVENTS, 0, 0)
+
+    /* Protect media.  */
+    FX_PROTECT
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    /* Start transaction. */
+    _fx_fault_tolerant_transaction_start(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Check for write protect at the media level (set by driver).  */
+    if (media_ptr -> fx_media_driver_write_protect)
+    {
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return write protect error.  */
+        return(FX_WRITE_PROTECT);
+    }
+
+    /* Setup temporary length.  */
+    temp_length =  source_unicode_length;
+
+    /* Determine if the destination file is already present.  */
+    status =  _fx_unicode_directory_search(media_ptr, &dir_entry, destination_shortname, sizeof(destination_shortname), source_unicode_name, &temp_length, 0);
+
+    /* Determine if the search was successful.  */
+    if (status == FX_SUCCESS)
+    {
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the error code.  */
+        return(FX_ALREADY_CREATED);
+    }
+
+    /* Okay, at this point we need to create a new long file name that has enough space for the
+       eventual unicode file name.  */
+
+    /* Copy the characters from the unicode file name and make sure they are
+       within the ASCII range.  */
+    _fx_unicode_temp_long_file_name[0] =  'z';
+    for (i = 1; i < source_unicode_length; i++)
+    {
+
+        /* Build temporary long file name.  */
+        _fx_unicode_temp_long_file_name[i] =  (UCHAR)((UINT)'0' + (i % 9));
+    }
+    _fx_unicode_temp_long_file_name[i] =  FX_NULL;
+
+    /* Loop to try different temp long file names... if necessary.  */
+    do
+    {
+
+        /* Create a new file with the temp long file name.  */
+        status =  _fx_file_create(media_ptr, (CHAR *)_fx_unicode_temp_long_file_name);
+
+        /* Determine if there was an error.  */
+        if (status == FX_ALREADY_CREATED)
+        {
+
+            /* Adjust the name slightly and try again!  */
+            _fx_unicode_temp_long_file_name[0]--;
+
+            /* Determine if it is outside the lower case boundary.  */
+            if (_fx_unicode_temp_long_file_name[0] < 0x61)
+            {
+                break;
+            }
+        }
+    } while (status == FX_ALREADY_CREATED);
+
+    /* Determine if there was an error.  */
+    if (status)
+    {
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return error.  */
+        return(status);
+    }
+
+    /* Setup pointer to media name buffer.  */
+    dir_entry.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
+
+    /* Clear the short name string.  */
+    dir_entry.fx_dir_entry_short_name[0] =  0;
+
+    /* Search the system for the supplied file name.  */
+    status =  _fx_directory_search(media_ptr, (CHAR *)_fx_unicode_temp_long_file_name, &dir_entry, FX_NULL, FX_NULL);
+
+    /* Determine if the search was successful.  */
+    if (status != FX_SUCCESS)
+    {
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the error status.  */
+        return(status);
+    }
+
+    /* We can now change the temporary long file name with the destination unicode name.  */
+    status =  _fx_unicode_directory_entry_change(media_ptr, &dir_entry,  source_unicode_name, source_unicode_length);
+
+    /* Was this successful?  */
+    if (status == FX_SUCCESS)
+    {
+
+        /* Yes, copy the short file name to the destination.  */
+        /* The new short name only have 8 characters, since we didn't include a dot in temp_long_file_name. */
+        for (i = 0; i < FX_DIR_NAME_SIZE; i++)
+        {
+
+            /* Copy a character.  */
+            short_name[i] =  dir_entry.fx_dir_entry_short_name[i];
+
+            /* Are we done?  */
+            if (short_name[i] == FX_NULL)
+            {
+                break;
+            }
+        }
+    }
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    /* Check for a bad status.  */
+    if (status != FX_SUCCESS)
+    {
+
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the bad status.  */
+        return(status);
+    }
+
+    /* End transaction. */
+    status = _fx_fault_tolerant_transaction_end(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Release the protection.  */
+    FX_UNPROTECT
+
+    /* Return completion status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_unicode_file_rename.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_unicode_file_rename.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_unicode_file_rename.c	(revision 30)
@@ -0,0 +1,353 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Unicode                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_unicode.h"
+#include "fx_directory.h"
+#include "fx_file.h"
+#include "fx_utility.h"
+#ifdef FX_ENABLE_FAULT_TOLERANT
+#include "fx_fault_tolerant.h"
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_unicode_file_rename                             PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function first attempts to find the specified file.  If found, */
+/*    the rename request is valid and the directory entry will be changed */
+/*    to the new file name.  Otherwise, if the file is not found, the     */
+/*    appropriate error code is returned to the caller.                   */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Pointer to media              */
+/*    old_unicode_name                      Pointer to old unicode name   */
+/*    old_unicode_length                    Old unicode name length       */
+/*    new_unicode_name                      Pointer to new unicode name   */
+/*    new_unicode_length                    New unicode name length       */
+/*    new_short_name                        Designated new short name     */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    Completion Status                                                   */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_unicode_short_name_get            Get short name of unicode name*/
+/*    _fx_directory_search                  Search directory              */
+/*    _fx_unicode_directory_entry_change    Change unicode file name      */
+/*    _fx_unicode_directory_search          Search for unicode name       */
+/*    _fx_file_rename                       Rename for ASCII file name    */
+/*    _fx_fault_tolerant_transaction_start  Start fault tolerant          */
+/*                                            transaction                 */
+/*    _fx_fault_tolerant_transaction_end    End fault tolerant transaction*/
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT _fx_unicode_file_rename(FX_MEDIA *media_ptr, UCHAR *old_unicode_name, ULONG old_unicode_length,
+                             UCHAR *new_unicode_name, ULONG new_unicode_length, CHAR *new_short_name)
+{
+ULONG        i;
+UINT         status;
+CHAR         alpha, beta;
+CHAR         old_shortname[13];
+CHAR         new_shortname[13];
+FX_DIR_ENTRY dir_entry;
+
+
+    /* Clear the return short name.  */
+    new_short_name[0] =  FX_NULL;
+
+    /* Set shortname to null.  */
+    old_shortname[0] =  FX_NULL;
+    new_shortname[0] =  FX_NULL;
+
+    /* Check the media to make sure it is open.  */
+    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
+    {
+
+        /* Return the media not opened error.  */
+        return(FX_MEDIA_NOT_OPEN);
+    }
+
+#ifdef FX_ENABLE_EXFAT
+    /* Check if media format is exFAT.  */
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+
+        /* Return the not implemented error.  */
+        return(FX_NOT_IMPLEMENTED);
+    }
+#endif
+
+    /* Get shortname of old unicode name. */
+    status = _fx_unicode_short_name_get(media_ptr, old_unicode_name, old_unicode_length, old_shortname);
+
+    /* Determine if the result was successful.  */
+    if (status != FX_SUCCESS)
+    {
+
+        /* Return the error code.  */
+        return(status);
+    }
+
+    /* Protect media.  */
+    FX_PROTECT
+
+    /* Setup pointer to media name buffer.  */
+    dir_entry.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
+
+    /* Clear the short name string.  */
+    dir_entry.fx_dir_entry_short_name[0] =  FX_NULL;
+
+    /* Search the target directory for the same file name.  */
+    status = _fx_unicode_directory_search(media_ptr, &dir_entry, (UCHAR *)new_shortname, sizeof(new_shortname),
+                                          new_unicode_name, &new_unicode_length, 0);
+
+    /* Determine if the name already exists.  */
+    if (status == FX_SUCCESS)
+    {
+
+        if (old_unicode_length == new_unicode_length)
+        {
+
+            /* Determine if the new name simply has an ASCII case change. If so, simply let the processing
+               continue.  */
+            i =  0;
+            do
+            {
+
+                /* Pickup an old name and new name character and convert to upper case if necessary.  */
+                alpha = (CHAR)old_unicode_name[i << 1];
+                if ((alpha >= 'a') && (alpha <= 'z') && (old_unicode_name[(i << 1) + 1] == 0))
+                {
+
+                    /* Lower case, convert to upper case!  */
+                    alpha =  (CHAR)((INT)alpha - 0x20);
+                }
+                beta =   (CHAR)new_unicode_name[i << 1];
+                if ((beta >= 'a') && (beta <= 'z') && (new_unicode_name[(i << 1) + 1] == 0))
+                {
+
+                    /* Lower case, convert to upper case!  */
+                    beta =  (CHAR)((INT)beta - 0x20);
+                }
+
+                /* Now compare the characters.  */
+                if ((alpha != beta))
+                {
+
+                    /* Get out of this loop!  */
+                    break;
+                }
+
+                /* Pickup the high bytes. */
+                alpha = (CHAR)old_unicode_name[(i << 1) + 1];
+                beta =  (CHAR)new_unicode_name[(i << 1) + 1];
+
+                /* Now compare the byte.  */
+                if ((alpha != beta))
+                {
+
+                    /* Get out of this loop!  */
+                    break;
+                }
+
+                /* Move to next character.  */
+                i++;
+            } while (i < old_unicode_length);
+        }
+        else
+        {
+
+            /* Names not match. */
+            alpha = 0;
+            beta = 1;
+        }
+
+        /* Now determine if the names match.  */
+        if (alpha != beta)
+        {
+
+            /* No, the names do not match so simply return an error
+               to the caller.  */
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* Return the not a file error code.  */
+            return(FX_ALREADY_CREATED);
+        }
+    }
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    /* Start transaction. */
+    _fx_fault_tolerant_transaction_start(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Okay, at this point we need to rename to a new long file name that has enough space for the
+       eventual unicode file name.  */
+
+    /* Copy the characters from the unicode file name and make sure they are
+       within the ASCII range.  */
+    _fx_unicode_temp_long_file_name[0] =  'z';
+    for (i = 1; i < new_unicode_length; i++)
+    {
+
+        /* Build temporary long file name.  */
+        _fx_unicode_temp_long_file_name[i] =  (UCHAR)((UINT)'0' + (i % 9));
+    }
+    _fx_unicode_temp_long_file_name[i] =  FX_NULL;
+
+    /* Loop to try different temp long file names... if necessary.  */
+    do
+    {
+
+        /* Create a new file with the temp long file name.  */
+        status = _fx_file_rename(media_ptr, old_shortname, (CHAR *)_fx_unicode_temp_long_file_name);
+
+        /* Determine if there was an error.  */
+        if (status == FX_ALREADY_CREATED)
+        {
+
+            /* Adjust the name slightly and try again!  */
+            _fx_unicode_temp_long_file_name[0]--; 
+
+            /* Determine if it is outside the lower case boundary.  */
+            if (_fx_unicode_temp_long_file_name[0] < 0x61)
+            {
+                break;
+            }
+        }
+    } while (status == FX_ALREADY_CREATED);
+
+    /* Determine if there was an error.  */
+    if (status)
+    {
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return error.  */
+        return(status);
+    }
+
+    /* Setup pointer to media name buffer.  */
+    dir_entry.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
+
+    /* Clear the short name string.  */
+    dir_entry.fx_dir_entry_short_name[0] =  0;
+
+    /* Search the system for the supplied file name.  */
+    status =  _fx_directory_search(media_ptr, (CHAR *)_fx_unicode_temp_long_file_name, &dir_entry, FX_NULL, FX_NULL);
+
+    /* Determine if the search was successful.  */
+    if (status != FX_SUCCESS)
+    {
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the error status.  */
+        return(status);
+    }
+
+    /* We can now change the temporary long file name with the destination unicode name.  */
+    status =  _fx_unicode_directory_entry_change(media_ptr, &dir_entry,  new_unicode_name, new_unicode_length);
+
+    /* Was this successful?  */
+    if (status == FX_SUCCESS)
+    {
+
+        /* Yes, copy the short file name to the destination.  */
+        /* The new short name only have 8 characters, since we didn't include a dot in temp_long_file_name. */
+        for (i = 0; i < FX_DIR_NAME_SIZE; i++)
+        {
+
+            /* Copy a character.  */
+            new_short_name[i] =  dir_entry.fx_dir_entry_short_name[i];
+
+            /* Are we done?  */
+            if (new_short_name[i] == FX_NULL)
+            {
+                break;
+            }
+        }
+    }
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    /* Check for a bad status.  */
+    if (status != FX_SUCCESS)
+    {
+
+        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the bad status.  */
+        return(status);
+    }
+
+    /* End transaction. */
+    status = _fx_fault_tolerant_transaction_end(media_ptr);
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Release the protection.  */
+    FX_UNPROTECT
+
+    /* Return completion status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_unicode_length_get.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_unicode_length_get.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_unicode_length_get.c	(revision 30)
@@ -0,0 +1,81 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Unicode                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_unicode.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_unicode_length_get                              PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function returns the length of the supplied unicode name.      */
+/*                                                                        */
+/*    Note, this API is deprecated as _fx_unicode_length_get_extended     */
+/*    should be used. The maximum buffer size of unicode_name is 256.     */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    unicode_name                          Pointer to unicode name       */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    length                                                              */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_unicode_length_get_extended       Actual unicode length get     */
+/*                                            service                     */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+ULONG  _fx_unicode_length_get(UCHAR *unicode_name)
+{
+
+    /* Call the extended version with 256 bytes maximum buffer length.  */
+    return(_fx_unicode_length_get_extended(unicode_name, 256));
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_unicode_length_get_extended.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_unicode_length_get_extended.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_unicode_length_get_extended.c	(revision 30)
@@ -0,0 +1,103 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Unicode                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_unicode.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_unicode_length_get_extended                     PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function returns the length of the supplied unicode name.      */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    unicode_name                          Pointer to unicode name       */
+/*    buffer_length                         Buffer length for unicode name*/
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    length                                                              */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+ULONG  _fx_unicode_length_get_extended(UCHAR *unicode_name, UINT buffer_length)
+{
+
+ULONG i;
+ULONG length;
+
+
+    i =  0;
+    length =  0;
+    while (i < buffer_length)
+    {
+
+        /* See if we are at the end of the unicode string...  This assumes that there is a NULL at the end of the string.  */
+        if ((unicode_name[i] == 0) && (unicode_name[i + 1] == 0))
+        {
+            break;
+        }
+
+        /* Increment index.  */
+        i =  i + 2;
+
+        /* Increment the length.  */
+        length++;
+    }
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_UNICODE_LENGTH_GET, unicode_name, length, 0, 0, FX_TRACE_FILE_EVENTS, 0, 0)
+
+    /* Return length.  */
+    return(length);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_unicode_name_get.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_unicode_name_get.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_unicode_name_get.c	(revision 30)
@@ -0,0 +1,87 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Unicode                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_unicode.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_unicode_name_get                                PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function finds the unicode name associated with the supplied   */
+/*    short 8.3 name.                                                     */
+/*                                                                        */
+/*    Note, this API is deprecated as fx_unicode_name_get_extended should */
+/*    be used. The maximum written size to destination_unicode_name could */
+/*    be FX_MAX_LONG_NAME_LEN * 2.                                        */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Pointer to media              */
+/*    source_short_name                     Pointer to short file name    */
+/*    destination_unicode_name              Pointer to destination name   */
+/*    destination_unicode_length            Destination for name length   */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    Completion Status                                                   */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_unicode_name_get_extended         Actual unicode name get       */
+/*                                            service                     */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_unicode_name_get(FX_MEDIA *media_ptr, CHAR *source_short_name,
+                           UCHAR *destination_unicode_name, ULONG *destination_unicode_length)
+{
+
+    /* Call the extended version with 13 bytes short name length.  */
+    return(_fx_unicode_name_get_extended(media_ptr, source_short_name, destination_unicode_name, destination_unicode_length, FX_MAX_LONG_NAME_LEN * 2));
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_unicode_name_get_extended.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_unicode_name_get_extended.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_unicode_name_get_extended.c	(revision 30)
@@ -0,0 +1,145 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Unicode                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_unicode.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_unicode_name_get_extended                       PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function finds the unicode name associated with the supplied   */
+/*    short 8.3 name.                                                     */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Pointer to media              */
+/*    source_short_name                     Pointer to short file name    */
+/*    destination_unicode_name              Pointer to destination name   */
+/*    destination_unicode_length            Destination for name length   */
+/*    unicode_name_buffer_length            Buffer length of unicode name */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    Completion Status                                                   */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_unicode_directory_search          Search for unicode name       */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_unicode_name_get_extended(FX_MEDIA *media_ptr, CHAR *source_short_name,
+                           UCHAR *destination_unicode_name, ULONG *destination_unicode_length, ULONG unicode_name_buffer_length)
+{
+
+UINT                   status;
+FX_DIR_ENTRY           dir_entry;
+
+#ifdef TX_ENABLE_EVENT_TRACE
+TX_TRACE_BUFFER_ENTRY *trace_event;
+ULONG                  trace_timestamp;
+#endif
+
+
+    /* Setup pointer to media name buffer.  */
+    dir_entry.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
+
+    /* Clear the short name string.  */
+    dir_entry.fx_dir_entry_short_name[0] =  0;
+
+    /* Check the media to make sure it is open.  */
+    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
+    {
+
+        /* Return the media not opened error.  */
+        return(FX_MEDIA_NOT_OPEN);
+    }
+
+#ifdef FX_ENABLE_EXFAT
+    /* Check if media format is exFAT.  */
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+
+        /* Return the not implemented error.  */
+        return(FX_NOT_IMPLEMENTED);
+    }
+#endif
+
+    /* Set the destination unicode length to zero to indicate there is nothing in terms of a match.  */
+    *destination_unicode_length =  0;
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_UNICODE_NAME_GET, media_ptr, source_short_name, destination_unicode_name, 0, FX_TRACE_FILE_EVENTS, &trace_event, &trace_timestamp)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+    /* Search the system for the supplied short file name and return the unicode name if there is a match.  */
+    status =  _fx_unicode_directory_search(media_ptr, &dir_entry, (UCHAR *)source_short_name, 0, destination_unicode_name, destination_unicode_length, unicode_name_buffer_length);
+
+    /* Determine if the search was successful.  */
+    if (status != FX_SUCCESS)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the error code.  */
+        return(status);
+    }
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* Update the trace event with the unicode length.  */
+    FX_TRACE_EVENT_UPDATE(trace_event, trace_timestamp, FX_TRACE_UNICODE_NAME_GET, 0, 0, 0, *destination_unicode_length)
+
+    /* Return successful completion status.  */
+    return(FX_SUCCESS);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_unicode_short_name_get.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_unicode_short_name_get.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_unicode_short_name_get.c	(revision 30)
@@ -0,0 +1,87 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Unicode                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_unicode.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_unicode_short_name_get                          PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function finds the short name associated with the supplied     */
+/*    unicode name.                                                       */
+/*                                                                        */
+/*    Note, this API is deprecated as fx_unicode_short_name_get_extended  */
+/*    should be used. The maximum written size to destination_short_name  */
+/*    could be 13.                                                        */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Pointer to media              */
+/*    source_unicode_name                   Pointer to unicode name       */
+/*    source_unicode_length                 Length of unicode name        */
+/*    destination_short_name                Pointer to destination name   */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    Completion Status                                                   */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_unicode_short_name_get_extended   Actual unicode short name get */
+/*                                            service                     */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_unicode_short_name_get(FX_MEDIA *media_ptr, UCHAR *source_unicode_name, ULONG source_unicode_length,
+                                 CHAR *destination_short_name)
+{
+
+    /* Call the extended version with 13 bytes short name length.  */
+    return(_fx_unicode_short_name_get_extended(media_ptr, source_unicode_name, source_unicode_length, destination_short_name, 13));
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_unicode_short_name_get_extended.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_unicode_short_name_get_extended.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_unicode_short_name_get_extended.c	(revision 30)
@@ -0,0 +1,130 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Unicode                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_unicode.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_unicode_short_name_get_extended                 PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function finds the short name associated with the supplied     */
+/*    unicode name.                                                       */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Pointer to media              */
+/*    source_unicode_name                   Pointer to unicode name       */
+/*    source_unicode_length                 Length of unicode name        */
+/*    destination_short_name                Pointer to destination name   */
+/*    short_name_buffer_length              Buffer length of short name   */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    Completion Status                                                   */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_unicode_directory_search          Search for unicode name       */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_unicode_short_name_get_extended(FX_MEDIA *media_ptr, UCHAR *source_unicode_name, ULONG source_unicode_length,
+                                 CHAR *destination_short_name, ULONG short_name_buffer_length)
+{
+
+UINT         status;
+ULONG        temp_unicode_length;
+FX_DIR_ENTRY dir_entry;
+
+
+    /* Setup pointer to media name buffer.  */
+    dir_entry.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
+
+    /* Clear the short name string.  */
+    dir_entry.fx_dir_entry_short_name[0] =  0;
+
+    /* Check the media to make sure it is open.  */
+    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
+    {
+
+        /* Return the media not opened error.  */
+        return(FX_MEDIA_NOT_OPEN);
+    }
+
+#ifdef FX_ENABLE_EXFAT
+    /* Check if media format is exFAT.  */
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+
+        /* Return the not implemented error.  */
+        return(FX_NOT_IMPLEMENTED);
+    }
+#endif
+
+    /* Null terminate the short return name.  */
+    destination_short_name[0] =  (UCHAR)0;
+
+    /* Setup temporary unicode name length for search call.  */
+    temp_unicode_length =  source_unicode_length;
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_UNICODE_SHORT_NAME_GET, media_ptr, source_unicode_name, source_unicode_length, destination_short_name, FX_TRACE_FILE_EVENTS, 0, 0)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+    /* Search the system for the supplied short name and return the unicode name if there is a match.  */
+    status =  _fx_unicode_directory_search(media_ptr, &dir_entry, (UCHAR *)destination_short_name, short_name_buffer_length, source_unicode_name, &temp_unicode_length, 0);
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* Return successful completion status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_16_unsigned_read.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_16_unsigned_read.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_16_unsigned_read.c	(revision 30)
@@ -0,0 +1,85 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Utility                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_utility.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_utility_16_unsigned_read                        PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function reads (with endian awareness) 16-bit unsigned data    */
+/*    from the specified source and returns the value to the caller.      */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    source_ptr                            Source memory pointer         */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    UINT value                                                          */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    FileX System Functions                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_utility_16_unsigned_read(UCHAR *source_ptr)
+{
+
+UINT value;
+
+    /* Pickup the UINT from the destination with endian-awareness.  */
+    value =  ((((UINT)*(source_ptr + 1)) & 0xFF) << 8) |
+              ((UINT)*(source_ptr) & 0xFF);
+
+    /* Return value to caller.  */
+    return(value);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_16_unsigned_write.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_16_unsigned_write.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_16_unsigned_write.c	(revision 30)
@@ -0,0 +1,81 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Utility                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_utility.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_utility_16_unsigned_write                       PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function writes (with endian awareness) 16-bit unsigned data   */
+/*    to the specified destination.                                       */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    dest_ptr                              Destination memory pointer    */
+/*    value                                 Value to write to memory      */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    FileX System Functions                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+VOID  _fx_utility_16_unsigned_write(UCHAR *dest_ptr, UINT value)
+{
+
+    /* Store the UINT into the destination with endian-awareness.  */
+    *(dest_ptr) =       (UCHAR)(value & 0xFF);
+    *(dest_ptr + 1) =   (UCHAR)((value >> 8) & 0xFF);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_32_unsigned_read.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_32_unsigned_read.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_32_unsigned_read.c	(revision 30)
@@ -0,0 +1,87 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Utility                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_utility.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_utility_32_unsigned_read                        PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function reads (with endian awareness) a 32-bit unsigned data  */
+/*    from the specified source and returns the value to the caller.      */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    source_ptr                            Source memory pointer         */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    ULONG value                                                         */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    FileX System Functions                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+ULONG  _fx_utility_32_unsigned_read(UCHAR *source_ptr)
+{
+
+ULONG value;
+
+    /* Pickup the UINT from the destination with endian-awareness.  */
+    value =  ((((ULONG) *(source_ptr+3)) & 0xFF) << 24) |
+             ((((ULONG) *(source_ptr+2)) & 0xFF) << 16) |
+             ((((ULONG) *(source_ptr+1)) & 0xFF) << 8)  |
+              (((ULONG) *(source_ptr)) & 0xFF);
+
+    /* Return value to caller.  */
+    return(value);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_32_unsigned_write.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_32_unsigned_write.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_32_unsigned_write.c	(revision 30)
@@ -0,0 +1,83 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Utility                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_utility.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_utility_32_unsigned_write                       PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function writes (with endian awareness) a 32-bit unsigned data */
+/*    type to the specified destination.                                  */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    dest_ptr                              Destination memory pointer    */
+/*    value                                 Value to write to memory      */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    FileX System Functions                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+VOID  _fx_utility_32_unsigned_write(UCHAR *dest_ptr, ULONG value)
+{
+
+    /* Store the UINT into the destination with endian-awareness.  */
+    *(dest_ptr) =       (UCHAR)(value & 0xFF);
+    *(dest_ptr + 1) =   (UCHAR)((value >> 8) & 0xFF);
+    *(dest_ptr + 2) =   (UCHAR)((value >> 16) & 0xFF);
+    *(dest_ptr + 3) =   (UCHAR)((value >> 24) & 0xFF);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_64_unsigned_read.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_64_unsigned_read.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_64_unsigned_read.c	(revision 30)
@@ -0,0 +1,90 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Utility                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_utility.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_utility_64_unsigned_read                        PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function reads (with endian awareness) a 64-bit unsigned data  */
+/*    from the specified source and returns the value to the caller.      */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    source_ptr                            Source memory pointer         */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    ULONG64 value                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    FileX System Functions                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+ULONG64  _fx_utility_64_unsigned_read(UCHAR *source_ptr)
+{
+
+ULONG64 value;
+ULONG   upper_portion;
+ULONG   lower_portion;
+
+
+    lower_portion = _fx_utility_32_unsigned_read(source_ptr);
+    upper_portion = _fx_utility_32_unsigned_read(source_ptr + sizeof(ULONG));
+
+    value =  ((ULONG64)upper_portion) << 32;
+    value |= (ULONG64)lower_portion;
+
+    /* Return 64-bit value to caller.  */
+    return(value);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_64_unsigned_write.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_64_unsigned_write.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_64_unsigned_write.c	(revision 30)
@@ -0,0 +1,81 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Utility                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_utility.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_utility_64_unsigned_write                       PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function writes (with endian awareness) a 64-bit unsigned data */
+/*    type to the specified destination.                                  */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    dest_ptr                              Destination memory pointer    */
+/*    value                                 Value to write to memory      */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    FileX System Functions                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+VOID  _fx_utility_64_unsigned_write(UCHAR *dest_ptr, ULONG64 value)
+{
+
+    /* Store the ULONG64 into the destination with endian-awareness.  */
+    _fx_utility_32_unsigned_write(dest_ptr, (ULONG)value);
+    _fx_utility_32_unsigned_write(dest_ptr + sizeof(ULONG), (ULONG)(value >> 32));
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_FAT_entry_read.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_FAT_entry_read.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_FAT_entry_read.c	(revision 30)
@@ -0,0 +1,450 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Utility                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_utility.h"
+#ifdef FX_ENABLE_FAULT_TOLERANT
+#include "fx_fault_tolerant.h"
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_utility_FAT_entry_read                          PORTABLE C      */
+/*                                                           6.2.0        */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function reads the supplied FAT entry from the first FAT of    */
+/*    the media.  12-bit, 16-bit, and 32-bit FAT reading is supported.    */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    cluster                               Cluster entry number          */
+/*    entry_ptr                             Pointer to destination for    */
+/*                                            the FAT entry               */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_16_unsigned_read          Read a UINT from FAT buffer   */
+/*    _fx_utility_32_unsigned_read          Read a ULONG form FAT buffer  */
+/*    _fx_utility_FAT_flush                 Flush FAT entry cache         */
+/*    _fx_utility_logical_sector_read       Read FAT sector into memory   */
+/*    _fx_fault_tolerant_read_FAT           Read FAT entry from log file  */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    FileX System Functions                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s), and      */
+/*                                            added conditional to        */
+/*                                            disable fat entry refresh,  */
+/*                                            resulting in version 6.1    */
+/*  10-31-2022     Tiejun Zhou              Modified comment(s), and      */
+/*                                            fixed compiler warning,     */
+/*                                            resulting in version 6.2.0  */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_utility_FAT_entry_read(FX_MEDIA *media_ptr, ULONG cluster, ULONG *entry_ptr)
+{
+
+ULONG               FAT_sector;
+ULONG               byte_offset, entry32;
+UCHAR              *FAT_ptr;
+UINT                entry, index;
+UINT                status;
+FX_FAT_CACHE_ENTRY *cache_entry_ptr;
+#ifndef FX_DISABLE_FAT_ENTRY_REFRESH
+FX_FAT_CACHE_ENTRY  temp_cache_entry;
+#endif /* FX_DISABLE_FAT_ENTRY_REFRESH */
+
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    if (media_ptr -> fx_media_fault_tolerant_enabled &&
+        (media_ptr -> fx_media_fault_tolerant_state & FX_FAULT_TOLERANT_STATE_STARTED))
+    {
+
+        /* Redirect this request to log file. */
+        status = _fx_fault_tolerant_read_FAT(media_ptr, cluster, entry_ptr, FX_FAULT_TOLERANT_FAT_LOG_TYPE);
+
+        /* Return on success. */
+        if (status != FX_READ_CONTINUE)
+        {
+            return(status);
+        }
+    }
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+    /* Increment the number of FAT entry reads and cache hits.  */
+    media_ptr -> fx_media_fat_entry_reads++;
+    media_ptr -> fx_media_fat_entry_cache_read_hits++;
+#endif
+
+    /* Extended port-specific processing macro, which is by default defined to white space.  */
+    FX_UTILITY_FAT_ENTRY_READ_EXTENSION
+
+    /* Calculate the area of the cache for this FAT entry.  */
+    index =  (cluster & FX_FAT_CACHE_HASH_MASK) * FX_FAT_CACHE_DEPTH;
+
+    /* Build a pointer to the cache entry.  */
+    cache_entry_ptr =  &media_ptr -> fx_media_fat_cache[index];
+
+#ifndef FX_DISABLE_FAT_ENTRY_REFRESH
+    /* Determine if the FAT entry is in the cache - assuming the depth of the FAT cache is
+       4 entries.  */
+    if ((cache_entry_ptr -> fx_fat_cache_entry_cluster) == cluster)
+    {
+
+        /* Yes, return the cached value.  */
+        *entry_ptr =  cache_entry_ptr -> fx_fat_cache_entry_value;
+
+        /* Don't move anything since we found the entry.  */
+
+        /* Return a successful status.  */
+        return(FX_SUCCESS);
+    }
+    else if (((cache_entry_ptr + 1) -> fx_fat_cache_entry_cluster) == cluster)
+    {
+
+        /* Yes, return the cached value.  */
+        *entry_ptr =  (cache_entry_ptr + 1) -> fx_fat_cache_entry_value;
+
+        /* Just swap the first and second entry.  */
+        temp_cache_entry =        *(cache_entry_ptr);
+        *(cache_entry_ptr) =      *(cache_entry_ptr + 1);
+        *(cache_entry_ptr + 1) =  temp_cache_entry;
+
+        /* Return a successful status.  */
+        return(FX_SUCCESS);
+    }
+    else if (((cache_entry_ptr + 2) -> fx_fat_cache_entry_cluster) == cluster)
+    {
+
+        /* Yes, return the cached value.  */
+        *entry_ptr =  (cache_entry_ptr + 2) -> fx_fat_cache_entry_value;
+
+        /* Move the third entry to the top and the first two entries down.  */
+        temp_cache_entry =        *(cache_entry_ptr);
+        *(cache_entry_ptr) =      *(cache_entry_ptr + 2);
+        *(cache_entry_ptr + 2) =  *(cache_entry_ptr + 1);
+        *(cache_entry_ptr + 1) =  temp_cache_entry;
+
+        /* Return a successful status.  */
+        return(FX_SUCCESS);
+    }
+    else if (((cache_entry_ptr + 3) -> fx_fat_cache_entry_cluster) == cluster)
+    {
+
+        /* Yes, return the cached value.  */
+        *entry_ptr =  (cache_entry_ptr + 3) -> fx_fat_cache_entry_value;
+
+        /* Move the last entry to the top and the first three entries down.  */
+        temp_cache_entry =        *(cache_entry_ptr);
+        *(cache_entry_ptr) =      *(cache_entry_ptr + 3);
+        *(cache_entry_ptr + 3) =  *(cache_entry_ptr + 2);
+        *(cache_entry_ptr + 2) =  *(cache_entry_ptr + 1);
+        *(cache_entry_ptr + 1) =  temp_cache_entry;
+
+        /* Return a successful status.  */
+        return(FX_SUCCESS);
+    }
+#else
+    for (UINT i = 0; i < 4; i++)
+    {
+        if (((cache_entry_ptr + i) -> fx_fat_cache_entry_cluster) == cluster)
+        {
+            *entry_ptr =  (cache_entry_ptr + i) -> fx_fat_cache_entry_value;
+
+            /* Return a successful status.  */
+            return(FX_SUCCESS);
+        }
+    }
+#endif /* FX_DISABLE_FAT_ENTRY_REFRESH */
+
+    /* Determine if the oldest entry was modified, i.e. whether or not it is
+       dirty.  */
+    if (media_ptr -> fx_media_fat_cache[index + 3].fx_fat_cache_entry_dirty)
+    {
+
+        /* Yes, the entry is dirty and needs to be flushed out.  */
+        status = _fx_utility_FAT_flush(media_ptr);
+
+        /* Check for completion status.  */
+        if (status != FX_SUCCESS)
+        {
+
+            /* Return error status.  */
+            return(status);
+        }
+    }
+
+    /* If we get here, the entry was not found in the FAT entry cache.  We need to
+       actually read the FAT entry.  */
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Decrement the number of cache hits.  */
+    media_ptr -> fx_media_fat_entry_cache_read_hits--;
+
+    /* Increment the number of cache misses.  */
+    media_ptr -> fx_media_fat_entry_cache_read_misses++;
+#endif
+
+    /* Determine which type of FAT is present.  */
+    if (media_ptr -> fx_media_12_bit_FAT)
+    {
+
+        /* Calculate the byte offset to the cluster entry.  */
+        byte_offset =  (((ULONG)cluster << 1) + cluster) >> 1;
+
+        /* Calculate the FAT sector the requested FAT entry resides in.  */
+        FAT_sector =  (byte_offset / media_ptr -> fx_media_bytes_per_sector) +
+            (ULONG)media_ptr -> fx_media_reserved_sectors;
+
+        /* Read the sector in.  */
+        status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) FAT_sector,
+                                                  media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_FAT_SECTOR);
+
+        /* Determine if an error occurred.  */
+        if (status != FX_SUCCESS)
+        {
+            /* Return the error status.  */
+            return(status);
+        }
+
+        /* Now calculate the byte offset into this FAT sector.  */
+        byte_offset =  byte_offset -
+            ((FAT_sector - (ULONG)media_ptr -> fx_media_reserved_sectors) *
+             media_ptr -> fx_media_bytes_per_sector);
+
+        /* Setup a pointer into the buffer.  */
+        FAT_ptr =  (UCHAR *)media_ptr -> fx_media_memory_buffer + (UINT)byte_offset;
+
+        /* Determine if the cluster entry is odd or even.  */
+        if (cluster & 1)
+        {
+
+            /* Odd cluster number.  */
+
+            /* Pickup the lower nibble of the FAT entry.  */
+            entry =  (((UINT)*FAT_ptr) & 0xF0) >> 4;
+
+            /* Move to the next byte of the FAT entry.  */
+            FAT_ptr++;
+
+            /* Determine if we are now past the end of the FAT buffer in memory.  */
+            if (byte_offset == (ULONG)(media_ptr -> fx_media_bytes_per_sector - 1))
+            {
+
+                /* Yes, we need to read the next sector.  */
+                FAT_sector++;
+                status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) FAT_sector,
+                                                          media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_FAT_SECTOR);
+
+                /* Determine if an error occurred.  */
+                if (status != FX_SUCCESS)
+                {
+
+                    /* Return the error status.  */
+                    return(status);
+                }
+
+                /* Setup a pointer into the buffer.  */
+                FAT_ptr =  (UCHAR *)media_ptr -> fx_media_memory_buffer;
+            }
+
+            /* Pickup the upper 8 bits of the FAT entry.  */
+            entry =  entry | (((UINT)*FAT_ptr) << 4);
+        }
+        else
+        {
+
+            /* Even cluster number.  */
+
+            /* Pickup the lower byte of the FAT entry.  */
+            entry =  (UINT)(((UINT)*FAT_ptr) & 0xFF);
+
+            /* Move to the next nibble of the FAT entry.  */
+            FAT_ptr++;
+
+            /* Determine if we are now past the end of the FAT buffer in memory.  */
+            if (byte_offset == (ULONG)(media_ptr -> fx_media_bytes_per_sector - 1))
+            {
+
+                /* Yes, we need to read the next sector.  */
+                FAT_sector++;
+                status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) FAT_sector,
+                                                          media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_FAT_SECTOR);
+
+                /* Determine if an error occurred.  */
+                if (status != FX_SUCCESS)
+                {
+                    return(status);
+                }
+
+                /* Setup a pointer into the buffer.  */
+                FAT_ptr =  (UCHAR *)media_ptr -> fx_media_memory_buffer;
+            }
+
+            /* Pickup the upper 4 bits of the FAT entry.  */
+            entry =  entry | ((((UINT)*FAT_ptr) & 0x0F) << 8);
+        }
+
+        /* Determine if we need to do sign extension on the 12-bit eof value.  */
+        if (entry >= FX_MAX_12BIT_CLUST)
+        {
+
+            /* Yes, we need to sign extend.  */
+            entry =  entry | FX_SIGN_EXTEND;
+        }
+
+        *entry_ptr =  entry;
+    }
+
+    /* Check for a 16-bit FAT.  */
+#ifdef FX_ENABLE_EXFAT
+    else if (FX_FAT16  == media_ptr -> fx_media_FAT_type)
+#else
+    else if (!media_ptr -> fx_media_32_bit_FAT)
+#endif /* FX_ENABLE_EXFAT */
+    {
+
+        /* 16-bit FAT is present.  */
+
+        /* Calculate the byte offset to the cluster entry.  */
+        byte_offset =  (((ULONG)cluster) * 2);
+
+        /* Calculate the FAT sector the requested FAT entry resides in.  */
+        FAT_sector =  (byte_offset / media_ptr -> fx_media_bytes_per_sector) +
+            (ULONG)media_ptr -> fx_media_reserved_sectors;
+
+        /* Read the FAT sector.  */
+        status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) FAT_sector,
+                                                  media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_FAT_SECTOR);
+
+        /* Determine if an error occurred.  */
+        if (status != FX_SUCCESS)
+        {
+
+            /* Return the error code.  */
+            return(status);
+        }
+
+        /* Now calculate the byte offset into this FAT sector.  */
+        byte_offset =  byte_offset -
+            ((FAT_sector - (ULONG)media_ptr -> fx_media_reserved_sectors) *
+             media_ptr -> fx_media_bytes_per_sector);
+
+        /* Setup a pointer into the buffer.  */
+        FAT_ptr =  (UCHAR *)media_ptr -> fx_media_memory_buffer + (UINT)byte_offset;
+
+        /* Pickup the FAT entry.  */
+        entry =  _fx_utility_16_unsigned_read(FAT_ptr);
+
+        *entry_ptr =  entry;
+    }
+#ifdef FX_ENABLE_EXFAT
+    else if ((media_ptr -> fx_media_FAT_type == FX_FAT32) ||
+             (media_ptr -> fx_media_FAT_type == FX_exFAT))
+#else
+    else
+#endif /* FX_ENABLE_EXFAT */
+    {
+
+        /* Otherwise, a 32 bit FAT present.  */
+        byte_offset =  (((ULONG)cluster) * 4);
+
+        /* Calculate the FAT sector the requested FAT entry resides in.  */
+        FAT_sector =  (byte_offset / media_ptr -> fx_media_bytes_per_sector) +
+            (ULONG)media_ptr -> fx_media_reserved_sectors;
+
+        /* Calculate the byte offset to the FAT entry.  */
+        byte_offset = (byte_offset % media_ptr -> fx_media_bytes_per_sector);
+
+        /* Read the appropriate FAT sector.  */
+        status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) FAT_sector,
+                                                  media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_FAT_SECTOR);
+
+        /* Determine if an error occurred.  */
+        if (status != FX_SUCCESS)
+        {
+
+            /* Return the error code.  */
+            return(status);
+        }
+
+        /* Setup a pointer into the buffer.  */
+        FAT_ptr =  (UCHAR *)media_ptr -> fx_media_memory_buffer + (ULONG)byte_offset;
+
+        /* Pickup the FAT entry.  */
+        entry32 =  _fx_utility_32_unsigned_read(FAT_ptr);
+
+#ifdef FX_ENABLE_EXFAT
+        /* FAT32 uses 28 bit cluster addressing but  exFAT uses 32 bit.  */
+        if (media_ptr -> fx_media_FAT_type == FX_FAT32)
+        {
+#endif /* FX_ENABLE_EXFAT */
+
+            /* Clear upper nibble.  */
+            entry32 = entry32 & 0x0FFFFFFF;
+#ifdef FX_ENABLE_EXFAT
+        }
+#endif /* FX_ENABLE_EXFAT */
+
+        *entry_ptr =  entry32;
+    }
+
+    /* Move all the cache entries down so the oldest is at the bottom.  */
+    *(cache_entry_ptr + 3) =  *(cache_entry_ptr + 2);
+    *(cache_entry_ptr + 2) =  *(cache_entry_ptr + 1);
+    *(cache_entry_ptr + 1) =  *(cache_entry_ptr);
+
+    /* Setup the new FAT entry in the cache.  */
+    cache_entry_ptr -> fx_fat_cache_entry_cluster =  cluster;
+    cache_entry_ptr -> fx_fat_cache_entry_value   =  *entry_ptr;
+
+    /* Return success to the caller.  */
+    return(FX_SUCCESS);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_FAT_entry_write.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_FAT_entry_write.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_FAT_entry_write.c	(revision 30)
@@ -0,0 +1,265 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Utility                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_utility.h"
+#ifdef FX_ENABLE_FAULT_TOLERANT
+#include "fx_fault_tolerant.h"
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_utility_FAT_entry_write                         PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function writes to the supplied FAT entry to all FATs in       */
+/*    the media.  12-bit, 16-bit, and 32-bit FAT writing is supported.    */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    cluster                               Cluster entry number          */
+/*    next_cluster                          Next cluster integer pointer  */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_FAT_flush                 FLUSH dirty entries in the    */
+/*                                            FAT cache                   */
+/*    _fx_fault_tolerant_add_fat_log        Add FAT redo log              */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    FileX System Functions                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_utility_FAT_entry_write(FX_MEDIA *media_ptr, ULONG cluster, ULONG next_cluster)
+{
+
+UINT                status, index, i;
+FX_FAT_CACHE_ENTRY *cache_entry_ptr;
+#ifdef FX_ENABLE_FAULT_TOLERANT
+ULONG               FAT_sector;
+
+    /* While fault_tolerant is enabled, only FAT entries in the same sector are allowed to be cached. */
+    /* We must flush FAT sectors in the order of FAT chains. */
+    if (media_ptr -> fx_media_fault_tolerant_enabled &&
+        (media_ptr -> fx_media_fault_tolerant_state & FX_FAULT_TOLERANT_STATE_STARTED))
+    {
+
+        if (!(media_ptr -> fx_media_fault_tolerant_state & FX_FAULT_TOLERANT_STATE_SET_FAT_CHAIN))
+        {
+
+            /* Redirect this request to log file. */
+            return(_fx_fault_tolerant_add_FAT_log(media_ptr, cluster, next_cluster));
+        }
+
+        /* Get sector number of the incoming FAT entry. */
+        FAT_sector = _fx_utility_FAT_sector_get(media_ptr, cluster);
+
+        /* Is FAT sector changed? */
+        if (FAT_sector != media_ptr -> fx_media_fault_tolerant_cached_FAT_sector)
+        {
+
+            /* Are there any cached FAT entries? */
+            if (media_ptr -> fx_media_fault_tolerant_cached_FAT_sector)
+            {
+
+                /* Current FAT entry is located in different sector. Force flush. */
+                /* Flush the cached individual FAT entries */
+                _fx_utility_FAT_flush(media_ptr);
+
+#ifdef FX_ENABLE_EXFAT
+                if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+                {
+
+                    /* Flush exFAT bitmap.  */
+                    _fx_utility_exFAT_bitmap_flush(media_ptr);
+                }
+#endif /* FX_ENABLE_EXFAT */
+            }
+
+            /* Record sector number of current FAT entry. */
+            media_ptr -> fx_media_fault_tolerant_cached_FAT_sector = FAT_sector;
+        }
+    }
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+    /* Increment the number of FAT entry writes and cache hits.  */
+    media_ptr -> fx_media_fat_entry_writes++;
+    media_ptr -> fx_media_fat_entry_cache_write_hits++;
+#endif
+
+    /* Extended port-specific processing macro, which is by default defined to white space.  */
+    FX_UTILITY_FAT_ENTRY_WRITE_EXTENSION
+
+    /* Calculate the area of the cache for this FAT entry.  */
+    index =  (cluster & FX_FAT_CACHE_HASH_MASK) * FX_FAT_CACHE_DEPTH;
+
+    /* Build a pointer to the cache entry.  */
+    cache_entry_ptr =  &media_ptr -> fx_media_fat_cache[index];
+
+    /* First search for the entry in the FAT entry cache.  */
+    for (i = 0; i < FX_FAT_CACHE_DEPTH; i++)
+    {
+
+        /* See if the entry matches the write request.  */
+        if (((cache_entry_ptr + i) -> fx_fat_cache_entry_cluster) == cluster)
+        {
+
+            /* Yes, we have a matching entry.  Save the new information in the FAT
+               cache and mark this entry as dirty.  */
+            (cache_entry_ptr + i) -> fx_fat_cache_entry_value =     next_cluster;
+            (cache_entry_ptr + i) -> fx_fat_cache_entry_dirty =     1;
+
+            /* Determine if the driver has requested notification when data sectors in the media
+               become free.  This can be useful to FLASH manager software.  */
+            if ((media_ptr -> fx_media_driver_free_sector_update) && (next_cluster == FX_FREE_CLUSTER))
+            {
+
+                /* Yes, the driver does wish to know that these specific sector(s) are
+                   not in use.  */
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+                /* Increment the number of driver release sectors requests.  */
+                media_ptr -> fx_media_driver_release_sectors_requests++;
+#endif
+
+                /* This cluster is being released so inform the driver that the
+                   corresponding sectors are now available.  */
+                media_ptr -> fx_media_driver_request =          FX_DRIVER_RELEASE_SECTORS;
+                media_ptr -> fx_media_driver_status =           FX_IO_ERROR;
+                media_ptr -> fx_media_driver_logical_sector =   (media_ptr -> fx_media_data_sector_start +
+                                                                 ((cluster - FX_FAT_ENTRY_START) * media_ptr -> fx_media_sectors_per_cluster));
+                media_ptr -> fx_media_driver_sectors =          media_ptr -> fx_media_sectors_per_cluster;
+
+                /* If trace is enabled, insert this event into the trace buffer.  */
+                FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_RELEASE_SECTORS, media_ptr, media_ptr -> fx_media_driver_logical_sector, media_ptr -> fx_media_driver_sectors, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+                /* Call the driver.  */
+                (media_ptr -> fx_media_driver_entry)(media_ptr);
+            }
+
+            /* Done, return successful status.  */
+            return(FX_SUCCESS);
+        }
+    }
+
+    /* If we reach this point, we know that the FAT write request is not in
+       the cache.  */
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+    /* Decrement the number of cache hits.  */
+    media_ptr -> fx_media_fat_entry_cache_write_hits--;
+
+    /* Increment the number of cache misses.  */
+    media_ptr -> fx_media_fat_entry_cache_write_misses++;
+#endif
+
+    /* Determine if the oldest entry is dirty and needs to be flushed.  */
+    if (media_ptr -> fx_media_fat_cache[index + 3].fx_fat_cache_entry_dirty == 1)
+    {
+
+        /* Flush the dirty entry so it can be used to hold the current
+           FAT entry write request.  */
+        status = _fx_utility_FAT_flush(media_ptr);
+
+        /* Determine if the write was successful.  */
+        if (status != FX_SUCCESS)
+        {
+
+            /* No, return error status to caller.  */
+            return(status);
+        }
+
+    }
+
+    /* Move all the cache entries down so the oldest is at the bottom.  */
+    *(cache_entry_ptr + 3) =  *(cache_entry_ptr + 2);
+    *(cache_entry_ptr + 2) =  *(cache_entry_ptr + 1);
+    *(cache_entry_ptr + 1) =  *(cache_entry_ptr);
+
+    /* Save the current FAT entry write request and mark as dirty.  */
+    cache_entry_ptr -> fx_fat_cache_entry_dirty =    1;
+    cache_entry_ptr -> fx_fat_cache_entry_cluster =  cluster;
+    cache_entry_ptr -> fx_fat_cache_entry_value =    next_cluster;
+
+    /* Determine if the driver has requested notification when data sectors in the media
+       become free.  This can be useful to FLASH manager software.  */
+    if ((media_ptr -> fx_media_driver_free_sector_update) && (next_cluster == FX_FREE_CLUSTER))
+    {
+
+        /* Yes, the driver does wish to know that these specific sector(s) are
+           not in use.  */
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+        /* Increment the number of driver release sectors requests.  */
+        media_ptr -> fx_media_driver_release_sectors_requests++;
+#endif
+
+        /* This cluster is being released so inform the driver that the
+              corresponding sectors are now available.  */
+        media_ptr -> fx_media_driver_request =          FX_DRIVER_RELEASE_SECTORS;
+        media_ptr -> fx_media_driver_status =           FX_IO_ERROR;
+        media_ptr -> fx_media_driver_logical_sector =   (media_ptr -> fx_media_data_sector_start +
+                                                         ((cluster - FX_FAT_ENTRY_START) * media_ptr -> fx_media_sectors_per_cluster));
+        media_ptr -> fx_media_driver_sectors =          media_ptr -> fx_media_sectors_per_cluster;
+
+        /* If trace is enabled, insert this event into the trace buffer.  */
+        FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_RELEASE_SECTORS, media_ptr, media_ptr -> fx_media_driver_logical_sector, media_ptr -> fx_media_driver_sectors, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+        /* Call the driver.  */
+        (media_ptr -> fx_media_driver_entry)(media_ptr);
+    }
+
+    /* Return success to caller.  */
+    return(FX_SUCCESS);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_FAT_flush.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_FAT_flush.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_FAT_flush.c	(revision 30)
@@ -0,0 +1,564 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Utility                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_utility.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_utility_FAT_flush                               PORTABLE C      */
+/*                                                           6.1.2        */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function flushes the contents of the FAT cache to the media.   */
+/*    12-bit, 16-bit and 32-bit FAT writing is supported.                 */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_16_unsigned_write         Write a UINT into buffer      */
+/*    _fx_utility_32_unsigned_read          Read a ULONG from buffer      */
+/*    _fx_utility_32_unsigned_write         Write a ULONG into buffer     */
+/*    _fx_utility_logical_sector_read       Read FAT sector into memory   */
+/*    _fx_utility_logical_sector_write      Write FAT sector back to disk */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    FileX System Functions                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*  11-09-2020     William E. Lamie         Modified comment(s),          */
+/*                                            updated logic for           */
+/*                                            FAT secondary update map,   */
+/*                                            resulting in version 6.1.2  */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_utility_FAT_flush(FX_MEDIA *media_ptr)
+{
+
+ULONG  FAT_sector;
+ULONG  byte_offset;
+UCHAR *FAT_ptr;
+UINT   temp, i;
+UINT   status, index, ind;
+ULONG  cluster, next_cluster;
+UCHAR  sectors_per_bit;
+INT    multi_sector_entry;
+ULONG  sector;
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+    /* Increment the number of cache flush requests.  */
+    media_ptr -> fx_media_fat_cache_flushes++;
+#endif
+
+    /* Loop through the media's FAT cache and flush out dirty entries.  */
+    for (index = 0; index < FX_MAX_FAT_CACHE; index++)
+    {
+
+        /* Determine if the entry is dirty.  */
+        if ((media_ptr -> fx_media_fat_cache[index].fx_fat_cache_entry_dirty) == 0)
+        {
+
+            /* No, just advance to the next entry.  */
+            continue;
+        }
+
+        /* Otherwise, the entry is indeed dirty and must be flushed out.  Process
+           relative to the type of FAT that is being used.  */
+
+        /* Pickup the contents of the FAT cache entry.  */
+        cluster =       media_ptr -> fx_media_fat_cache[index].fx_fat_cache_entry_cluster;
+
+        /* Determine which type of FAT is present.  */
+#ifdef FX_ENABLE_EXFAT
+        if (media_ptr -> fx_media_FAT_type == FX_FAT12)
+#else
+        if (media_ptr -> fx_media_12_bit_FAT)
+#endif /* FX_ENABLE_EXFAT */
+        {
+
+            /* Calculate the byte offset to the cluster entry.  */
+            byte_offset =  (((ULONG)cluster << 1) + cluster) >> 1;
+
+            /* Calculate the FAT sector the requested FAT entry resides in.  */
+            FAT_sector =  (byte_offset / media_ptr -> fx_media_bytes_per_sector) +
+                (ULONG)media_ptr -> fx_media_reserved_sectors;
+
+            /* Initialize as not written.  */
+            multi_sector_entry = -1;
+
+            for (;;)
+            {
+
+                /* Pickup the FAT sector.  */
+                status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) FAT_sector,
+                                                          media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_FAT_SECTOR);
+
+                /* Determine if an error occurred.  */
+                if (status != FX_SUCCESS)
+                {
+
+                    /* Return the error status.  */
+                    return(status);
+                }
+
+                /* Determine if a mulit-sector FAT update is present.  */
+                if (multi_sector_entry != -1)
+                {
+
+                    /* Yes, store the remaining portion of the new FAT entry in the
+                       next FAT sector.  */
+
+                    /* Setup a pointer into the buffer.  */
+                    FAT_ptr =  (UCHAR *)media_ptr -> fx_media_memory_buffer;
+
+                    /* Pickup the cluster and next cluster.  */
+                    cluster = (media_ptr -> fx_media_fat_cache[multi_sector_entry].fx_fat_cache_entry_cluster);
+                    next_cluster = media_ptr -> fx_media_fat_cache[multi_sector_entry].fx_fat_cache_entry_value;
+
+                    /* Determine if the cluster entry is odd or even.  */
+                    if (cluster & 1)
+                    {
+
+                        /* Store the upper 8 bits of the FAT entry.  */
+                        *FAT_ptr =  (UCHAR)((next_cluster >> 4) & 0xFF);
+                    }
+                    else
+                    {
+
+                        /* Store the upper 4 bits of the FAT entry.  */
+                        temp =  ((UINT)*FAT_ptr) & 0xF0;
+                        *FAT_ptr =  (UCHAR)(temp | ((next_cluster >> 8) & 0xF));
+                    }
+
+                    /* Clear the multi-sector flag.  */
+                    multi_sector_entry = -1;
+                }
+
+                /* Loop through the remainder of the cache to check for multiple entries
+                   within the same FAT sector being written out.  */
+                for (i = index; i < FX_MAX_FAT_CACHE; i++)
+                {
+
+                    /* Is the cache entry dirty?  */
+                    if ((media_ptr -> fx_media_fat_cache[i].fx_fat_cache_entry_dirty) == 0)
+                    {
+
+                        /* Not dirty, does not need to be flushed.  */
+                        continue;
+                    }
+
+                    /* Isolate the cluster.  */
+                    cluster = (media_ptr -> fx_media_fat_cache[i].fx_fat_cache_entry_cluster);
+
+                    /* Calculate the byte offset to the cluster entry.  */
+                    byte_offset =  (((ULONG)cluster << 1) + cluster) >> 1;
+
+                    /* Pickup the sector.  */
+                    sector =  (byte_offset / media_ptr -> fx_media_bytes_per_sector) +
+                        (ULONG)media_ptr -> fx_media_reserved_sectors;
+
+                    /* Is it the current FAT sector?  */
+                    if (sector != FAT_sector)
+                    {
+
+                        /* Different FAT sector - not in this pass of the loop.  */
+                        continue;
+                    }
+
+                    /* Pickup new value for this FAT entry.  */
+                    next_cluster =  media_ptr -> fx_media_fat_cache[i].fx_fat_cache_entry_value;
+
+                    /* Now calculate the byte offset into this FAT sector.  */
+                    byte_offset =  byte_offset -
+                        ((FAT_sector - (ULONG)media_ptr -> fx_media_reserved_sectors) *
+                         media_ptr -> fx_media_bytes_per_sector);
+
+                    /* Determine if we are now past the end of the FAT buffer in memory.  */
+                    if (byte_offset == (ULONG)(media_ptr -> fx_media_bytes_per_sector - 1))
+                    {
+
+                        /* Yes, we need to read the next sector */
+                        multi_sector_entry = (INT)i;
+                    }
+
+                    /* Setup a pointer into the buffer.  */
+                    FAT_ptr =  (UCHAR *)media_ptr -> fx_media_memory_buffer + (UINT)byte_offset;
+
+                    /* Clear the dirty flag.  */
+                    media_ptr -> fx_media_fat_cache[i].fx_fat_cache_entry_dirty = 0;
+
+                    /* Determine if the cluster entry is odd or even.  */
+                    if (cluster & 1)
+                    {
+
+                        /* Odd cluster number.  */
+
+                        /* Pickup the upper nibble of the FAT entry.  */
+
+                        /* First, set the lower nibble of the FAT entry.  */
+                        temp =      (((UINT)*FAT_ptr) & 0x0F);
+                        *FAT_ptr =  (UCHAR)(temp | ((next_cluster << 4) & 0xF0));
+
+                        /* Determine if this is a mulit-sector entry.  */
+                        if ((multi_sector_entry) == (INT)i)
+                        {
+
+                            /* Yes, requires multiple sector - will write rest of the part later.  */
+                            continue;
+                        }
+
+                        /* Move to the next byte of the FAT entry.  */
+                        FAT_ptr++;
+
+                        /* Store the upper 8 bits of the FAT entry.  */
+                        *FAT_ptr =  (UCHAR)((next_cluster >> 4) & 0xFF);
+                    }
+                    else
+                    {
+
+                        /* Even cluster number.  */
+
+                        /* Store the lower byte of the FAT entry.  */
+                        *FAT_ptr =  (UCHAR)(next_cluster & 0xFF);
+
+                        /* Determine if this is a mulit-sector entry.  */
+                        if ((multi_sector_entry) == (INT)i)
+                        {
+
+                            /* Yes, requires multiple sector - will write rest of the part later.  */
+                            continue;
+                        }
+
+                        /* Move to the next nibble of the FAT entry.  */
+                        FAT_ptr++;
+
+                        /* Store the upper 4 bits of the FAT entry.  */
+                        temp =  ((UINT)*FAT_ptr) & 0xF0;
+                        *FAT_ptr =  (UCHAR)(temp | ((next_cluster >> 8) & 0xF));
+                    }
+                }
+
+                /* First, write out the current sector. */
+                status =  _fx_utility_logical_sector_write(media_ptr, (ULONG64) FAT_sector,
+                                                           media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_FAT_SECTOR);
+                /* Determine if an error occurred.  */
+                if (status != FX_SUCCESS)
+                {
+
+                    /* Return the error status.  */
+                    return(status);
+                }
+
+                /* Mark the FAT sector update bit map to indicate this sector has been written.  */
+                if (media_ptr -> fx_media_sectors_per_FAT % (FX_FAT_MAP_SIZE << 3) == 0)
+                {
+                    sectors_per_bit =  (UCHAR)((UINT)media_ptr -> fx_media_sectors_per_FAT / (FX_FAT_MAP_SIZE << 3));
+                }
+                else
+                {
+                    sectors_per_bit =  (UCHAR)((UINT)media_ptr -> fx_media_sectors_per_FAT / (FX_FAT_MAP_SIZE << 3) + 1);
+                }
+
+                /* Check for invalid value.  */
+                if (sectors_per_bit == 0)
+                {
+
+                    /* Invalid media, return error.  */
+                    return(FX_MEDIA_INVALID);
+                }
+
+                ind = ((FAT_sector - media_ptr -> fx_media_reserved_sectors) / sectors_per_bit) >> 3;
+                media_ptr -> fx_media_fat_secondary_update_map[ind] = 
+                    (UCHAR)((INT)media_ptr -> fx_media_fat_secondary_update_map[ind]
+                    | (1 <<(((FAT_sector - media_ptr -> fx_media_reserved_sectors) / sectors_per_bit) & 7)));
+
+                /* Determine if the multi-sector flag is set.  */
+                if (multi_sector_entry != -1)
+                {
+
+                    /* Yes, position to the next sector and read it in.  */
+                    FAT_sector++;
+                }
+                else
+                {
+
+                    /* No, we are finished with this loop.   */
+                    break;
+                }
+            }
+        }
+#ifdef FX_ENABLE_EXFAT
+        else if (media_ptr -> fx_media_FAT_type == FX_FAT16)
+#else
+        else if (!media_ptr -> fx_media_32_bit_FAT)
+#endif /* FX_ENABLE_EXFAT */
+        {
+
+            /* 16-bit FAT is present.  */
+
+            /* Calculate the byte offset to the cluster entry.  */
+            byte_offset =  (((ULONG)cluster) << 1);
+
+            /* Calculate the FAT sector the requested FAT entry resides in.  */
+            FAT_sector =  (byte_offset / media_ptr -> fx_media_bytes_per_sector) +
+                (ULONG)media_ptr -> fx_media_reserved_sectors;
+
+            /* Read the FAT sector.  */
+            status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) FAT_sector,
+                                                      media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_FAT_SECTOR);
+
+            /* Determine if an error occurred.  */
+            if (status != FX_SUCCESS)
+            {
+
+                /* Return the error status.  */
+                return(status);
+            }
+
+            /* Loop through the remainder of the cache to check for multiple entries
+               within the same FAT sector being written out.  */
+            for (i = index; i < FX_MAX_FAT_CACHE; i++)
+            {
+
+                /* Determine if the entry is dirty.  */
+                if (media_ptr -> fx_media_fat_cache[i].fx_fat_cache_entry_dirty == 0)
+                {
+
+                    /* Not dirty, does not need to be flushed.  */
+                    continue;
+                }
+
+                /* Isolate the cluster.  */
+                cluster = (media_ptr -> fx_media_fat_cache[i].fx_fat_cache_entry_cluster);
+
+                /* Calculate the byte offset to the cluster entry.  */
+                byte_offset =  (((ULONG)cluster) * 2);
+
+                /* Pickup the sector.  */
+                sector =  (byte_offset / media_ptr -> fx_media_bytes_per_sector) +
+                    (ULONG)media_ptr -> fx_media_reserved_sectors;
+
+                /* Is it the current FAT sector?  */
+                if (sector != FAT_sector)
+                {
+
+                    /* Different FAT sector - not in this pass of the loop.  */
+                    continue;
+                }
+
+                /* Now calculate the byte offset into this FAT sector.  */
+                byte_offset =  byte_offset -
+                    ((FAT_sector - (ULONG)media_ptr -> fx_media_reserved_sectors) *
+                     media_ptr -> fx_media_bytes_per_sector);
+
+                /* Setup a pointer into the buffer.  */
+                FAT_ptr =  (UCHAR *)media_ptr -> fx_media_memory_buffer + (UINT)byte_offset;
+
+                /* Pickup new value for this FAT entry.  */
+                next_cluster =  media_ptr -> fx_media_fat_cache[i].fx_fat_cache_entry_value;
+
+                /* Store the FAT entry.  */
+                _fx_utility_16_unsigned_write(FAT_ptr, (UINT)next_cluster);
+
+                /* Clear the dirty flag.  */
+                media_ptr -> fx_media_fat_cache[i].fx_fat_cache_entry_dirty = 0;
+            }
+
+            /* Write the last written FAT sector out.  */
+            status =  _fx_utility_logical_sector_write(media_ptr, (ULONG64) FAT_sector,
+                                                       media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_FAT_SECTOR);
+
+            /* Determine if an error occurred.  */
+            if (status != FX_SUCCESS)
+            {
+                /* Return the error status.  */
+                return(status);
+            }
+
+            /* Mark the FAT sector update bit map to indicate this sector has been
+               written.  */
+            if (media_ptr -> fx_media_sectors_per_FAT % (FX_FAT_MAP_SIZE << 3) == 0)
+            {
+                sectors_per_bit =  (UCHAR)(media_ptr -> fx_media_sectors_per_FAT / (FX_FAT_MAP_SIZE << 3));
+            }
+            else
+            {
+                sectors_per_bit =  (UCHAR)((media_ptr -> fx_media_sectors_per_FAT / (FX_FAT_MAP_SIZE << 3)) + 1);
+            }
+            ind = ((FAT_sector - media_ptr -> fx_media_reserved_sectors) / sectors_per_bit) >> 3;
+            media_ptr -> fx_media_fat_secondary_update_map[ind] = 
+                (UCHAR)((INT)media_ptr -> fx_media_fat_secondary_update_map[ind]
+                | (1 <<(((FAT_sector - media_ptr -> fx_media_reserved_sectors) / sectors_per_bit) & 7)));
+        }
+        else
+        {
+
+            /* 32-bit FAT or exFAT are present.  */
+
+            /* Calculate the byte offset to the cluster entry.  */
+            byte_offset =  (((ULONG)cluster) * 4);
+
+            /* Calculate the FAT sector the requested FAT entry resides in.  */
+            FAT_sector =  (byte_offset / media_ptr -> fx_media_bytes_per_sector) +
+                (ULONG)media_ptr -> fx_media_reserved_sectors;
+
+            /* Read the FAT sector.  */
+            status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) FAT_sector,
+                                                      media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_FAT_SECTOR);
+
+            /* Determine if an error occurred.  */
+            if (status != FX_SUCCESS)
+            {
+
+                /* Return the error status.  */
+                return(status);
+            }
+
+            /* Loop through the remainder of the cache to check for multiple entries
+               within the same FAT sector being written out.  */
+            for (i = index; i < FX_MAX_FAT_CACHE; i++)
+            {
+
+                /* Determine if the entry is dirty.  */
+                if (media_ptr -> fx_media_fat_cache[i].fx_fat_cache_entry_dirty == 0)
+                {
+
+                    /* Not dirty, does not need to be flushed.  */
+                    continue;
+                }
+
+                /* Isolate the cluster.  */
+                cluster = (media_ptr -> fx_media_fat_cache[i].fx_fat_cache_entry_cluster);
+
+                /* Calculate the byte offset to the cluster entry.  */
+                byte_offset =  (((ULONG)cluster) * 4);
+
+                /* Pickup the sector.  */
+                sector =  (byte_offset / media_ptr -> fx_media_bytes_per_sector) +
+                    (ULONG)media_ptr -> fx_media_reserved_sectors;
+
+                /* Is it the current FAT sector?  */
+                if (sector != FAT_sector)
+                {
+
+                    /* Different FAT sector - not in this pass of the loop.  */
+                    continue;
+                }
+
+                /* Now calculate the byte offset into this FAT sector.  */
+                byte_offset =  byte_offset -
+                    ((FAT_sector - (ULONG)media_ptr -> fx_media_reserved_sectors) *
+                     media_ptr -> fx_media_bytes_per_sector);
+
+                /* Setup a pointer into the buffer.  */
+                FAT_ptr =  (UCHAR *)media_ptr -> fx_media_memory_buffer + (UINT)byte_offset;
+
+                /* Pickup new value for this FAT entry.  */
+                next_cluster =  media_ptr -> fx_media_fat_cache[i].fx_fat_cache_entry_value;
+
+                /* Store the FAT entry.  */
+                _fx_utility_32_unsigned_write(FAT_ptr, next_cluster);
+
+                /* Clear the dirty flag.  */
+                media_ptr -> fx_media_fat_cache[i].fx_fat_cache_entry_dirty = 0;
+            }
+
+            /* Write the last written FAT sector out.  */
+            status =  _fx_utility_logical_sector_write(media_ptr, (ULONG64) FAT_sector,
+                                                       media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_FAT_SECTOR);
+
+            /* Determine if an error occurred.  */
+            if (status != FX_SUCCESS)
+            {
+
+                /* Return the error status.  */
+                return(status);
+            }
+
+#ifdef FX_ENABLE_EXFAT
+            /* We are not using fx_media_fat_secondary_update_map for exFAT.  */
+            if (media_ptr -> fx_media_FAT_type == FX_FAT32)
+            {
+#endif /* FX_ENABLE_EXFAT */
+
+                /* Mark the FAT sector update bit map to indicate this sector has been
+                   written.  */
+                if (media_ptr -> fx_media_sectors_per_FAT % (FX_FAT_MAP_SIZE << 3) == 0)
+                {
+                    sectors_per_bit =  (UCHAR)(media_ptr -> fx_media_sectors_per_FAT / (FX_FAT_MAP_SIZE << 3));
+                }
+                else
+                {
+                    sectors_per_bit =  (UCHAR)((media_ptr -> fx_media_sectors_per_FAT / (FX_FAT_MAP_SIZE << 3)) + 1);
+                }
+                ind = ((FAT_sector - media_ptr -> fx_media_reserved_sectors) / sectors_per_bit) >> 3;
+                media_ptr -> fx_media_fat_secondary_update_map[ind] = 
+                    (UCHAR)((INT)media_ptr -> fx_media_fat_secondary_update_map[ind]
+                    | (1 <<(((FAT_sector - media_ptr -> fx_media_reserved_sectors) / sectors_per_bit) & 7)));
+#ifdef FX_ENABLE_EXFAT
+            }
+#endif /* FX_ENABLE_EXFAT */
+        }
+    }
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+
+    /* While fault_tolerant is enabled, this function will be called before the return of all APIs. */
+    if (media_ptr -> fx_media_fault_tolerant_enabled)
+    {
+
+        /* Delete the record of FAT sector since all FAT entries are flushed. */
+        media_ptr -> fx_media_fault_tolerant_cached_FAT_sector = 0;
+    }
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Return successful status.  */
+    return(FX_SUCCESS);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_FAT_map_flush.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_FAT_map_flush.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_FAT_map_flush.c	(revision 30)
@@ -0,0 +1,172 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Utility                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_utility.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_utility_FAT_map_flush                           PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function updates mirrors changes in the primary FAT to each of */
+/*    secondary FATs in the media.                                        */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_logical_sector_read       Read FAT sector into memory   */
+/*    _fx_utility_logical_sector_write      Write FAT sector back to disk */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    FileX System Functions                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_utility_FAT_map_flush(FX_MEDIA *media_ptr)
+{
+
+ULONG FAT_sector, last_sector;
+UINT  i, status, FATs;
+UCHAR sectors_per_bit;
+
+
+    /* Determine how many FAT sectors each bit in the bit map represents.  Depending on
+       the number of sectors in the primary FAT, each bit in this map may represent one
+       or more primary FAT sectors. Because of this, it is possible some FAT sectors that
+       were not changed may get flushed out to the secondary FAT.  However, this method
+       provides very nice performance benefits during normal operation and is much more
+       reasonable than performing a total copy of the primary FAT to each secondary FAT
+       on media flush and media close.  */
+    if (media_ptr -> fx_media_sectors_per_FAT % (FX_FAT_MAP_SIZE << 3) == 0)
+    {
+        sectors_per_bit =  (UCHAR)(media_ptr -> fx_media_sectors_per_FAT / (FX_FAT_MAP_SIZE << 3));
+    }
+    else
+    {
+        sectors_per_bit =  (UCHAR)(media_ptr -> fx_media_sectors_per_FAT / (FX_FAT_MAP_SIZE << 3) + 1);
+    }
+
+    /* Loop through the FAT update map to mirror primary FAT sectors to secondary FAT(s).  */
+    for (i = 0; i < FX_FAT_MAP_SIZE << 3; i++)
+    {
+
+        /* Determine if there are FAT changes specified by this entry.  */
+        if ((media_ptr -> fx_media_fat_secondary_update_map[i >> 3] & (1 << (i & 7))) == 0)
+        {
+
+            /* No, look at the next bit map entry.  */
+            continue;
+        }
+
+        /* Setup the parameters for performing the update.  */
+        FAT_sector =    i * sectors_per_bit + media_ptr -> fx_media_reserved_sectors;
+        last_sector =   FAT_sector + sectors_per_bit;
+
+        /* Make sure the last update sector is within range.  */
+        if (last_sector > (media_ptr -> fx_media_sectors_per_FAT + media_ptr -> fx_media_reserved_sectors))
+        {
+            last_sector =  media_ptr -> fx_media_sectors_per_FAT + media_ptr -> fx_media_reserved_sectors;
+        }
+
+        /* Loop to mirror primary FAT sectors to secondary FAT(s).  */
+        for (; FAT_sector < last_sector; FAT_sector++)
+        {
+
+            /* Read the FAT sector.  */
+            status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) FAT_sector,
+                                                      media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_FAT_SECTOR);
+
+            /* Determine if an error occurred.  */
+            if (status != FX_SUCCESS)
+            {
+                /* Return the error status.  */
+                return(status);
+            }
+
+            /* Pickup how many secondary FATs there are.  */
+            FATs =  media_ptr -> fx_media_number_of_FATs - 1;
+
+            /* Loop to update additional FAT entries.  */
+            while (FATs)
+            {
+
+                /* Mirror main FAT sector write into the additional FATs.  */
+                status =  _fx_utility_logical_sector_write(media_ptr,
+                                                           ((ULONG64) FAT_sector) + ((ULONG64)FATs * (ULONG64)(media_ptr -> fx_media_sectors_per_FAT)),
+                                                           media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_FAT_SECTOR);
+
+                /* Determine if an error occurred.  */
+                if (status != FX_SUCCESS)
+                {
+
+                    /* Return the error status.  */
+                    return(status);
+                }
+
+                /* Decrement the number of FATs.  */
+                FATs--;
+            }
+        }
+    }
+
+    /* Clear the bit map that indicates primary FAT updates.  */
+    for (i = 0; i < FX_FAT_MAP_SIZE; i++)
+    {
+
+        /* Clear each entry in the bit map.  */
+        media_ptr -> fx_media_fat_secondary_update_map[i] =  0;
+    }
+
+    /* Return a successful completion.  */
+    return(FX_SUCCESS);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_FAT_sector_get.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_FAT_sector_get.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_FAT_sector_get.c	(revision 30)
@@ -0,0 +1,119 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Utility                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_utility.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_utility_FAT_sector_get                          PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function gets the sector of supplied FAT entry.                */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    cluster                               Cluster entry number          */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return sector of FAT entry                                          */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    FileX System Functions                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+ULONG  _fx_utility_FAT_sector_get(FX_MEDIA *media_ptr, ULONG cluster)
+{
+
+ULONG  FAT_sector;
+ULONG  byte_offset;
+
+    /* Determine which type of FAT is present.  */
+#ifdef FX_ENABLE_EXFAT
+    if (media_ptr -> fx_media_FAT_type == FX_FAT12)
+#else
+    if (media_ptr -> fx_media_12_bit_FAT)
+#endif /* FX_ENABLE_EXFAT */
+    {
+
+        /* 12-bit FAT is present.  */
+
+        /* Calculate the byte offset to the cluster entry.  */
+        byte_offset =  (((ULONG)cluster << 1) + cluster) >> 1;
+
+    }
+#ifdef FX_ENABLE_EXFAT
+    else if (media_ptr -> fx_media_FAT_type == FX_FAT16)
+#else
+    else if (!media_ptr -> fx_media_32_bit_FAT)
+#endif /* FX_ENABLE_EXFAT */
+    {
+
+        /* 16-bit FAT is present.  */
+
+        /* Calculate the byte offset to the cluster entry.  */
+        byte_offset =  (((ULONG)cluster) << 1);
+    }
+    else
+    {
+
+        /* 32-bit FAT or exFAT are present.  */
+
+        /* Calculate the byte offset to the cluster entry.  */
+        byte_offset =  (((ULONG)cluster) * 4);
+    }
+
+    /* Calculate the FAT sector the requested FAT entry resides in.  */
+    FAT_sector =  (byte_offset / media_ptr -> fx_media_bytes_per_sector) +
+        (ULONG)media_ptr -> fx_media_reserved_sectors;
+
+    /* Return successful status.  */
+    return(FAT_sector);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_absolute_path_get.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_absolute_path_get.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_absolute_path_get.c	(revision 30)
@@ -0,0 +1,254 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Utility                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_utility.h"
+
+
+#ifdef FX_ENABLE_EXFAT
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_utility_absolute_path_get                       PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function converts concatenating of base and new path to        */
+/*    absolute path.                                                      */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    base_path                             Base (current) path           */
+/*    new_path                              New path                      */
+/*    absolute_path                         Absolute Path                 */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    absolute_path                         Resulting absolute path       */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_token_length_get          Get the next token length     */
+/*    _fx_utility_string_length_get         Get string length             */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    _fx_directory_default_set                                           */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_utility_absolute_path_get(CHAR *base_path, CHAR *new_path, CHAR *absolute_path)
+{
+
+UINT length;
+UINT absolute_position;
+UINT i;
+
+
+    /* Check if we got null pointers.  */
+    if (!base_path || !new_path || !absolute_path)
+    {
+
+        /* Return error.  */
+        return(FX_INVALID_PATH);
+    }
+
+    /* Is the new path starts from root?  */
+    if ((new_path[0] == '\\') || (new_path[0] == '/'))
+    {
+
+        /* Yes, set the absolute path to root.  */
+        absolute_path[0] = '\\';
+        absolute_path[1] = 0;
+        new_path++;
+    }
+    else
+    {
+
+        /* Initialize the absolute path with the base path.  */
+        i =  0;
+        while ((base_path[i]) && (i < FX_MAXIMUM_PATH))
+        {
+
+            /* Copy a character.  */
+            absolute_path[i] =  base_path[i];
+
+            /* Move to next character.  */
+            i++;
+        }
+
+        /* Is the absolute path still NULL?  */
+        if ((absolute_path[0] == 0) || (i == 0))
+        {
+
+            /* Yes, set the absolute path to root.  */
+            absolute_path[0] = '\\';
+            absolute_path[1] = 0;
+        }
+    }
+
+    /* Loop to add new path to the absolute path.  */
+    while ((length = _fx_utility_token_length_get(new_path)) > 0)
+    {
+
+        /* Check if the path is too long.  */
+        if ((new_path[length] != 0) && (new_path[length] != '\\') && (new_path[length] != '/'))
+        {
+            /* The path is too long, return error.  */
+            return(FX_INVALID_PATH);
+        }
+
+        /* Check if we have a current directory mark.  */
+        if ((length == 1) && (new_path[0] == '.'))
+        {
+
+            /* The same directory, just skip it.  */
+        }
+        /* Do we have a parent directory mark?  */
+        else if ((length == 2) && (new_path[0] == '.') && (new_path[1] == '.'))
+        {
+
+            /* Yes, we need to move the absolute path to the parent directory.  */
+            /* Check absolute path length.  */
+            absolute_position = _fx_utility_string_length_get(absolute_path, FX_MAXIMUM_PATH);
+            if ((absolute_position < 2) || (absolute_path[absolute_position] != 0))
+            {
+
+                /* No parent directory left in the absolute path, or invalid path length, return error.  */
+                return(FX_INVALID_PATH);
+            }
+
+            /* Move to the last character of the absolute path.  */
+            absolute_position--;
+
+            /* Check if we have a directory separator.  */
+            if ((absolute_path[absolute_position] == '\\') || (absolute_path[absolute_position] == '/'))
+            {
+
+                /* Remove the separator.  */
+                absolute_path[absolute_position] = 0;
+                absolute_position--;
+            }
+
+            /* Loop to clear the character backward until a seprator or string exhaust.  */
+            while ((absolute_path[absolute_position] != '\\') && (absolute_path[absolute_position] != '/') && (absolute_position > 0))
+            {
+
+                /* Remove one character.  */
+                absolute_path[absolute_position] = 0;
+                absolute_position--;
+            }
+
+            /* Do we have somthing left in the path?  */
+            if (absolute_position > 1)
+            {
+
+                /* Yes, remove the last separator.  */
+                absolute_path[absolute_position] = 0;
+            }
+        }
+        else
+        {
+
+            /* Normal directory, add it.  */
+            absolute_position = _fx_utility_string_length_get(absolute_path, FX_MAXIMUM_PATH);
+
+            /* Check if the path is too long.  */
+            if (absolute_path[absolute_position] != 0)
+            {
+
+                /* The path is too long, return error.  */
+                return(FX_INVALID_PATH);
+            }
+
+            /* Check if we have something in the path.  */
+            if (absolute_position)
+            {
+
+                /* Do we have a separator in the last character?  */
+                if ((absolute_path[absolute_position - 1] != '\\') && (absolute_path[absolute_position - 1] != '/'))
+                {
+
+                    /* No, add a directory separator to the path string.  */
+                    absolute_path[absolute_position] = '\\';
+                    absolute_position++;
+                }
+            }
+
+            /* Loop to copy the new path to the absolute path.  */
+            i = 0;
+            while ((absolute_position < FX_MAXIMUM_PATH) && (i < length))
+            {
+
+                /* Copy one character.  */
+                absolute_path[absolute_position++] = new_path[i++];
+            }
+
+            /* Check if we have not exceed the maximum length.  */
+            if (absolute_position < FX_MAXIMUM_PATH)
+            {
+
+                /* Terminate the string.  */
+                absolute_path[absolute_position] = 0;
+            }
+            else
+            {
+
+                /* The path is too long, return error.  */
+                return(FX_INVALID_PATH);
+            }
+        }
+
+        /* Move to the next component.  */
+        new_path += length;
+
+        /* Is the next component starts with a separator?  */
+        if ((new_path[0] == '\\') || (new_path[0] == '/'))
+        {
+
+            /* Yes, skip it.  */
+            new_path++;
+        }
+    }
+
+    return(FX_SUCCESS);
+}
+#endif /* FX_ENABLE_EXFAT */
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_allocate_new_cluster.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_allocate_new_cluster.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_allocate_new_cluster.c	(revision 30)
@@ -0,0 +1,232 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_directory.h"
+#include "fx_utility.h"
+#ifdef FX_ENABLE_EXFAT
+#include "fx_directory_exFAT.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_utility_exFAT_allocate_new_cluster              PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function allocates new cluster media for a free                */
+/*    directory entry.                                                    */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    directory_ptr                         Pointer to directory to       */
+/*                                            search in                   */
+/*    last_cluster                          Last cluster of entry         */
+/*    cluster                               Allocated cluster             */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_exFAT_entry_read        Read exFAT entries            */
+/*    _fx_utility_exFAT_bitmap_flush        Flush exFAT allocation bitmap */
+/*    _fx_utility_exFAT_bitmap_free_cluster_find                          */
+/*                                          Find free cluster             */
+/*    _fx_utility_exFAT_cluster_state_get   Get cluster state             */
+/*    _fx_utility_FAT_entry_read            Read FAT entry                */
+/*    _fx_utility_FAT_entry_write           Write FAT entry               */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    _fx_directory_exFAT_free_search                                     */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_utility_exFAT_allocate_new_cluster(FX_MEDIA *media_ptr, FX_DIR_ENTRY *directory_ptr,
+                                             ULONG *last_cluster, ULONG *cluster)
+{
+
+UINT  status = FX_SUCCESS;
+ULONG cluster_count;
+ULONG bytes_per_cluster;
+ULONG i;
+ULONG FAT_value = 0;
+UCHAR cluster_state = FX_EXFAT_BITMAP_CLUSTER_OCCUPIED;
+
+
+    /* Clear the last cluster number.  */
+    *last_cluster = 0;
+
+    /* Check if we have any already allocated clusters.  */
+    if (!directory_ptr || (directory_ptr -> fx_dir_entry_available_file_size > 0))
+    {
+
+        /* Calculate bytes per cluster.  */
+        bytes_per_cluster = ((ULONG)media_ptr -> fx_media_bytes_per_sector) *
+                             ((ULONG)media_ptr -> fx_media_sectors_per_cluster);
+
+        /* Check if FAT table is not used.  */
+        if (directory_ptr && (directory_ptr -> fx_dir_entry_dont_use_fat & 1))
+        {
+
+            /* Calculate the cluster count associated with the directory.  */
+            cluster_count = (ULONG)((directory_ptr -> fx_dir_entry_available_file_size + bytes_per_cluster - 1) /
+                                    bytes_per_cluster);
+
+            /* Calculate the next cluster and the last cluster.  */
+            *cluster = directory_ptr -> fx_dir_entry_cluster + cluster_count;
+            *last_cluster = *cluster - 1;
+
+            /* Make sure the next cluster number don't exceed the total cluster number.  */
+            if (*cluster < media_ptr -> fx_media_total_clusters + FX_FAT_ENTRY_START)
+            {
+
+                /* Get cluster state.  */
+                status = _fx_utility_exFAT_cluster_state_get(media_ptr, *cluster, &cluster_state);
+
+                if (status != FX_SUCCESS)
+                {
+
+                    /* Return the bad status.  */
+                    return(status);
+                }
+            }
+
+            /* Is the next cluster free?  */
+            if (cluster_state == FX_EXFAT_BITMAP_CLUSTER_FREE)
+            {
+
+                /* Yes, so we still don't need to use FAT.  */
+                return(FX_SUCCESS);
+            }
+
+            /* Now we should use FAT. Clear the bit 0.  */
+            directory_ptr -> fx_dir_entry_dont_use_fat &= (CHAR)0xfe;
+
+            /* Loop to build FAT chain.  */
+            for (i = directory_ptr -> fx_dir_entry_cluster; i < *last_cluster; ++i)
+            {
+
+                /* Write the FAT entry.  */
+                status = _fx_utility_FAT_entry_write(media_ptr, i, i + 1);
+                if (status != FX_SUCCESS)
+                {
+
+                    /* Return the bad status.  */
+                    return(status);
+                }
+            }
+
+            /* Write last cluster entry.  */
+            status = _fx_utility_FAT_entry_write(media_ptr, *last_cluster, FX_LAST_CLUSTER_exFAT);
+
+            if (status != FX_SUCCESS)
+            {
+
+                /* Return the bad status.  */
+                return(status);
+            }
+        }
+        else
+        {
+
+            /* Find last cluster by walk through the FAT chain.  */
+            /* See if we are in sub directory or the root directory. And set the start cluster.  */
+            if (directory_ptr)
+            {
+                *cluster = directory_ptr -> fx_dir_entry_cluster;
+            }
+            else
+            {
+                *cluster = media_ptr -> fx_media_root_cluster_32;
+            }
+
+            /* Initialize loop variables.  */
+            *last_cluster =  0;
+            i =  0;
+
+            /* Follow the link of FAT entries.  */
+            while ((*cluster >= FX_FAT_ENTRY_START) && (*cluster < FX_RESERVED_1_exFAT))
+            {
+
+                /* Read the current cluster entry from the FAT.  */
+                status =  _fx_utility_FAT_entry_read(media_ptr, *cluster, &FAT_value);
+                i++;
+
+                /* Check the return value.  */
+                if (status != FX_SUCCESS)
+                {
+
+                    /* Return the error status.  */
+                    return(status);
+                }
+
+                /* Determine if the FAT read was invalid.  */
+                if ((*cluster == FAT_value) || (i > media_ptr -> fx_media_total_clusters))
+                {
+
+                    /* Return the bad status.  */
+                    return(FX_FAT_READ_ERROR);
+                }
+
+                /* Save the last valid cluster.  */
+                *last_cluster = *cluster;
+
+                /* Setup for the next cluster.  */
+                *cluster =  FAT_value;
+            }
+        }
+    }
+
+    /* Find free cluster from exFAT media.  */
+    status =  _fx_utility_exFAT_bitmap_free_cluster_find(media_ptr,
+                                                         media_ptr -> fx_media_cluster_search_start,
+                                                         cluster);
+
+    return(status);
+}
+
+
+#endif /* FX_ENABLE_EXFAT */
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_bitmap_cache_prepare.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_bitmap_cache_prepare.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_bitmap_cache_prepare.c	(revision 30)
@@ -0,0 +1,120 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Utility                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+
+
+#ifdef FX_ENABLE_EXFAT
+#include "fx_system.h"
+#include "fx_media.h"
+#include "fx_utility.h"
+#include "fx_directory_exFAT.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_utility_exFAT_bitmap_cache_prepare              PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks if the bitmap for specified cluster is in      */
+/*    cache. If not, it will read the bitmap portion to cache.            */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    cluster                               Cluster number                */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_exFAT_bitmap_flush        Flush bitmap cache            */
+/*    _fx_utility_exFAT_bitmap_cache_update Read bitmap to cache          */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    FileX System Functions                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_utility_exFAT_bitmap_cache_prepare(FX_MEDIA *media_ptr, ULONG cluster)
+{
+
+UINT status;
+
+
+    /* Default the status to no more space.  */
+    status = FX_NO_MORE_SPACE;
+
+    /* Make sure the cluster does not exceed the total count.  */
+    if (cluster < media_ptr -> fx_media_total_clusters + FX_FAT_ENTRY_START)
+    {
+
+        /* Check if the request cluster is already cached.  */
+        if ((cluster >= media_ptr -> fx_media_exfat_bitmap_cache_start_cluster) &&
+            (cluster <= media_ptr -> fx_media_exfat_bitmap_cache_end_cluster))
+        {
+
+            /* Cluster already cached.  */
+            status = FX_SUCCESS;
+        }
+        else
+        {
+
+            /* Need to Cache update.  */
+
+            /* Flush previous cached data if required.  */
+            if (FX_SUCCESS == (status = _fx_utility_exFAT_bitmap_flush(media_ptr)))
+            {
+
+                /* Call utility function to update cache.  */
+                status = _fx_utility_exFAT_bitmap_cache_update(media_ptr, cluster);
+            }
+        }
+    }
+
+    /* Return status.  */
+    return(status);
+}
+
+#endif /* FX_ENABLE_EXFAT */
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_bitmap_cache_update.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_bitmap_cache_update.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_bitmap_cache_update.c	(revision 30)
@@ -0,0 +1,107 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Utility                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+
+
+#ifdef FX_ENABLE_EXFAT
+#include "fx_system.h"
+#include "fx_media.h"
+#include "fx_utility.h"
+#include "fx_directory_exFAT.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_utility_exFAT_bitmap_cache_update               PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function reads parts of exFAT bitmap to cache.                 */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    cluster                               Cluster number                */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    Media driver                                                        */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    FileX System Functions                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT   _fx_utility_exFAT_bitmap_cache_update(FX_MEDIA *media_ptr, ULONG cluster)
+{
+
+    /* Read exFAT bitmap to cache.  */
+    cluster -= FX_FAT_ENTRY_START;
+    media_ptr -> fx_media_driver_request        =  FX_DRIVER_READ;
+    media_ptr -> fx_media_driver_buffer         =  (UCHAR *)media_ptr -> fx_media_exfat_bitmap_cache;
+    media_ptr -> fx_media_driver_logical_sector =  media_ptr -> fx_media_exfat_bitmap_start_sector +
+        (cluster >> media_ptr -> fx_media_exfat_bitmap_clusters_per_sector_shift);
+    media_ptr -> fx_media_driver_sectors        =  media_ptr -> fx_media_exfat_bitmap_cache_size_in_sectors;
+    media_ptr -> fx_media_driver_status         =  FX_IO_ERROR;
+
+    /* Invoke the driver to read the FAT sectors.  */
+    (media_ptr -> fx_media_driver_entry)(media_ptr);
+
+    /* Calculate new cached clusters.  */
+    media_ptr -> fx_media_exfat_bitmap_cache_start_cluster =
+        (ULONG)((media_ptr -> fx_media_driver_logical_sector - media_ptr -> fx_media_exfat_bitmap_start_sector) <<
+                media_ptr -> fx_media_exfat_bitmap_clusters_per_sector_shift) +
+        FX_FAT_ENTRY_START;
+
+    media_ptr -> fx_media_exfat_bitmap_cache_end_cluster = media_ptr -> fx_media_exfat_bitmap_cache_start_cluster +
+        ((media_ptr -> fx_media_exfat_bitmap_cache_size_in_sectors << media_ptr -> fx_media_exfat_bytes_per_sector_shift) <<
+         BITS_PER_BYTE_SHIFT) - 1;
+
+    /* Return driver status.  */
+    return(media_ptr -> fx_media_driver_status);
+}
+
+#endif /* FX_ENABLE_EXFAT */
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_bitmap_flush.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_bitmap_flush.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_bitmap_flush.c	(revision 30)
@@ -0,0 +1,115 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Utility                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+#define FX_SOURCE_CODE
+
+/* Include necessary system files.  */
+
+
+#include "fx_api.h"
+
+
+#ifdef FX_ENABLE_EXFAT
+#include "fx_system.h"
+#include "fx_media.h"
+#include "fx_utility.h"
+#include "fx_directory_exFAT.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_utility_exFAT_bitmap_flush                      PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function writes cached exFAT bitmap back to media.             */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    Media driver                                                        */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    FileX System Functions                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_utility_exFAT_bitmap_flush(FX_MEDIA *media_ptr)
+{
+
+    /* Check if the bitmap cache is dirty.  */
+    if (FX_TRUE == media_ptr -> fx_media_exfat_bitmap_cache_dirty)
+    {
+
+        /* Write cached exFAT bitmap.  */
+        media_ptr -> fx_media_driver_request =  FX_DRIVER_WRITE;
+        media_ptr -> fx_media_driver_status =   FX_IO_ERROR;
+        media_ptr -> fx_media_driver_buffer  =  (UCHAR *)media_ptr -> fx_media_exfat_bitmap_cache;
+        media_ptr -> fx_media_driver_sectors =  media_ptr -> fx_media_exfat_bitmap_cache_size_in_sectors;
+
+        media_ptr -> fx_media_driver_logical_sector =  media_ptr -> fx_media_exfat_bitmap_start_sector +
+            ((media_ptr -> fx_media_exfat_bitmap_cache_start_cluster - FX_FAT_ENTRY_START) >>
+             media_ptr -> fx_media_exfat_bitmap_clusters_per_sector_shift);
+
+        /* Invoke the driver to write the bitmap sectors.  */
+        (media_ptr -> fx_media_driver_entry)(media_ptr);
+
+        /* Determine if the write was successful.  */
+        if (media_ptr -> fx_media_driver_status == FX_SUCCESS)
+        {
+
+            /* Set bitmap cache dirty flag to false.  */
+            media_ptr -> fx_media_exfat_bitmap_cache_dirty =  FX_FALSE;
+        }
+    }
+    else
+    {
+
+        /* Initialize return status to success.  */
+        media_ptr -> fx_media_driver_status =  FX_SUCCESS;
+    }
+
+    return(media_ptr -> fx_media_driver_status);
+}
+
+#endif /* FX_ENABLE_EXFAT */
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_bitmap_free_cluster_find.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_bitmap_free_cluster_find.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_bitmap_free_cluster_find.c	(revision 30)
@@ -0,0 +1,161 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Utility                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+#define FX_SOURCE_CODE
+
+/* Include necessary system files.  */
+
+
+#include "fx_api.h"
+
+
+#ifdef FX_ENABLE_EXFAT
+#include "fx_system.h"
+#include "fx_media.h"
+#include "fx_utility.h"
+#include "fx_directory_exFAT.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_utility_exFAT_bitmap_free_cluster_find          PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function searches for a free cluster.                          */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    search_start_cluster                  Cluster number to begin search*/
+/*    free_cluster                          ULONG pointer to store cluster*/
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_exFAT_cluster_state_get   Get cluster state             */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    FileX System Functions                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_utility_exFAT_bitmap_free_cluster_find(FX_MEDIA *media_ptr, ULONG search_start_cluster, ULONG *free_cluster)
+{
+
+UINT  status;
+UCHAR cluster_state;
+ULONG cluster = search_start_cluster;
+
+
+    /* Search for a free cluster.  */
+    while (cluster < media_ptr -> fx_media_total_clusters + FX_FAT_ENTRY_START)
+    {
+
+        /* Get the cluster state.  */
+        status = _fx_utility_exFAT_cluster_state_get(media_ptr, cluster, &cluster_state);
+
+        /* Check the status of the state get.  */
+        if (status != FX_SUCCESS)
+        {
+
+            /* Media error or out of total clusters number - stop searching.  */
+            return(status);
+        }
+
+        /* Is this cluster free?  */
+        if (cluster_state == FX_EXFAT_BITMAP_CLUSTER_FREE)
+        {
+
+            /* Yes, finished the search.  */
+
+            /* Return the cluster.  */
+            *free_cluster = cluster;
+
+            /* Return success.  */
+            return(FX_SUCCESS);
+        }
+
+        /* Move to next cluster.  */
+        cluster++;
+    }
+
+    /* See if there is anything to search in the beginning.  */
+    if (search_start_cluster > FX_FAT_ENTRY_START)
+    {
+
+        /* Start at the beginning.  */
+        cluster = FX_FAT_ENTRY_START;
+
+        /* Loop to search clusters.  */
+        while (cluster < search_start_cluster)
+        {
+
+            /* Get the cluster state.  */
+            status = _fx_utility_exFAT_cluster_state_get(media_ptr, cluster, &cluster_state);
+            if (status != FX_SUCCESS)
+            {
+
+                /* Media error or out of total clusters number - stop searching.  */
+                return(status);
+            }
+
+            /* Is this cluster free?  */
+            if (cluster_state == FX_EXFAT_BITMAP_CLUSTER_FREE)
+            {
+
+                /* Yes, finished the search.  */
+
+                /* Return the cluster.  */
+                *free_cluster = cluster;
+
+                /* Return success.  */
+                return(FX_SUCCESS);
+            }
+
+            /* Move to the next cluster.  */
+            cluster++;
+        }
+    }
+
+    /* No more free clusters, return error.  */
+    return(FX_NO_MORE_SPACE);
+}
+
+#endif /* FX_ENABLE_EXFAT */
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_bitmap_initialize.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_bitmap_initialize.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_bitmap_initialize.c	(revision 30)
@@ -0,0 +1,186 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Utility                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+
+
+#ifdef FX_ENABLE_EXFAT
+#include "fx_system.h"
+#include "fx_media.h"
+#include "fx_utility.h"
+#include "fx_directory_exFAT.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_utility_exFAT_bitmap_initialize                 PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function initializes bitmap for exFAT volume.                  */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    Media driver                                                        */
+/*    _fx_utility_exFAT_bitmap_free_cluster_find                          */
+/*                                          Find free cluster             */
+/*    _fx_utility_exFAT_bitmap_cache_update Read bitmap cache             */
+/*    _fx_utility_exFAT_bitmap_start_sector_get                           */
+/*                                          Get the bitmap starting sector*/
+/*    _fx_utility_exFAT_cluster_state_get   Get cluster state             */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    FileX System Functions                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT   _fx_utility_exFAT_bitmap_initialize(FX_MEDIA *media_ptr)
+{
+
+UINT  status;
+ULONG cluster;
+UCHAR cluster_state;
+ULONG bitmap_cache_size;
+ULONG bitmap_size_in_bytes;
+ULONG bitmap_size_in_sectors;
+ULONG bitmap_total_size_in_bytes;
+
+
+    /* Calculate exFAT bitmap size.  */
+    bitmap_size_in_bytes =    DIVIDE_TO_CEILING(media_ptr -> fx_media_total_clusters, BITS_PER_BYTE);
+    bitmap_size_in_sectors =  DIVIDE_TO_CEILING(bitmap_size_in_bytes, media_ptr -> fx_media_bytes_per_sector);
+
+    /* Align bitmap size by sectors size.  */
+    bitmap_total_size_in_bytes =  bitmap_size_in_sectors << media_ptr -> fx_media_exfat_bytes_per_sector_shift;
+
+    /* Set default bitMap cache size.  */
+    bitmap_cache_size = media_ptr -> fx_media_bytes_per_sector * FX_EXFAT_BIT_MAP_NUM_OF_CACHED_SECTORS;
+
+    /* Do not use the memory if it not required.  */
+    if (bitmap_cache_size > bitmap_total_size_in_bytes)
+    {
+
+        /* Adjust the cache size.  */
+        bitmap_cache_size =  bitmap_total_size_in_bytes;
+    }
+
+    /* Try to find BitMap start sector.  */
+    status = _fx_utility_exFAT_bitmap_start_sector_get(media_ptr, &media_ptr -> fx_media_exfat_bitmap_start_sector);
+
+    /* Did we get the starting sector?  */
+    if (status == FX_SUCCESS)
+    {
+
+        /* Yes, setup the media cache parameters.  */
+        media_ptr -> fx_media_exfat_bitmap_cache_size_in_sectors  =
+            bitmap_cache_size >> media_ptr -> fx_media_exfat_bytes_per_sector_shift;
+
+        media_ptr -> fx_media_exfat_bitmap_cache_dirty         =  FX_FALSE;
+        media_ptr -> fx_media_exfat_bitmap_cache_start_cluster =  FX_FAT_ENTRY_START;
+
+        /* Calculate how many clusters mapped in the one sector.  */
+        media_ptr -> fx_media_exfat_bitmap_clusters_per_sector_shift =
+            media_ptr -> fx_media_exfat_bytes_per_sector_shift +
+            BITS_PER_BYTE_SHIFT;
+
+        /* Start at initial cluster.  */
+        cluster =  FX_FAT_ENTRY_START;
+
+        /* Read first portion of BitMap.  */
+        status = _fx_utility_exFAT_bitmap_cache_update(media_ptr, cluster);
+
+        /* Was the BitMap read successful?  */
+        if (status == FX_SUCCESS)
+        {
+
+            /* Find first free cluster.  */
+            status = _fx_utility_exFAT_bitmap_free_cluster_find(media_ptr, cluster, &cluster);
+
+            /* Did we find a free cluster?  */
+            if (status == FX_SUCCESS)
+            {
+
+                /* Save first free cluster number.  */
+                media_ptr -> fx_media_cluster_search_start =  cluster;
+
+                /* Calculate number of free clusters from first free cluster.  */
+                while (cluster < media_ptr -> fx_media_total_clusters  + FX_FAT_ENTRY_START)
+                {
+
+                    /* Get the state of the cluster.  */
+                    status = _fx_utility_exFAT_cluster_state_get(media_ptr, cluster, &cluster_state);
+
+                    /* Was the state get successful?  */
+                    if (status != FX_SUCCESS)
+                    {
+
+                        /* No, get out of the loop.  */
+                        break;
+                    }
+
+                    /* Is the cluster free?  */
+                    if (FX_EXFAT_BITMAP_CLUSTER_FREE == cluster_state)
+                    {
+
+                        /* Yes, increment the available clusters.  */
+                        media_ptr -> fx_media_available_clusters++;
+                    }
+
+                    /* Move to next cluster.  */
+                    cluster++;
+                }
+            }
+        }
+    }
+
+    /* Return status.  */
+    return(status);
+}
+
+#endif /* FX_ENABLE_EXFAT */
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_bitmap_start_sector_get.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_bitmap_start_sector_get.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_bitmap_start_sector_get.c	(revision 30)
@@ -0,0 +1,153 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Utility                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+
+
+#ifdef FX_ENABLE_EXFAT
+#include "fx_system.h"
+#include "fx_media.h"
+#include "fx_utility.h"
+#include "fx_directory_exFAT.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_utility_exFAT_bitmap_start_sector_get           PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function gets the start sector of exFAT bitmap.                */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    bitmap_started_sector                 Pointer to ULONG              */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_logical_sector_read       Read logical sector           */
+/*    _fx_utility_64_unsigned_read          Read a ULONG64 from memory    */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    FileX System Functions                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT   _fx_utility_exFAT_bitmap_start_sector_get(FX_MEDIA *media_ptr, ULONG *bitmap_started_sector)
+{
+
+ULONG  sectors_count;
+UCHAR *dir_entry_ptr;
+
+
+    /* Initialize the sector count.  */
+    sectors_count =  0;
+
+    /* Go through the first cluster of exFAT root directory. This cluster should
+       contain BitMap allocation DirEntry */
+    while (sectors_count < media_ptr -> fx_media_sectors_per_cluster)
+    {
+
+        /*  Will use read sector function with cache functionality since first cluster
+            will be used by other services. */
+        if (FX_SUCCESS != _fx_utility_logical_sector_read(media_ptr,
+                                                          (ULONG64) (media_ptr -> fx_media_root_sector_start + sectors_count),
+                                                          media_ptr -> fx_media_memory_buffer,
+                                                          ((ULONG) 1), FX_DATA_SECTOR))
+        {
+
+            /* Error reading the sector, get out of the loop.  */
+            break;
+        }
+
+        /* Increment the sectors count.  */
+        sectors_count++;
+
+        /* Setup pointer to directory entry.  */
+        dir_entry_ptr =  media_ptr -> fx_media_memory_buffer;
+
+        /* Go through the read buffer and try to find BitMap table directory entry.  */
+        while (dir_entry_ptr < (media_ptr -> fx_media_memory_buffer +
+                                media_ptr -> fx_media_bytes_per_sector))
+        {
+
+            /* Determine if this entry is the bitmap allocation type.  */
+            if (FX_EXFAT_DIR_ENTRY_TYPE_ALLOCATION_BITMAP == dir_entry_ptr[FX_EXFAT_ENTRY_TYPE])
+            {
+
+                /* Yes, calculate BitMap table start sector.  */
+                *bitmap_started_sector = media_ptr -> fx_media_data_sector_start +
+                    (UINT)((dir_entry_ptr[FX_EXFAT_FIRST_CLUSTER] - FX_FAT_ENTRY_START) <<
+                                        media_ptr -> fx_media_exfat_sector_per_clusters_shift);
+
+                /* Check FirstCluster and DataLength fields for error.  */
+                if ((0 == *bitmap_started_sector) ||
+                    (media_ptr -> fx_media_total_clusters >
+                     ((ULONG)_fx_utility_64_unsigned_read(&dir_entry_ptr[FX_EXFAT_DATA_LENGTH]) <<
+                    BITS_PER_BYTE_SHIFT)))
+                {
+
+                    /* Media invalid - return error!  */
+                    return(FX_MEDIA_INVALID);
+                }
+
+                /* Return success!  */
+                return(FX_SUCCESS);
+            }
+            else
+            {
+
+                /* Move to next directory entry.  */
+                dir_entry_ptr +=  FX_EXFAT_DIR_ENTRY_SIZE;
+            }
+        }
+    }
+
+    /* Return media invalid error.  */
+    return(FX_MEDIA_INVALID);
+}
+
+#endif /* FX_ENABLE_EXFAT */
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_cluster_free.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_cluster_free.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_cluster_free.c	(revision 30)
@@ -0,0 +1,215 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Utility                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+
+
+#ifdef FX_ENABLE_EXFAT
+#include "fx_directory_exFAT.h"
+#include "fx_utility.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_utility_exFAT_cluster_free                      PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function deallocates clusters deleted unknown type             */
+/*    directory entry.                                                    */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    work_ptr                              Pointer to directory to       */
+/*                                            unknown directory entry     */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_32_unsigned_read          Read 32-bit value             */
+/*    _fx_utility_64_unsigned_read          Read 64-bit value             */
+/*    _fx_utility_FAT_entry_read            Read FAT entry                */
+/*    _fx_utility_FAT_entry_write           Write FAT entry               */
+/*    _fx_utility_exFAT_cluster_state_set   Set cluster state             */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    _fx_directory_exFAT_unicode_entry_write                             */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_utility_exFAT_cluster_free(FX_MEDIA *media_ptr, UCHAR *work_ptr)
+{
+
+ULONG   cluster;
+ULONG64 data_length;
+ULONG   clusters_released;
+ULONG   clusters_count;
+ULONG   bytes_per_cluster;
+ULONG   contents = 0;
+UCHAR   dont_use_fat;
+UINT    status;
+
+
+    /* Pickup the cluster to release. */
+    cluster =       _fx_utility_32_unsigned_read(&(work_ptr[FX_EXFAT_FIRST_CLUSTER]));
+
+    /* Pickup the data length.  */
+    data_length =   _fx_utility_64_unsigned_read(&(work_ptr[FX_EXFAT_DATA_LENGTH]));
+
+    /* Pickup the flag that determines if the FAT should be used.  */
+    dont_use_fat =  (work_ptr[FX_EXFAT_SECOND_FLAG] >> 1) & 1;
+
+    /* Default status to success.  */
+    status =  FX_SUCCESS;
+
+    /* Is the allocation possible flag cleared? Is there any allocated cluster for this entry?  */
+    if (((work_ptr[FX_EXFAT_SECOND_FLAG] & FX_EXFAT_SECOND_FLAG_ALLOCATION_POSSIBLE_MASK) == 0) ||
+        (cluster == 0) ||
+        (data_length == 0))
+    {
+
+        /* No cluster allocated to this entry, nothing to deallocate.  */
+        return(FX_SUCCESS);
+    }
+
+    /* Calculate the number of bytes per cluster.  */
+    bytes_per_cluster = ((ULONG)media_ptr -> fx_media_bytes_per_sector) *
+        ((ULONG)media_ptr -> fx_media_sectors_per_cluster);
+
+    /* Determine how many clusters.  */
+    clusters_count =  (ULONG)((data_length + bytes_per_cluster - 1) / bytes_per_cluster - 1);
+
+    /* Initialize released cluster count to 0.  */
+    clusters_released = 0;
+
+    /* Follow the link of FAT entries.  */
+    while ((cluster >= FX_FAT_ENTRY_START) && (cluster < FX_RESERVED_1_exFAT))
+    {
+
+        /* Increment the number of clusters released.  */
+        clusters_released++;
+
+        /* Determine if the FAT chain is to be used.  */
+        if (dont_use_fat)
+        {
+
+            /* Yes, don't use the FAT chain.  */
+
+            /* Check for file size range.  */
+            if (clusters_released - 1 >= clusters_count)
+            {
+
+                /* Set the next cluster to LAST to indicate it is the last cluster.  */
+                contents =  FX_LAST_CLUSTER_exFAT;
+            }
+            else
+            {
+
+                /* The next cluster is just after the current cluster.  */
+                contents =  cluster + 1;
+            }
+        }
+        else
+        {
+
+            /* Read the current cluster entry from the FAT.  */
+            status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &contents);
+
+            /* Check the return value.  */
+            if (status != FX_SUCCESS)
+            {
+
+                /* Return the error status.  */
+                return(status);
+            }
+        }
+
+        /* Check for data corruption.  */
+        if ((cluster == contents) || (clusters_released > media_ptr -> fx_media_total_clusters))
+        {
+
+            /* Return the bad status.  */
+            return(FX_FAT_READ_ERROR);
+        }
+
+        /* Make the current cluster available.  */
+        if (!dont_use_fat)
+        {
+
+            /* Write the FAT to free the cluster.  */
+            status = _fx_utility_FAT_entry_write(media_ptr, cluster, FX_FREE_CLUSTER);
+
+            /* Check the return value.  */
+            if (status != FX_SUCCESS)
+            {
+
+                /* Return the error status.  */
+                return(status);
+            }
+        }
+
+        /* Set cluster state in the bitmap.  */
+        status = _fx_utility_exFAT_cluster_state_set(media_ptr, cluster, FX_EXFAT_BITMAP_CLUSTER_FREE);
+
+        /* Check the return status.  */
+        if (status != FX_SUCCESS)
+        {
+
+            /* Return the bad status.  */
+            return(status);
+        }
+
+        /* Setup for the next cluster.  */
+        cluster =  contents;
+    }
+
+    /* Update the free clusters in the media control block.  */
+    media_ptr -> fx_media_available_clusters =  media_ptr -> fx_media_available_clusters + clusters_released;
+
+    /* Return success.  */
+    return(FX_SUCCESS);
+}
+
+#endif /* FX_ENABLE_EXFAT */
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_cluster_state_get.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_cluster_state_get.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_cluster_state_get.c	(revision 30)
@@ -0,0 +1,157 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Utility                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+#define FX_SOURCE_CODE
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+
+
+#ifdef FX_ENABLE_EXFAT
+#include "fx_system.h"
+#include "fx_media.h"
+#include "fx_utility.h"
+#include "fx_directory_exFAT.h"
+#ifdef FX_ENABLE_FAULT_TOLERANT
+#include "fx_fault_tolerant.h"
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_utility_exFAT_cluster_state_get                 PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function gets the cluster state of exFAT volume.               */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    cluster                               Cluster number                */
+/*    cluster_state                         UCHAR pointer to store state  */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_exFAT_bitmap_cache_prepare                              */
+/*                                          Read bitmap to cache          */
+/*    _fx_fault_tolerant_read_FAT           Read FAT entry from log file  */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    FileX System Functions                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_utility_exFAT_cluster_state_get(FX_MEDIA *media_ptr, ULONG cluster, UCHAR *cluster_state)
+{
+
+UINT  status;
+UINT  bitmap_offset;
+UCHAR cluster_shift;
+UCHAR eight_clusters_block;
+#ifdef FX_ENABLE_FAULT_TOLERANT
+ULONG value;
+
+    if (media_ptr -> fx_media_fault_tolerant_enabled &&
+        (media_ptr -> fx_media_fault_tolerant_state & FX_FAULT_TOLERANT_STATE_STARTED))
+    {
+
+
+        /* Redirect this request to the log file.
+           During file or directory operations with Fault Tolerant
+           protection, intermediate operations are written to the fault
+           tolerant log file.  Therefore, FAT-entry read should search for
+           fault tolerant log before the request can be passed to normal FAT
+           entry read routine.
+         */
+        status = _fx_fault_tolerant_read_FAT(media_ptr, cluster, &value, FX_FAULT_TOLERANT_BITMAP_LOG_TYPE);
+
+        /* Return on success. */
+        if (status != FX_READ_CONTINUE)
+        {
+            *cluster_state = (UCHAR)value;
+            return(status);
+        }
+    }
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Prepare bitmap cache.  */
+    status = _fx_utility_exFAT_bitmap_cache_prepare(media_ptr, cluster);
+
+    /* Was it successful?  */
+    if (status == FX_SUCCESS)
+    {
+
+        /* Calculate the bitmap offset.  */
+        bitmap_offset = (UINT)(cluster - media_ptr -> fx_media_exfat_bitmap_cache_start_cluster) >> BITS_PER_BYTE_SHIFT;
+
+        /* Pickup the 8 cluster block.  */
+        eight_clusters_block = *(media_ptr -> fx_media_exfat_bitmap_cache + bitmap_offset);
+
+        /* Check all 8 bits for 0x00 (all clusters in the block are free).  */
+        if (eight_clusters_block == 0x00)
+        {
+
+            /* Cluster is free, return state.  */
+            *cluster_state = FX_EXFAT_BITMAP_CLUSTER_FREE;
+        }
+        /* Check all 8 bits for 0xFF (all 8 clusters are occupied).  */
+        else if (0xFF == eight_clusters_block)
+        {
+
+            /* Cluster is not free, return state.  */
+            *cluster_state = FX_EXFAT_BITMAP_CLUSTER_OCCUPIED;
+        }
+        else
+        {
+
+            /* Check bit respondent for cluster state.  */
+            cluster_shift = (UCHAR)((cluster - FX_FAT_ENTRY_START) % BITS_PER_BYTE);
+
+            *cluster_state = (eight_clusters_block >> cluster_shift) & 0x1;
+        }
+    }
+
+    /* Return status.  */
+    return(status);
+}
+
+#endif /* FX_ENABLE_EXFAT */
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_cluster_state_set.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_cluster_state_set.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_cluster_state_set.c	(revision 30)
@@ -0,0 +1,146 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Utility                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+
+
+#ifdef FX_ENABLE_EXFAT
+#include "fx_system.h"
+#include "fx_media.h"
+#include "fx_utility.h"
+#include "fx_directory_exFAT.h"
+#ifdef FX_ENABLE_FAULT_TOLERANT
+#include "fx_fault_tolerant.h"
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_utility_exFAT_cluster_state_set                 PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function sets the cluster state of exFAT volume.               */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    cluster                               Cluster number                */
+/*    new_cluster_state                     Cluster state to set          */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_exFAT_cluster_state_get   Get cluster state             */
+/*    _fx_fault_tolerant_add_bitmap_log     Add bitmap redo log           */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    FileX System Functions                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_utility_exFAT_cluster_state_set(FX_MEDIA  *media_ptr, ULONG cluster, UCHAR new_cluster_state)
+{
+
+UINT  status;
+UCHAR cluster_state;
+UINT  bitmap_offset;
+UCHAR cluster_shift;
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+    if (media_ptr -> fx_media_fault_tolerant_enabled &&
+        (media_ptr -> fx_media_fault_tolerant_state & FX_FAULT_TOLERANT_STATE_STARTED) &&
+        !(media_ptr -> fx_media_fault_tolerant_state & FX_FAULT_TOLERANT_STATE_SET_FAT_CHAIN))
+    {
+
+        /* Redirect this request to log file.
+           Under fault tolerant protection, the changes to FAT is recorded in the fault tolerant
+           log, in case the operation fails, the changes can be reverted.  */
+        return(_fx_fault_tolerant_add_bitmap_log(media_ptr, cluster, new_cluster_state));
+    }
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+    /* Get the state of the cluster?  */
+    status =  _fx_utility_exFAT_cluster_state_get(media_ptr, cluster, &cluster_state);
+
+    /* Was the state get successful?  */
+    if (status == FX_SUCCESS)
+    {
+
+        /* Is it the same state?  */
+        if (new_cluster_state != cluster_state)
+        {
+
+            /* No, we need to set the state.  */
+
+            /* Calculate the bitmap offset.  */
+            bitmap_offset =  (UINT)(cluster - media_ptr -> fx_media_exfat_bitmap_cache_start_cluster) >> BITS_PER_BYTE_SHIFT;
+
+            /* Calculate where the cluster is located.  */
+            cluster_shift =  (UCHAR)((cluster - FX_FAT_ENTRY_START) % BITS_PER_BYTE);
+
+            /* Is occupied the new state?  */
+            if (FX_EXFAT_BITMAP_CLUSTER_OCCUPIED == new_cluster_state)
+            {
+
+                /* Yes, mark this cluster as occupied.  */
+                *(media_ptr -> fx_media_exfat_bitmap_cache + bitmap_offset) = (UCHAR)(*(media_ptr -> fx_media_exfat_bitmap_cache + bitmap_offset) | (1 << cluster_shift));
+            }
+            else
+            {
+
+                /* No, mark this cluster as not occupied.  */
+                *(media_ptr -> fx_media_exfat_bitmap_cache + bitmap_offset) &=  (UCHAR)~(1 << cluster_shift);
+            }
+
+            /* Mark the cache as dirty.  */
+            media_ptr -> fx_media_exfat_bitmap_cache_dirty = FX_TRUE;
+        }
+    }
+
+    /* Return status.  */
+    return(status);
+}
+
+#endif /* FX_ENABLE_EXFAT */
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_geometry_check.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_geometry_check.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_geometry_check.c	(revision 30)
@@ -0,0 +1,320 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Utility                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+
+
+#ifdef FX_ENABLE_EXFAT
+#include "fx_system.h"
+#include "fx_media.h"
+#include "fx_utility.h"
+#include "fx_directory_exFAT.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_utility_exFAT_geometry_check                    PORTABLE C      */
+/*                                                           6.1.10       */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks exFAT geometry.                                */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    sector_buffer                         Pointer to sector buffer      */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_exFAT_system_area_checksum_verify Verify SystemArea checksum    */
+/*    _fx_utility_64_unsigned_read          Read ULONG64 from memory      */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    FileX System Functions                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*  01-31-2022     Bhupendra Naphade        Modified comment(s), replaced */
+/*                                            sector size constant,       */
+/*                                            resulting in version 6.1.10 */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_utility_exFAT_geometry_check(FX_MEDIA *media_ptr, UCHAR *sector_buffer)
+{
+
+ULONG  temp;
+ULONG  counter;
+ULONG  calculated_checksum         = 0;
+ULONG  main_system_area_checksum   = 0;
+ULONG  backup_system_area_checksum      = 0;
+ULONG  bitmap_start_sector       = 0;
+ULONG  bitmap_size_in_bytes      = 0;
+ULONG  upcase_table_start_sector  = 0;
+ULONG  upcase_table_size_in_bytes = 0;
+ULONG  upcase_table_checksum    = 0;
+UCHAR *dir_entry_ptr           = NULL;
+ULONG  dir_entries_found        = 0;
+UINT   status;
+
+
+    /* Check FAT Size.  */
+    temp = (media_ptr -> fx_media_sectors_per_FAT <<
+            media_ptr -> fx_media_exfat_bytes_per_sector_shift) >>
+        FX_EXFAT_SIZE_OF_FAT_ELEMENT_SHIFT;
+
+    /* Is the FAT capable of holding the total number of clusters?  */
+    if (temp < media_ptr -> fx_media_total_clusters)
+    {
+
+        /* No, return error.  */
+        return(FX_MEDIA_INVALID);
+    }
+
+    /* Check Cluster Heap Offset.  */
+    temp = media_ptr -> fx_media_reserved_sectors +
+        media_ptr -> fx_media_sectors_per_FAT;
+
+    /* Is the cluster heap placed after the FAT table?  */
+    if (temp > media_ptr -> fx_media_data_sector_start)
+    {
+
+        /* No, the media is invalid.  */
+        return(FX_MEDIA_INVALID);
+    }
+
+    /* Check System Area checksum.  */
+    status = _fx_utility_exFAT_system_area_checksum_verify(media_ptr,
+                                                           sector_buffer,
+                                                           FX_EXFAT_FAT_MAIN_BOOT_SECTOR_OFFSET,
+                                                           &main_system_area_checksum);
+
+    /* Is the checksum correct?  */
+    if (FX_SUCCESS != status)
+    {
+
+        /* No, return error.  */
+        return(status);
+    }
+
+    /* Check System Area checksum in backup region.  */
+    status = _fx_utility_exFAT_system_area_checksum_verify(media_ptr,
+                                                           sector_buffer,
+                                                           FX_EXFAT_FAT_BACKUP_BOOT_SECTOR_OFFSET,
+                                                           &backup_system_area_checksum);
+
+    /* Is the checksum correct?  */
+    if (FX_SUCCESS != status)
+    {
+
+        /* No, return error.  */
+        return(status);
+    }
+
+    /* Is the main system area checksum equals to the backup system area checksum?  */
+    if (main_system_area_checksum != backup_system_area_checksum)
+    {
+
+        /* No, return error.  */
+        return(FX_MEDIA_INVALID);
+    }
+
+    /* Get Bit Map and Up Case table parameters.  */
+    media_ptr -> fx_media_driver_request = FX_DRIVER_READ;
+    media_ptr -> fx_media_driver_buffer  = sector_buffer;
+    media_ptr -> fx_media_driver_sectors = 1;
+
+    counter = 0;
+
+    /* Go through the first cluster of exFAT root directory.
+       This cluster should contain BitMap allocation Dir Entry
+       and Up Case table Dir Entry.  */
+    while ((counter < media_ptr -> fx_media_sectors_per_cluster) &&
+           (EXFAT_NUM_OF_DIR_ENTRIES != dir_entries_found))
+    {
+
+        /* Build the read sector command.  */
+        media_ptr -> fx_media_driver_logical_sector = media_ptr -> fx_media_root_sector_start + counter;
+        media_ptr -> fx_media_driver_status = FX_IO_ERROR;
+
+        /* Invoke the driver to read the directory entry sector.  */
+        (media_ptr -> fx_media_driver_entry)(media_ptr);
+
+        /* Determine if the read was successful. */
+        if (FX_SUCCESS != media_ptr -> fx_media_driver_status)
+        {
+
+            /* Return the error status.  */
+            return(media_ptr -> fx_media_driver_status);
+        }
+
+        /* Move to next sector.  */
+        counter++;
+
+        /* Setup directory entry pointer to the sector buffer.  */
+        dir_entry_ptr = sector_buffer;
+
+        /* Go through the read buffer and try to find BitMap table and UpCase table dir entries.  */
+        while (dir_entry_ptr < (media_ptr -> fx_media_memory_buffer +
+                                media_ptr -> fx_media_bytes_per_sector) &&
+               (EXFAT_NUM_OF_DIR_ENTRIES != dir_entries_found))
+        {
+
+            /* Check if we found the bitmap table.  */
+            if (FX_EXFAT_DIR_ENTRY_TYPE_ALLOCATION_BITMAP == dir_entry_ptr[FX_EXFAT_ENTRY_TYPE])
+            {
+
+                /* Calculate BitMap table start sector.  */
+                bitmap_start_sector  = media_ptr -> fx_media_data_sector_start +
+                    ((_fx_utility_32_unsigned_read(&dir_entry_ptr[FX_EXFAT_FIRST_CLUSTER]) -
+                      FX_FAT_ENTRY_START) << media_ptr -> fx_media_exfat_sector_per_clusters_shift);
+
+                bitmap_size_in_bytes = (ULONG)_fx_utility_64_unsigned_read(&dir_entry_ptr[FX_EXFAT_DATA_LENGTH]);
+
+                dir_entries_found++;
+            }
+            /* Check if we found the upcase table.  */
+            else if (FX_EXFAT_DIR_ENTRY_TYPE_UP_CASE_TABLE == dir_entry_ptr[FX_EXFAT_ENTRY_TYPE])
+            {
+
+                /* Calculate UpCase table start sector.  */
+                upcase_table_start_sector  = media_ptr -> fx_media_data_sector_start +
+                    ((_fx_utility_32_unsigned_read(&dir_entry_ptr[FX_EXFAT_FIRST_CLUSTER]) -
+                      FX_FAT_ENTRY_START) << media_ptr -> fx_media_exfat_sector_per_clusters_shift);
+
+                upcase_table_checksum    = _fx_utility_32_unsigned_read(&dir_entry_ptr[FX_EXFAT_UP_CASE_TABLE_CHECK_SUM]);
+                upcase_table_size_in_bytes = (ULONG)_fx_utility_64_unsigned_read(&dir_entry_ptr[FX_EXFAT_DATA_LENGTH]);
+
+                dir_entries_found++;
+            }
+
+            /* Move to next directory entry.  */
+            dir_entry_ptr += FX_EXFAT_DIR_ENTRY_SIZE;
+        }
+    }
+
+    /* Validate the directory entries.  */
+    if ((0 == bitmap_start_sector)  ||
+        (0 == bitmap_size_in_bytes) ||
+        (0 == upcase_table_start_sector) ||
+        (0 == upcase_table_checksum) ||
+        (0 == upcase_table_size_in_bytes))
+    {
+
+        /* Directory entries have invalid value, return error.  */
+        return(FX_MEDIA_INVALID);
+    }
+
+    /* Check Bit Map size.  */
+    if (media_ptr -> fx_media_total_clusters >
+        /* 1 Byte = > map to 8 clusters.  */
+        (bitmap_size_in_bytes << BITS_PER_BYTE_SHIFT))
+    {
+
+        /* Bitmap size is not correct, return error.  */
+        return(FX_MEDIA_INVALID);
+    }
+
+    /* Check Up Case Table checksum.  */
+    calculated_checksum = 0;
+
+    /* Build driver request to read the upcase table.  */
+    media_ptr -> fx_media_driver_logical_sector = upcase_table_start_sector;
+
+    /* Loop to calculate upcase table checksum.  */
+    while (upcase_table_size_in_bytes > 0)
+    {
+
+        /* Build driver request.  */
+        media_ptr -> fx_media_driver_status = FX_IO_ERROR;
+
+        /* Invoke the driver to read one sector.  */
+        (media_ptr -> fx_media_driver_entry)(media_ptr);
+
+        /* Determine if the read was successful. */
+        if (FX_SUCCESS != media_ptr -> fx_media_driver_status)
+        {
+
+            /* Return the error status.  */
+            return(media_ptr -> fx_media_driver_status);
+        }
+
+        /* Determine the processing size.  */
+        if (upcase_table_size_in_bytes >= media_ptr -> fx_media_bytes_per_sector)
+        {
+
+            /* Process one sector at a time.  */
+            temp = media_ptr -> fx_media_bytes_per_sector;
+            upcase_table_size_in_bytes -= media_ptr -> fx_media_bytes_per_sector;
+            media_ptr -> fx_media_driver_logical_sector++;
+        }
+        else
+        {
+
+            /* Remaining data is less than one sector, process all the remaining bytes.  */
+            temp = upcase_table_size_in_bytes;
+            upcase_table_size_in_bytes = 0;
+        }
+
+        /* Calculate checksum.  */
+        for (counter = 0; counter < temp; counter++)
+        {
+
+            /* Calculate the checksum using the algorithm specified in the specification.  */
+            /* Right rotate the checksum by one bit position and add the data.  */
+            calculated_checksum = ((calculated_checksum >> 1) | (calculated_checksum << 31)) + (ULONG)sector_buffer[counter];
+        }
+    }
+
+    /* Verify the checksum.  */
+    if (calculated_checksum != upcase_table_checksum)
+    {
+
+        /* Checksum not correct, return error.  */
+        return(FX_MEDIA_INVALID);
+    }
+
+    /* Return success.  */
+    return(FX_SUCCESS);
+}
+
+#endif /* FX_ENABLE_EXFAT */
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_name_hash_get.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_name_hash_get.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_name_hash_get.c	(revision 30)
@@ -0,0 +1,109 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Utility                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+
+
+#ifdef FX_ENABLE_EXFAT
+#include "fx_directory_exFAT.h"
+#include "fx_utility.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_utility_exFAT_name_hash_get                     PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function returns hash of ASCII file name.                      */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    name                                  ASCII file name               */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return name hash                                                    */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    _fx_directory_exFAT_entry_write                                     */
+/*    _fx_directory_rename                                                */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+USHORT  _fx_utility_exFAT_name_hash_get(CHAR *name)
+{
+
+USHORT hash;
+
+
+    /* Initialize hash to 0. */
+    hash = 0;
+
+    /* Is there a name?  */
+    if (!name)
+    {
+
+        /* No, just return 0.  */
+        return(0);
+    }
+
+    /* Create hash for name.  */
+    while (*name)
+    {
+
+        /* Compute hash.  */
+        hash = (USHORT)(((hash >> 1) | (hash << 15)) + _fx_utility_exFAT_upcase_get((USHORT)*name));
+        hash = (USHORT)((hash >> 1) | (hash << 15));
+
+        /* Move to next character of name.  */
+        name++;
+    }
+
+    /* Return the hash.  */
+    return(hash);
+}
+
+#endif /* FX_ENABLE_EXFAT */
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_size_calculate.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_size_calculate.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_size_calculate.c	(revision 30)
@@ -0,0 +1,157 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Utility                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+
+
+#ifdef FX_ENABLE_EXFAT
+#include "fx_system.h"
+#include "fx_media.h"
+#include "fx_utility.h"
+#include "fx_directory_exFAT.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_utility_exFAT_size_calculate                    PORTABLE C      */
+/*                                                           6.1.10       */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function calculates FAT size according to given parameters.    */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    boundary_unit                         Data area alignment in sectors*/
+/*    size_in_sectors                       Partition size in sectors     */
+/*    sectors_per_cluster                   Number of sectors per cluster */
+/*    sectors_per_fat_ptr                   Pointer to sector per FAT     */
+/*    fat_offset_ptr                        Pointer to offset of FAT      */
+/*    cluster_heap_offset_ptr               Pointer to offset of cluster  */
+/*                                            heap                        */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    NONE                                                                */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    _fx_media_exFAT_format                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*  03-02-2021     William E. Lamie         Modified comment(s), fixed    */
+/*                                            FAT size calculation issue, */
+/*                                            resulting in version 6.1.5  */
+/*  01-31-2022     Bhupendra Naphade        Modified comment(s), and      */
+/*                                            replaced sector size        */
+/*                                            constant,                   */
+/*                                            resulting in version 6.1.10 */
+/*                                                                        */
+/**************************************************************************/
+VOID  _fx_utility_exFAT_size_calculate(UINT bytes_per_sector, ULONG boundary_unit, ULONG64 size_in_sectors, ULONG sectors_per_cluster,
+                                       ULONG *sectors_per_fat_ptr, ULONG *fat_offset_ptr, ULONG *cluster_heap_offset_ptr)
+{
+
+ULONG   system_area_sectors = 0; /* Number of sectors for exFTA system area (from partition begining) */
+ULONG64 total_cluster_heap_sectors;
+
+
+    /* Align the boundary unit. If zero supplied, then set to default value.  */
+    boundary_unit = ALIGN_UP(boundary_unit, 128);
+
+    /* Align System Area according Boundary Unit.  */
+    while (system_area_sectors < (EXFAT_BOOT_REGION_SIZE + EXFAT_MIN_NUM_OF_RESERVED_SECTORS))
+    {
+
+        system_area_sectors += boundary_unit;
+    }
+
+    /* Save preliminary FAT offset.  */
+    *fat_offset_ptr = system_area_sectors;
+
+    /* Save preliminary Clusters Heap offset.  */
+    *cluster_heap_offset_ptr = *fat_offset_ptr;
+
+    /* Calculate number of available sectors without system sectors.  */
+    total_cluster_heap_sectors = size_in_sectors - system_area_sectors;
+
+    /* Calculate required number of FAT sectors.  */
+    *sectors_per_fat_ptr = (ULONG)DIVIDE_TO_CEILING(((total_cluster_heap_sectors / sectors_per_cluster) * EXFAT_FAT_BITS),
+                                                    (bytes_per_sector * BITS_PER_BYTE));
+
+    *sectors_per_fat_ptr = ALIGN_UP(*sectors_per_fat_ptr, boundary_unit >> 1);
+
+    /* Check is it possible to allocate FAT inside calculated System Area sectors or not.  */
+    if (system_area_sectors >
+        (EXFAT_BOOT_REGION_SIZE +
+         EXFAT_MIN_NUM_OF_RESERVED_SECTORS + *sectors_per_fat_ptr))
+    {
+
+        /* We able allocate FAT inside calculated logical_system_area_sectors.  */
+        *fat_offset_ptr -= *sectors_per_fat_ptr;
+    }
+    else /* Recalculate FAT size since System Area will be increased on FAT size.  */
+    {
+        do
+        {
+
+            /* Increase System Area size on number of FAT sectors aligned according BU.  */
+            system_area_sectors = *fat_offset_ptr + *sectors_per_fat_ptr;
+
+            /* Decrease sectors available for clusters heap.  */
+            total_cluster_heap_sectors = size_in_sectors - system_area_sectors;
+
+            /* Re-calculate number of sectors per FAT.  */
+            *sectors_per_fat_ptr = (ULONG)DIVIDE_TO_CEILING(((total_cluster_heap_sectors / sectors_per_cluster) * EXFAT_FAT_BITS),
+                                                            (bytes_per_sector * BITS_PER_BYTE));
+
+            *sectors_per_fat_ptr = ALIGN_UP(*sectors_per_fat_ptr, boundary_unit >> 1);
+
+            /* Increase Cluster Heap offset according new FAT size.  */
+            *cluster_heap_offset_ptr = *fat_offset_ptr + *sectors_per_fat_ptr;
+
+        /* Loop until we find a FAT size that can hold all the clusters.  */
+        }while (*sectors_per_fat_ptr * bytes_per_sector * BITS_PER_BYTE / EXFAT_FAT_BITS < ((size_in_sectors - *cluster_heap_offset_ptr) / sectors_per_cluster));
+    }
+}
+
+#endif /* FX_ENABLE_EXFAT */
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_system_area_checksum_verify.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_system_area_checksum_verify.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_system_area_checksum_verify.c	(revision 30)
@@ -0,0 +1,216 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Utility                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+
+
+#ifdef FX_ENABLE_EXFAT
+#include "fx_system.h"
+#include "fx_media.h"
+#include "fx_utility.h"
+#include "fx_directory_exFAT.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_utility_exFAT_system_area_checksum_verify       PORTABLE C      */
+/*                                                           6.1.10       */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks exFAT geometry.                                */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    sector_buffer                         Pointer to sector buffer      */
+/*    boot_sector_offset                    Offset of boot sector         */
+/*    calculated_checksum                   Pointer to checksum value     */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    Media driver                                                        */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    FileX System Functions                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*  01-31-2022     Bhupendra Naphade        Modified comment(s), replaced */
+/*                                            sector size constant,       */
+/*                                            resulting in version 6.1.10 */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_utility_exFAT_system_area_checksum_verify(FX_MEDIA *media_ptr, UCHAR *sector_buffer,
+                                                    ULONG boot_sector_offset, ULONG *calculated_checksum)
+{
+
+ULONG temp;
+ULONG counter;
+
+
+    /* Clear the checksum for checksum calculation.  */
+    *calculated_checksum =  0;
+
+    /* Prepare driver request.  */
+    media_ptr -> fx_media_driver_request =          FX_DRIVER_READ;
+    media_ptr -> fx_media_driver_buffer  =          sector_buffer;
+    media_ptr -> fx_media_driver_sectors =          1;
+    media_ptr -> fx_media_driver_status         =   FX_IO_ERROR;
+    media_ptr -> fx_media_driver_logical_sector =   boot_sector_offset;
+
+    /* Call driver.  */
+    (media_ptr -> fx_media_driver_entry)(media_ptr);
+
+    /* Check driver status.  */
+    if (FX_SUCCESS != media_ptr -> fx_media_driver_status)
+    {
+
+        /* Error, return error status.  */
+        return(media_ptr -> fx_media_driver_status);
+    }
+
+    /* Loop to calculate Boot Sector checksum.  */
+    for (temp = 0; temp < media_ptr -> fx_media_bytes_per_sector; temp++)
+    {
+
+        /* Check if it is VolumeFlags or PercentInUse.  */
+        if ((FX_EF_VOLUME_FLAGS     == temp) ||
+            (FX_EF_VOLUME_FLAGS + 1 == temp) ||
+            (FX_EF_PERCENT_IN_USE   == temp))
+        {
+
+            /* Skip these fields in checksum calculation.  */
+            continue;
+        }
+
+        /* Calculate the checksum using the algorithm specified in the specification.  */
+        /* Right rotate the checksum by one bit position and add the data.  */
+        *calculated_checksum = ((*calculated_checksum >> 1) | (*calculated_checksum << 31)) + (ULONG)sector_buffer[temp];
+    }
+
+    /* Map to Extended boot Sector.  */
+    media_ptr -> fx_media_driver_logical_sector++;
+
+    /* Read System Area from Extended Boot Sector
+       and calculate checksum.  */
+    for (temp = FX_EXFAT_FAT_EXT_BOOT_SECTOR_OFFSET; FX_EXFAT_FAT_CHECK_SUM_OFFSET > temp; temp++)
+    {
+
+        /* Build driver request.  */
+        media_ptr -> fx_media_driver_status = FX_IO_ERROR;
+
+        /* Read next sector.  */
+        (media_ptr -> fx_media_driver_entry)(media_ptr);
+
+        /* Check status.  */
+        if (FX_SUCCESS != media_ptr -> fx_media_driver_status)
+        {
+
+            /* Clear checksum.  */
+            *calculated_checksum = 0;
+
+            /* Error, return error status.  */
+            return(media_ptr -> fx_media_driver_status);
+        }
+
+        /* Move to next logical sector.  */
+        media_ptr -> fx_media_driver_logical_sector++;
+
+        /* Check Sector Signature.  */
+        if (((sector_buffer[media_ptr -> fx_media_bytes_per_sector - 2] != FX_SIG_BYTE_1) ||
+             (sector_buffer[media_ptr -> fx_media_bytes_per_sector - 1] != FX_SIG_BYTE_2)) &&
+            (FX_EXFAT_FAT_OEM_PARAM_OFFSET > temp))
+        {
+
+            /* Clear checksum.  */
+            *calculated_checksum =  0;
+
+            /* Error, return error status.  */
+            return(FX_MEDIA_INVALID);
+        }
+
+        /* Loop to calculate the checksum.  */
+        for (counter = 0; counter < media_ptr -> fx_media_bytes_per_sector; counter++)
+        {
+
+            /* Calculate the checksum using the algorithm specified in the specification.  */
+            /* Right rotate the checksum by one bit position and add the data.  */
+            *calculated_checksum = ((*calculated_checksum >> 1) | (*calculated_checksum << 31)) + (ULONG)sector_buffer[counter];
+        }
+    }
+
+    /* Build driver request.  */
+    media_ptr -> fx_media_driver_status = FX_IO_ERROR;
+
+    /* Read stored checksum.  */
+    (media_ptr -> fx_media_driver_entry)(media_ptr);
+
+    /* Determine if the read was successful.  */
+    if (FX_SUCCESS != media_ptr -> fx_media_driver_status)
+    {
+
+        /* Not successful, return error status.  */
+        return(media_ptr -> fx_media_driver_status);
+    }
+
+    /* Loop to check sector content.  */
+    for (counter = 0; counter < media_ptr -> fx_media_bytes_per_sector; counter += sizeof(ULONG))
+    {
+
+        /* Read a 32 bit value from sector buffer.  */
+        temp = _fx_utility_32_unsigned_read(&sector_buffer[counter]);
+
+        /* Compare the read value with the caclulated checksum.  */
+        if (temp != *calculated_checksum)
+        {
+
+            /* Not equal, checksum verify failed.  */
+            return(FX_MEDIA_INVALID);
+        }
+    }
+
+    /* Return success.  */
+    return(FX_SUCCESS);
+}
+
+#endif /* FX_ENABLE_EXFAT */
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_system_area_checksum_write.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_system_area_checksum_write.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_system_area_checksum_write.c	(revision 30)
@@ -0,0 +1,115 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Utility                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+
+
+#ifdef FX_ENABLE_EXFAT
+#include "fx_system.h"
+#include "fx_media.h"
+#include "fx_utility.h"
+#include "fx_directory_exFAT.h"
+
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_utility_exFAT_system_area_checksum_write        PORTABLE C      */
+/*                                                           6.1.10       */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function writes system area checksum.                          */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    sector_buffer                         Pointer to sector buffer      */
+/*    system_area_checksum_ptr              Pointer to checksum value     */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_exFAT_system_sector_write Write a format sector         */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    FileX System Functions                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*  01-31-2022     Bhupendra Naphade        Modified comment(s), replaced */
+/*                                            sector size constant,       */
+/*                                            resulting in version 6.1.10 */
+/*                                                                        */
+/**************************************************************************/
+UINT _fx_utility_exFAT_system_area_checksum_write(FX_MEDIA *media_ptr, UCHAR *sector_buffer, ULONG *system_area_checksum_ptr)
+{
+
+UINT index;
+
+    /* Fill buffer by check sum.  */
+    for (index = 0; index < media_ptr -> fx_media_bytes_per_sector;)
+    {
+        _fx_utility_32_unsigned_write(&sector_buffer[index],
+                                      *system_area_checksum_ptr);
+
+        index += sizeof(*system_area_checksum_ptr);
+    }
+
+    /* Write Check Sum for Main System area.  */
+    _fx_utility_exFAT_system_sector_write(media_ptr, sector_buffer,
+                                          FX_EXFAT_FAT_MAIN_SYSTEM_AREA_SIZE - 1,
+                                          1, FX_BOOT_SECTOR);
+
+    if (FX_SUCCESS != media_ptr -> fx_media_driver_status)
+    {
+        return(media_ptr -> fx_media_driver_status);
+    }
+
+    /* Write Check Sum for BackUp System area.  */
+    _fx_utility_exFAT_system_sector_write(media_ptr, sector_buffer,
+                                          FX_EXFAT_FAT_MAIN_SYSTEM_AREA_SIZE - 1 + FX_EXFAT_FAT_MAIN_SYSTEM_AREA_SIZE,
+                                          1, FX_BOOT_SECTOR);
+
+    return(media_ptr -> fx_media_driver_status);
+}
+
+#endif /* FX_ENABLE_EXFAT */
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_system_area_format.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_system_area_format.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_system_area_format.c	(revision 30)
@@ -0,0 +1,237 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Utility                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+
+
+#ifdef FX_ENABLE_EXFAT
+#include "fx_utility.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_utility_exFAT_system_area_format                PORTABLE C      */
+/*                                                           6.1.10       */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function formats system area for exFAT.                        */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Pointer to media control block*/
+/*    boundary_unit                         Data area alignment in sectors*/
+/*    system_area_checksum_ptr              Pointer system area checksum  */
+/*    memory_ptr                            Pointer to work buffer        */
+/*    memory_size                           Size of the work buffer       */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    Completion Status                                                   */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_memory_set                Set memory                    */
+/*    _fx_utility_exFAT_system_sector_write Write exFAT format sector     */
+/*    _fx_utility_32_unsigned_write         Write 32-bit word             */
+/*    _fx_utility_16_unsigned_write         Write 16-bit word             */
+/*                                                                        */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    _fx_media_exFAT_format                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*  01-31-2022     Bhupendra Naphade        Modified comment(s), replaced */
+/*                                            sector size constant,       */
+/*                                            resulting in version 6.1.10 */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_utility_exFAT_system_area_format(FX_MEDIA *media_ptr, ULONG boundary_unit,
+                                           ULONG *system_area_checksum_ptr,
+                                           UCHAR *memory_ptr, UINT memory_size)
+{
+
+UINT   counter;
+UINT   i;
+UINT   sector_offset   = 0;
+UINT   status;
+UCHAR *system_area_buffer  = NULL;
+
+
+    /* Is the memory size large enough?  */
+    if (memory_size < media_ptr -> fx_media_bytes_per_sector)
+    {
+
+        /* No, return an error.  */
+        return(FX_PTR_ERROR);
+    }
+
+    /* Setup pointer to system area buffer.  */
+    system_area_buffer =  memory_ptr;
+
+    /* Align the boundary unit.  */
+    boundary_unit = ALIGN_UP(boundary_unit, 128);
+
+    /* Clear work buffer.  */
+    _fx_utility_memory_set(system_area_buffer, 0x00, media_ptr -> fx_media_bytes_per_sector);
+
+    /* Add signature to System area sectors without boot, OEM, reserved and checksum sector.  */
+    system_area_buffer[media_ptr -> fx_media_bytes_per_sector - 2] =  FX_SIG_BYTE_1;
+    system_area_buffer[media_ptr -> fx_media_bytes_per_sector - 1] =  FX_SIG_BYTE_2;
+
+    /* Loop to write all the extended boot sectors.  */
+    for (counter = 0; counter < (FX_EXFAT_FAT_OEM_PARAM_OFFSET - FX_EXFAT_FAT_EXT_BOOT_SECTOR_OFFSET); counter++)
+    {
+
+        /* Loop to calculate the checksum for System Area  */
+        for (i = 0; i < media_ptr -> fx_media_bytes_per_sector; i++)
+        {
+
+            /* Calculate the checksum using the algorithm specified in the specification.  */
+            /* Right rotate the checksum by one bit position and add the data.  */
+            *system_area_checksum_ptr = ((*system_area_checksum_ptr >> 1) | (*system_area_checksum_ptr << 31)) +
+                (ULONG)system_area_buffer[i];
+        }
+
+        /* Write out the extended boot sector.  */
+        status = _fx_utility_exFAT_system_sector_write(media_ptr, system_area_buffer,
+                                                       (ULONG64) (FX_EXFAT_FAT_EXT_BOOT_SECTOR_OFFSET + counter),
+                                                       ((ULONG) 1), FX_BOOT_SECTOR);
+
+
+        /* Determine if the write was successful.  */
+        if (status != FX_SUCCESS)
+        {
+            return(status);
+        }
+
+        /* Write out the extended boot sector in the backup region.  */
+        status = _fx_utility_exFAT_system_sector_write(media_ptr, system_area_buffer,
+                                                       (ULONG64) (FX_EXFAT_FAT_EXT_BOOT_SECTOR_OFFSET + counter + FX_EXFAT_FAT_MAIN_SYSTEM_AREA_SIZE),
+                                                       ((ULONG) 1), FX_BOOT_SECTOR);
+
+        /* Determine if the write was successful.  */
+        if (status != FX_SUCCESS)
+        {
+            return(status);
+        }
+    }
+
+    /* Add OEM - Flash parameters.  */
+    system_area_buffer[media_ptr -> fx_media_bytes_per_sector - 2] = 0;
+    system_area_buffer[media_ptr -> fx_media_bytes_per_sector - 1] = 0;
+
+    /* GUID 0A0C7E46-3399-4021-90C8-FA6D389C4BA2 */
+    _fx_utility_32_unsigned_write(&(system_area_buffer[sector_offset]), 0x0A0C7E46);
+    _fx_utility_16_unsigned_write(&(system_area_buffer[sector_offset + 4]), 0x3399);
+    _fx_utility_16_unsigned_write(&(system_area_buffer[sector_offset + 6]), 0x4021);
+    system_area_buffer[sector_offset +  8] = 0x90; system_area_buffer[sector_offset +  9] = 0xC8;
+    system_area_buffer[sector_offset + 10] = 0xFA; system_area_buffer[sector_offset + 11] = 0x6D;
+    system_area_buffer[sector_offset + 12] = 0x38; system_area_buffer[sector_offset + 13] = 0x9C;
+    system_area_buffer[sector_offset + 14] = 0x4B; system_area_buffer[sector_offset + 15] = 0xA2;
+
+    /* Add EraseBlockSize.  */
+    _fx_utility_32_unsigned_write(&(system_area_buffer[sector_offset + 16]), boundary_unit / 2);
+
+    /* Write out the OEM parameters sector.  */
+    status = _fx_utility_exFAT_system_sector_write(media_ptr, system_area_buffer,
+                                                   FX_EXFAT_FAT_OEM_PARAM_OFFSET,
+                                                   1, FX_BOOT_SECTOR);
+
+    /* Determine if the write was successful.  */
+    if (status != FX_SUCCESS)
+    {
+        return(status);
+    }
+
+    /* Write out the OEM parameters sector in the backup region.  */
+    status = _fx_utility_exFAT_system_sector_write(media_ptr, system_area_buffer,
+                                                   FX_EXFAT_FAT_OEM_PARAM_OFFSET + FX_EXFAT_FAT_MAIN_SYSTEM_AREA_SIZE,
+                                                   1, FX_BOOT_SECTOR);
+
+    /* Determine if the write was successful.  */
+    if (status != FX_SUCCESS)
+    {
+        return(status);
+    }
+
+    /* Loop to calculate checksum for System Area.  */
+    for (counter = 0; counter < media_ptr -> fx_media_bytes_per_sector; counter++)
+    {
+
+        /* Calculate the checksum using the algorithm specified in the specification.  */
+        /* Right rotate the checksum by one bit position and add the data.  */
+        *system_area_checksum_ptr = ((*system_area_checksum_ptr >> 1) | (*system_area_checksum_ptr << 31)) +
+            (ULONG)system_area_buffer[counter];
+    }
+
+    /* Clear work buffer.  */
+    _fx_utility_memory_set(system_area_buffer, 0x00, media_ptr -> fx_media_bytes_per_sector);
+
+    /* Loop to calculate checksum for System Area.  */
+    for (counter = 0; counter < media_ptr -> fx_media_bytes_per_sector; counter++)
+    {
+
+        /* Calculate the checksum using the algorithm specified in the specification.  */
+        /* Right rotate the checksum by one bit position and add the data.  */
+        *system_area_checksum_ptr = ((*system_area_checksum_ptr >> 1) | (*system_area_checksum_ptr << 31)) +
+            (ULONG)system_area_buffer[counter];
+    }
+
+    /* Write out the boot checksum sector.  */
+    status = _fx_utility_exFAT_system_sector_write(media_ptr, system_area_buffer,
+                                                   FX_EXFAT_FAT_OEM_PARAM_OFFSET + 1,
+                                                   1, FX_BOOT_SECTOR);
+
+    /* Determine if the write was successful.  */
+    if (status != FX_SUCCESS)
+    {
+        return(status);
+    }
+
+    /* Write out the boot checksum sector in the backup region.  */
+    status = _fx_utility_exFAT_system_sector_write(media_ptr, system_area_buffer,
+                                                   FX_EXFAT_FAT_OEM_PARAM_OFFSET + 1 + FX_EXFAT_FAT_MAIN_SYSTEM_AREA_SIZE,
+                                                   1, FX_BOOT_SECTOR);
+
+    /* Return completion status.  */
+    return(status);
+}
+
+#endif
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_system_sector_write.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_system_sector_write.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_system_sector_write.c	(revision 30)
@@ -0,0 +1,104 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Utility                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+#include "fx_api.h"
+#include "fx_utility.h"
+
+
+#ifdef FX_ENABLE_EXFAT
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_utility_exFAT_system_sector_write               PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function writes a sector for exFAT format.                     */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Pointer to media control block*/
+/*    data_buffer                           Pointer to sector data buffer */
+/*    logical_sector                        Sector number to write        */
+/*    sector_count                          Number of sectors to write    */
+/*    sector_type                           Sector type of the sector to  */
+/*                                            be written                  */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    Completion Status                                                   */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    Media driver                                                        */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    _fx_media_exFAT_format                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_utility_exFAT_system_sector_write(FX_MEDIA *media_ptr, UCHAR *data_buffer,
+                                            ULONG64 logical_sector, ULONG sector_count,
+                                            ULONG sector_type)
+{
+
+
+    /* Build sector write command.  */
+#ifdef FX_DRIVER_USE_64BIT_LBA
+    media_ptr -> fx_media_driver_logical_sector =   logical_sector;
+#else
+    media_ptr -> fx_media_driver_logical_sector =   (ULONG)logical_sector;
+#endif
+    media_ptr -> fx_media_driver_request =          FX_DRIVER_WRITE;
+    media_ptr -> fx_media_driver_sectors =          sector_count;
+    media_ptr -> fx_media_driver_system_write =     FX_TRUE;
+    media_ptr -> fx_media_driver_sector_type =      sector_type;
+    media_ptr -> fx_media_driver_buffer =           data_buffer;
+    media_ptr -> fx_media_driver_status =           FX_IO_ERROR;
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_WRITE, media_ptr, media_ptr -> fx_media_driver_logical_sector, 1, sector_type, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+    /* Write out the sector.  */
+    (media_ptr -> fx_media_driver_entry)(media_ptr);
+
+    /* Return status.  */
+    return(media_ptr -> fx_media_driver_status);
+}
+
+#endif
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_unicode_name_hash_get.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_unicode_name_hash_get.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_unicode_name_hash_get.c	(revision 30)
@@ -0,0 +1,116 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Utility                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+
+
+#ifdef FX_ENABLE_EXFAT
+#include "fx_directory_exFAT.h"
+#include "fx_utility.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_utility_exFAT_unicode_name_hash_get             PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function returns hash of Unicode file name.                    */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    unicode_name                          Unicode file name             */
+/*    unicode_length                        Unicode name length           */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return name hash                                                    */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    _fx_directory_exFAT_entry_write                                     */
+/*    _fx_directory_rename                                                */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+USHORT  _fx_utility_exFAT_unicode_name_hash_get(CHAR *unicode_name, ULONG unicode_length)
+{
+
+USHORT hash;
+USHORT upcased_char;
+
+    /* Initialize hash to 0. */
+    hash = 0;
+
+    /* Is there a name?  */
+    if (!unicode_name)
+    {
+
+        /* No, just return 0.  */
+        return(0);
+    }
+
+    /* Create hash for name.  */
+    while (unicode_length)
+    {
+
+        /* Get up-cased character.  */
+        upcased_char = (USHORT)(_fx_utility_exFAT_upcase_get((USHORT)(*unicode_name | (*(unicode_name + 1) << 8))));
+
+        /* Compute hash.  */
+        hash = (USHORT)(((hash >> 1) | (hash << 15)) + (upcased_char & 0xFF));
+        hash = (USHORT)(((hash >> 1) | (hash << 15)) + (upcased_char >> 8));
+
+        /* Move to next character of the Unicode name.  */
+        unicode_name = unicode_name + 2;
+
+        /* Decrement length.  */
+        unicode_length--;
+    }
+
+    /* Return the hash.  */
+    return(hash);
+}
+
+#endif /* FX_ENABLE_EXFAT */
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_upcase_table.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_upcase_table.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_exFAT_upcase_table.c	(revision 30)
@@ -0,0 +1,261 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Utility                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_utility.h"
+
+
+#ifdef FX_ENABLE_EXFAT
+#include "fx_directory_exFAT.h"
+
+
+/* Define upcase table used by exFAT.  */
+static const USHORT _fx_utility_exFAT_upcase_table_differential[] =
+{
+
+    /* 0x0060 - 0x007f, offset 0  */
+    0x0060, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+    0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
+
+    /* 0x00e0 - 0x029f, offset 32  */
+    0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
+    0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00f7, 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x0178,
+    0x0100, 0x0100, 0x0102, 0x0102, 0x0104, 0x0104, 0x0106, 0x0106, 0x0108, 0x0108, 0x010a, 0x010a, 0x010c, 0x010c, 0x010e, 0x010e,
+    0x0110, 0x0110, 0x0112, 0x0112, 0x0114, 0x0114, 0x0116, 0x0116, 0x0118, 0x0118, 0x011a, 0x011a, 0x011c, 0x011c, 0x011e, 0x011e,
+    0x0120, 0x0120, 0x0122, 0x0122, 0x0124, 0x0124, 0x0126, 0x0126, 0x0128, 0x0128, 0x012a, 0x012a, 0x012c, 0x012c, 0x012e, 0x012e,
+    0x0130, 0x0131, 0x0132, 0x0132, 0x0134, 0x0134, 0x0136, 0x0136, 0x0138, 0x0139, 0x0139, 0x013b, 0x013b, 0x013d, 0x013d, 0x013f,
+    0x013f, 0x0141, 0x0141, 0x0143, 0x0143, 0x0145, 0x0145, 0x0147, 0x0147, 0x0149, 0x014a, 0x014a, 0x014c, 0x014c, 0x014e, 0x014e,
+    0x0150, 0x0150, 0x0152, 0x0152, 0x0154, 0x0154, 0x0156, 0x0156, 0x0158, 0x0158, 0x015a, 0x015a, 0x015c, 0x015c, 0x015e, 0x015e,
+    0x0160, 0x0160, 0x0162, 0x0162, 0x0164, 0x0164, 0x0166, 0x0166, 0x0168, 0x0168, 0x016a, 0x016a, 0x016c, 0x016c, 0x016e, 0x016e,
+    0x0170, 0x0170, 0x0172, 0x0172, 0x0174, 0x0174, 0x0176, 0x0176, 0x0178, 0x0179, 0x0179, 0x017b, 0x017b, 0x017d, 0x017d, 0x017f,
+    0x0243, 0x0181, 0x0182, 0x0182, 0x0184, 0x0184, 0x0186, 0x0187, 0x0187, 0x0189, 0x018a, 0x018b, 0x018b, 0x018d, 0x018e, 0x018f,
+    0x0190, 0x0191, 0x0191, 0x0193, 0x0194, 0x01f6, 0x0196, 0x0197, 0x0198, 0x0198, 0x023d, 0x019b, 0x019c, 0x019d, 0x0220, 0x019f,
+    0x01a0, 0x01a0, 0x01a2, 0x01a2, 0x01a4, 0x01a4, 0x01a6, 0x01a7, 0x01a7, 0x01a9, 0x01aa, 0x01ab, 0x01ac, 0x01ac, 0x01ae, 0x01af,
+    0x01af, 0x01b1, 0x01b2, 0x01b3, 0x01b3, 0x01b5, 0x01b5, 0x01b7, 0x01b8, 0x01b8, 0x01ba, 0x01bb, 0x01bc, 0x01bc, 0x01be, 0x01f7,
+    0x01c0, 0x01c1, 0x01c2, 0x01c3, 0x01c4, 0x01c5, 0x01c4, 0x01c7, 0x01c8, 0x01c7, 0x01ca, 0x01cb, 0x01ca, 0x01cd, 0x01cd, 0x01cf,
+    0x01cf, 0x01d1, 0x01d1, 0x01d3, 0x01d3, 0x01d5, 0x01d5, 0x01d7, 0x01d7, 0x01d9, 0x01d9, 0x01db, 0x01db, 0x018e, 0x01de, 0x01de,
+    0x01e0, 0x01e0, 0x01e2, 0x01e2, 0x01e4, 0x01e4, 0x01e6, 0x01e6, 0x01e8, 0x01e8, 0x01ea, 0x01ea, 0x01ec, 0x01ec, 0x01ee, 0x01ee,
+    0x01f0, 0x01f1, 0x01f2, 0x01f1, 0x01f4, 0x01f4, 0x01f6, 0x01f7, 0x01f8, 0x01f8, 0x01fa, 0x01fa, 0x01fc, 0x01fc, 0x01fe, 0x01fe,
+    0x0200, 0x0200, 0x0202, 0x0202, 0x0204, 0x0204, 0x0206, 0x0206, 0x0208, 0x0208, 0x020a, 0x020a, 0x020c, 0x020c, 0x020e, 0x020e,
+    0x0210, 0x0210, 0x0212, 0x0212, 0x0214, 0x0214, 0x0216, 0x0216, 0x0218, 0x0218, 0x021a, 0x021a, 0x021c, 0x021c, 0x021e, 0x021e,
+    0x0220, 0x0221, 0x0222, 0x0222, 0x0224, 0x0224, 0x0226, 0x0226, 0x0228, 0x0228, 0x022a, 0x022a, 0x022c, 0x022c, 0x022e, 0x022e,
+    0x0230, 0x0230, 0x0232, 0x0232, 0x0234, 0x0235, 0x0236, 0x0237, 0x0238, 0x0239, 0x2c65, 0x023b, 0x023b, 0x023d, 0x2c66, 0x023f,
+    0x0240, 0x0241, 0x0241, 0x0243, 0x0244, 0x0245, 0x0246, 0x0246, 0x0248, 0x0248, 0x024a, 0x024a, 0x024c, 0x024c, 0x024e, 0x024e,
+    0x0250, 0x0251, 0x0252, 0x0181, 0x0186, 0x0255, 0x0189, 0x018a, 0x0258, 0x018f, 0x025a, 0x0190, 0x025c, 0x025d, 0x025e, 0x025f,
+    0x0193, 0x0261, 0x0262, 0x0194, 0x0264, 0x0265, 0x0266, 0x0267, 0x0197, 0x0196, 0x026a, 0x2c62, 0x026c, 0x026d, 0x026e, 0x019c,
+    0x0270, 0x0271, 0x019d, 0x0273, 0x0274, 0x019f, 0x0276, 0x0277, 0x0278, 0x0279, 0x027a, 0x027b, 0x027c, 0x2c64, 0x027e, 0x027f,
+    0x01a6, 0x0281, 0x0282, 0x01a9, 0x0284, 0x0285, 0x0286, 0x0287, 0x01ae, 0x0244, 0x01b1, 0x01b2, 0x0245, 0x028d, 0x028e, 0x028f,
+    0x0290, 0x0291, 0x01b7, 0x0293, 0x0294, 0x0295, 0x0296, 0x0297, 0x0298, 0x0299, 0x029a, 0x029b, 0x029c, 0x029d, 0x029e, 0x029f,
+
+    /* 0x0370 - 0x037f, offset 480  */
+    0x0370, 0x0371, 0x0372, 0x0373, 0x0374, 0x0375, 0x0376, 0x0377, 0x0378, 0x0379, 0x037a, 0x03fd, 0x03fe, 0x03ff, 0x037e, 0x037f,
+
+    /* 0x03a0 - 0x03ff, offset 496  */
+    0x03a0, 0x03a1, 0x03a2, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7, 0x03a8, 0x03a9, 0x03aa, 0x03ab, 0x0386, 0x0388, 0x0389, 0x038a,
+    0x03b0, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f,
+    0x03a0, 0x03a1, 0x03a3, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7, 0x03a8, 0x03a9, 0x03aa, 0x03ab, 0x038c, 0x038e, 0x038f, 0x03cf,
+    0x03d0, 0x03d1, 0x03d2, 0x03d3, 0x03d4, 0x03d5, 0x03d6, 0x03d7, 0x03d8, 0x03d8, 0x03da, 0x03da, 0x03dc, 0x03dc, 0x03de, 0x03de,
+    0x03e0, 0x03e0, 0x03e2, 0x03e2, 0x03e4, 0x03e4, 0x03e6, 0x03e6, 0x03e8, 0x03e8, 0x03ea, 0x03ea, 0x03ec, 0x03ec, 0x03ee, 0x03ee,
+    0x03f0, 0x03f1, 0x03f9, 0x03f3, 0x03f4, 0x03f5, 0x03f6, 0x03f7, 0x03f7, 0x03f9, 0x03fa, 0x03fa, 0x03fc, 0x03fd, 0x03fe, 0x03ff,
+
+    /* 0x0430 - 0x051f, offset 592  */
+    0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f,
+    0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f,
+    0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, 0x0408, 0x0409, 0x040a, 0x040b, 0x040c, 0x040d, 0x040e, 0x040f,
+    0x0460, 0x0460, 0x0462, 0x0462, 0x0464, 0x0464, 0x0466, 0x0466, 0x0468, 0x0468, 0x046a, 0x046a, 0x046c, 0x046c, 0x046e, 0x046e,
+    0x0470, 0x0470, 0x0472, 0x0472, 0x0474, 0x0474, 0x0476, 0x0476, 0x0478, 0x0478, 0x047a, 0x047a, 0x047c, 0x047c, 0x047e, 0x047e,
+    0x0480, 0x0480, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487, 0x0488, 0x0489, 0x048a, 0x048a, 0x048c, 0x048c, 0x048e, 0x048e,
+    0x0490, 0x0490, 0x0492, 0x0492, 0x0494, 0x0494, 0x0496, 0x0496, 0x0498, 0x0498, 0x049a, 0x049a, 0x049c, 0x049c, 0x049e, 0x049e,
+    0x04a0, 0x04a0, 0x04a2, 0x04a2, 0x04a4, 0x04a4, 0x04a6, 0x04a6, 0x04a8, 0x04a8, 0x04aa, 0x04aa, 0x04ac, 0x04ac, 0x04ae, 0x04ae,
+    0x04b0, 0x04b0, 0x04b2, 0x04b2, 0x04b4, 0x04b4, 0x04b6, 0x04b6, 0x04b8, 0x04b8, 0x04ba, 0x04ba, 0x04bc, 0x04bc, 0x04be, 0x04be,
+    0x04c0, 0x04c1, 0x04c1, 0x04c3, 0x04c3, 0x04c5, 0x04c5, 0x04c7, 0x04c7, 0x04c9, 0x04c9, 0x04cb, 0x04cb, 0x04cd, 0x04cd, 0x04c0,
+    0x04d0, 0x04d0, 0x04d2, 0x04d2, 0x04d4, 0x04d4, 0x04d6, 0x04d6, 0x04d8, 0x04d8, 0x04da, 0x04da, 0x04dc, 0x04dc, 0x04de, 0x04de,
+    0x04e0, 0x04e0, 0x04e2, 0x04e2, 0x04e4, 0x04e4, 0x04e6, 0x04e6, 0x04e8, 0x04e8, 0x04ea, 0x04ea, 0x04ec, 0x04ec, 0x04ee, 0x04ee,
+    0x04f0, 0x04f0, 0x04f2, 0x04f2, 0x04f4, 0x04f4, 0x04f6, 0x04f6, 0x04f8, 0x04f8, 0x04fa, 0x04fa, 0x04fc, 0x04fc, 0x04fe, 0x04fe,
+    0x0500, 0x0500, 0x0502, 0x0502, 0x0504, 0x0504, 0x0506, 0x0506, 0x0508, 0x0508, 0x050a, 0x050a, 0x050c, 0x050c, 0x050e, 0x050e,
+    0x0510, 0x0510, 0x0512, 0x0512, 0x0514, 0x0515, 0x0516, 0x0517, 0x0518, 0x0519, 0x051a, 0x051b, 0x051c, 0x051d, 0x051e, 0x051f,
+
+
+    /* 0x0560 - 0x058f, offset 832  */
+    0x0560, 0x0531, 0x0532, 0x0533, 0x0534, 0x0535, 0x0536, 0x0537, 0x0538, 0x0539, 0x053a, 0x053b, 0x053c, 0x053d, 0x053e, 0x053f,
+    0x0540, 0x0541, 0x0542, 0x0543, 0x0544, 0x0545, 0x0546, 0x0547, 0x0548, 0x0549, 0x054a, 0x054b, 0x054c, 0x054d, 0x054e, 0x054f,
+    0x0550, 0x0551, 0x0552, 0x0553, 0x0554, 0x0555, 0x0556, 0x0587, 0x0588, 0x0589, 0x058a, 0x058b, 0x058c, 0x058d, 0x058e, 0x058f,
+
+    /* 0x1d70 - 0x1d7f, offset 880  */
+    0x1d70, 0x1d71, 0x1d72, 0x1d73, 0x1d74, 0x1d75, 0x1d76, 0x1d77, 0x1d78, 0x1d79, 0x1d7a, 0x1d7b, 0x1d7c, 0x2c63, 0x1d7e, 0x1d7f,
+
+    /* 0x1e00 - 0x1fff, offset 896  */
+    0x1e00, 0x1e00, 0x1e02, 0x1e02, 0x1e04, 0x1e04, 0x1e06, 0x1e06, 0x1e08, 0x1e08, 0x1e0a, 0x1e0a, 0x1e0c, 0x1e0c, 0x1e0e, 0x1e0e,
+    0x1e10, 0x1e10, 0x1e12, 0x1e12, 0x1e14, 0x1e14, 0x1e16, 0x1e16, 0x1e18, 0x1e18, 0x1e1a, 0x1e1a, 0x1e1c, 0x1e1c, 0x1e1e, 0x1e1e,
+    0x1e20, 0x1e20, 0x1e22, 0x1e22, 0x1e24, 0x1e24, 0x1e26, 0x1e26, 0x1e28, 0x1e28, 0x1e2a, 0x1e2a, 0x1e2c, 0x1e2c, 0x1e2e, 0x1e2e,
+    0x1e30, 0x1e30, 0x1e32, 0x1e32, 0x1e34, 0x1e34, 0x1e36, 0x1e36, 0x1e38, 0x1e38, 0x1e3a, 0x1e3a, 0x1e3c, 0x1e3c, 0x1e3e, 0x1e3e,
+    0x1e40, 0x1e40, 0x1e42, 0x1e42, 0x1e44, 0x1e44, 0x1e46, 0x1e46, 0x1e48, 0x1e48, 0x1e4a, 0x1e4a, 0x1e4c, 0x1e4c, 0x1e4e, 0x1e4e,
+    0x1e50, 0x1e50, 0x1e52, 0x1e52, 0x1e54, 0x1e54, 0x1e56, 0x1e56, 0x1e58, 0x1e58, 0x1e5a, 0x1e5a, 0x1e5c, 0x1e5c, 0x1e5e, 0x1e5e,
+    0x1e60, 0x1e60, 0x1e62, 0x1e62, 0x1e64, 0x1e64, 0x1e66, 0x1e66, 0x1e68, 0x1e68, 0x1e6a, 0x1e6a, 0x1e6c, 0x1e6c, 0x1e6e, 0x1e6e,
+    0x1e70, 0x1e70, 0x1e72, 0x1e72, 0x1e74, 0x1e74, 0x1e76, 0x1e76, 0x1e78, 0x1e78, 0x1e7a, 0x1e7a, 0x1e7c, 0x1e7c, 0x1e7e, 0x1e7e,
+    0x1e80, 0x1e80, 0x1e82, 0x1e82, 0x1e84, 0x1e84, 0x1e86, 0x1e86, 0x1e88, 0x1e88, 0x1e8a, 0x1e8a, 0x1e8c, 0x1e8c, 0x1e8e, 0x1e8e,
+    0x1e90, 0x1e90, 0x1e92, 0x1e92, 0x1e94, 0x1e94, 0x1e96, 0x1e97, 0x1e98, 0x1e99, 0x1e9a, 0x1e9b, 0x1e9c, 0x1e9d, 0x1e9e, 0x1e9f,
+    0x1ea0, 0x1ea0, 0x1ea2, 0x1ea2, 0x1ea4, 0x1ea4, 0x1ea6, 0x1ea6, 0x1ea8, 0x1ea8, 0x1eaa, 0x1eaa, 0x1eac, 0x1eac, 0x1eae, 0x1eae,
+    0x1eb0, 0x1eb0, 0x1eb2, 0x1eb2, 0x1eb4, 0x1eb4, 0x1eb6, 0x1eb6, 0x1eb8, 0x1eb8, 0x1eba, 0x1eba, 0x1ebc, 0x1ebc, 0x1ebe, 0x1ebe,
+    0x1ec0, 0x1ec0, 0x1ec2, 0x1ec2, 0x1ec4, 0x1ec4, 0x1ec6, 0x1ec6, 0x1ec8, 0x1ec8, 0x1eca, 0x1eca, 0x1ecc, 0x1ecc, 0x1ece, 0x1ece,
+    0x1ed0, 0x1ed0, 0x1ed2, 0x1ed2, 0x1ed4, 0x1ed4, 0x1ed6, 0x1ed6, 0x1ed8, 0x1ed8, 0x1eda, 0x1eda, 0x1edc, 0x1edc, 0x1ede, 0x1ede,
+    0x1ee0, 0x1ee0, 0x1ee2, 0x1ee2, 0x1ee4, 0x1ee4, 0x1ee6, 0x1ee6, 0x1ee8, 0x1ee8, 0x1eea, 0x1eea, 0x1eec, 0x1eec, 0x1eee, 0x1eee,
+    0x1ef0, 0x1ef0, 0x1ef2, 0x1ef2, 0x1ef4, 0x1ef4, 0x1ef6, 0x1ef6, 0x1ef8, 0x1ef8, 0x1efa, 0x1efb, 0x1efc, 0x1efd, 0x1efe, 0x1eff,
+    0x1f08, 0x1f09, 0x1f0a, 0x1f0b, 0x1f0c, 0x1f0d, 0x1f0e, 0x1f0f, 0x1f08, 0x1f09, 0x1f0a, 0x1f0b, 0x1f0c, 0x1f0d, 0x1f0e, 0x1f0f,
+    0x1f18, 0x1f19, 0x1f1a, 0x1f1b, 0x1f1c, 0x1f1d, 0x1f16, 0x1f17, 0x1f18, 0x1f19, 0x1f1a, 0x1f1b, 0x1f1c, 0x1f1d, 0x1f1e, 0x1f1f,
+    0x1f28, 0x1f29, 0x1f2a, 0x1f2b, 0x1f2c, 0x1f2d, 0x1f2e, 0x1f2f, 0x1f28, 0x1f29, 0x1f2a, 0x1f2b, 0x1f2c, 0x1f2d, 0x1f2e, 0x1f2f,
+    0x1f38, 0x1f39, 0x1f3a, 0x1f3b, 0x1f3c, 0x1f3d, 0x1f3e, 0x1f3f, 0x1f38, 0x1f39, 0x1f3a, 0x1f3b, 0x1f3c, 0x1f3d, 0x1f3e, 0x1f3f,
+    0x1f48, 0x1f49, 0x1f4a, 0x1f4b, 0x1f4c, 0x1f4d, 0x1f46, 0x1f47, 0x1f48, 0x1f49, 0x1f4a, 0x1f4b, 0x1f4c, 0x1f4d, 0x1f4e, 0x1f4f,
+    0x1f50, 0x1f59, 0x1f52, 0x1f5b, 0x1f54, 0x1f5d, 0x1f56, 0x1f5f, 0x1f58, 0x1f59, 0x1f5a, 0x1f5b, 0x1f5c, 0x1f5d, 0x1f5e, 0x1f5f,
+    0x1f68, 0x1f69, 0x1f6a, 0x1f6b, 0x1f6c, 0x1f6d, 0x1f6e, 0x1f6f, 0x1f68, 0x1f69, 0x1f6a, 0x1f6b, 0x1f6c, 0x1f6d, 0x1f6e, 0x1f6f,
+    0x1fba, 0x1fbb, 0x1fc8, 0x1fc9, 0x1fca, 0x1fcb, 0x1fda, 0x1fdb, 0x1ff8, 0x1ff9, 0x1fea, 0x1feb, 0x1ffa, 0x1ffb, 0x1f7e, 0x1f7f,
+    0x1f88, 0x1f89, 0x1f8a, 0x1f8b, 0x1f8c, 0x1f8d, 0x1f8e, 0x1f8f, 0x1f88, 0x1f89, 0x1f8a, 0x1f8b, 0x1f8c, 0x1f8d, 0x1f8e, 0x1f8f,
+    0x1f98, 0x1f99, 0x1f9a, 0x1f9b, 0x1f9c, 0x1f9d, 0x1f9e, 0x1f9f, 0x1f98, 0x1f99, 0x1f9a, 0x1f9b, 0x1f9c, 0x1f9d, 0x1f9e, 0x1f9f,
+    0x1fa8, 0x1fa9, 0x1faa, 0x1fab, 0x1fac, 0x1fad, 0x1fae, 0x1faf, 0x1fa8, 0x1fa9, 0x1faa, 0x1fab, 0x1fac, 0x1fad, 0x1fae, 0x1faf,
+    0x1fb8, 0x1fb9, 0x1fb2, 0x1fbc, 0x1fb4, 0x1fb5, 0x1fb6, 0x1fb7, 0x1fb8, 0x1fb9, 0x1fba, 0x1fbb, 0x1fbc, 0x1fbd, 0x1fbe, 0x1fbf,
+    0x1fc0, 0x1fc1, 0x1fc2, 0x1fc3, 0x1fc4, 0x1fc5, 0x1fc6, 0x1fc7, 0x1fc8, 0x1fc9, 0x1fca, 0x1fcb, 0x1fc3, 0x1fcd, 0x1fce, 0x1fcf,
+    0x1fd8, 0x1fd9, 0x1fd2, 0x1fd3, 0x1fd4, 0x1fd5, 0x1fd6, 0x1fd7, 0x1fd8, 0x1fd9, 0x1fda, 0x1fdb, 0x1fdc, 0x1fdd, 0x1fde, 0x1fdf,
+    0x1fe8, 0x1fe9, 0x1fe2, 0x1fe3, 0x1fe4, 0x1fec, 0x1fe6, 0x1fe7, 0x1fe8, 0x1fe9, 0x1fea, 0x1feb, 0x1fec, 0x1fed, 0x1fee, 0x1fef,
+    0x1ff0, 0x1ff1, 0x1ff2, 0x1ff3, 0x1ff4, 0x1ff5, 0x1ff6, 0x1ff7, 0x1ff8, 0x1ff9, 0x1ffa, 0x1ffb, 0x1ff3, 0x1ffd, 0x1ffe, 0x1fff,
+
+    /* 0x2140 - 0x214f, offset 1408  */
+    0x2140, 0x2141, 0x2142, 0x2143, 0x2144, 0x2145, 0x2146, 0x2147, 0x2148, 0x2149, 0x214a, 0x214b, 0x214c, 0x214d, 0x2132, 0x214f,
+
+    /* 0x2170 - 0x218f, offset 1424  */
+    0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0x216a, 0x216b, 0x216c, 0x216d, 0x216e, 0x216f,
+    0x2180, 0x2181, 0x2182, 0x2183, 0x2183, 0x2185, 0x2186, 0x2187, 0x2188, 0x2189, 0x218a, 0x218b, 0x218c, 0x218d, 0x218e, 0x218f,
+
+    /* 0x24d0 - 0x24ef, offset 1456  */
+    0x24b6, 0x24b7, 0x24b8, 0x24b9, 0x24ba, 0x24bb, 0x24bc, 0x24bd, 0x24be, 0x24bf, 0x24c0, 0x24c1, 0x24c2, 0x24c3, 0x24c4, 0x24c5,
+    0x24c6, 0x24c7, 0x24c8, 0x24c9, 0x24ca, 0x24cb, 0x24cc, 0x24cd, 0x24ce, 0x24cf, 0x24ea, 0x24eb, 0x24ec, 0x24ed, 0x24ee, 0x24ef,
+
+    /* 0x2c30 - 0x2d2f, offset 1488  */
+    0x2c00, 0x2c01, 0x2c02, 0x2c03, 0x2c04, 0x2c05, 0x2c06, 0x2c07, 0x2c08, 0x2c09, 0x2c0a, 0x2c0b, 0x2c0c, 0x2c0d, 0x2c0e, 0x2c0f,
+    0x2c10, 0x2c11, 0x2c12, 0x2c13, 0x2c14, 0x2c15, 0x2c16, 0x2c17, 0x2c18, 0x2c19, 0x2c1a, 0x2c1b, 0x2c1c, 0x2c1d, 0x2c1e, 0x2c1f,
+    0x2c20, 0x2c21, 0x2c22, 0x2c23, 0x2c24, 0x2c25, 0x2c26, 0x2c27, 0x2c28, 0x2c29, 0x2c2a, 0x2c2b, 0x2c2c, 0x2c2d, 0x2c2e, 0x2c5f,
+    0x2c60, 0x2c60, 0x2c62, 0x2c63, 0x2c64, 0x2c65, 0x2c66, 0x2c67, 0x2c67, 0x2c69, 0x2c69, 0x2c6b, 0x2c6b, 0x2c6d, 0x2c6e, 0x2c6f,
+    0x2c70, 0x2c71, 0x2c72, 0x2c73, 0x2c74, 0x2c75, 0x2c75, 0x2c77, 0x2c78, 0x2c79, 0x2c7a, 0x2c7b, 0x2c7c, 0x2c7d, 0x2c7e, 0x2c7f,
+    0x2c80, 0x2c80, 0x2c82, 0x2c82, 0x2c84, 0x2c84, 0x2c86, 0x2c86, 0x2c88, 0x2c88, 0x2c8a, 0x2c8a, 0x2c8c, 0x2c8c, 0x2c8e, 0x2c8e,
+    0x2c90, 0x2c90, 0x2c92, 0x2c92, 0x2c94, 0x2c94, 0x2c96, 0x2c96, 0x2c98, 0x2c98, 0x2c9a, 0x2c9a, 0x2c9c, 0x2c9c, 0x2c9e, 0x2c9e,
+    0x2ca0, 0x2ca0, 0x2ca2, 0x2ca2, 0x2ca4, 0x2ca4, 0x2ca6, 0x2ca6, 0x2ca8, 0x2ca8, 0x2caa, 0x2caa, 0x2cac, 0x2cac, 0x2cae, 0x2cae,
+    0x2cb0, 0x2cb0, 0x2cb2, 0x2cb2, 0x2cb4, 0x2cb4, 0x2cb6, 0x2cb6, 0x2cb8, 0x2cb8, 0x2cba, 0x2cba, 0x2cbc, 0x2cbc, 0x2cbe, 0x2cbe,
+    0x2cc0, 0x2cc0, 0x2cc2, 0x2cc2, 0x2cc4, 0x2cc4, 0x2cc6, 0x2cc6, 0x2cc8, 0x2cc8, 0x2cca, 0x2cca, 0x2ccc, 0x2ccc, 0x2cce, 0x2cce,
+    0x2cd0, 0x2cd0, 0x2cd2, 0x2cd2, 0x2cd4, 0x2cd4, 0x2cd6, 0x2cd6, 0x2cd8, 0x2cd8, 0x2cda, 0x2cda, 0x2cdc, 0x2cdc, 0x2cde, 0x2cde,
+    0x2ce0, 0x2ce0, 0x2ce2, 0x2ce2, 0x2ce4, 0x2ce5, 0x2ce6, 0x2ce7, 0x2ce8, 0x2ce9, 0x2cea, 0x2ceb, 0x2cec, 0x2ced, 0x2cee, 0x2cef,
+    0x2cf0, 0x2cf1, 0x2cf2, 0x2cf3, 0x2cf4, 0x2cf5, 0x2cf6, 0x2cf7, 0x2cf8, 0x2cf9, 0x2cfa, 0x2cfb, 0x2cfc, 0x2cfd, 0x2cfe, 0x2cff,
+    0x10a0, 0x10a1, 0x10a2, 0x10a3, 0x10a4, 0x10a5, 0x10a6, 0x10a7, 0x10a8, 0x10a9, 0x10aa, 0x10ab, 0x10ac, 0x10ad, 0x10ae, 0x10af,
+    0x10b0, 0x10b1, 0x10b2, 0x10b3, 0x10b4, 0x10b5, 0x10b6, 0x10b7, 0x10b8, 0x10b9, 0x10ba, 0x10bb, 0x10bc, 0x10bd, 0x10be, 0x10bf,
+    0x10c0, 0x10c1, 0x10c2, 0x10c3, 0x10c4, 0x10c5, 0x2d26, 0x2d27, 0x2d28, 0x2d29, 0x2d2a, 0x2d2b, 0x2d2c, 0x2d2d, 0x2d2e, 0x2d2f,
+
+    /* 0xff40 - 0xff5f, offset 1744  */
+    0xff40, 0xff21, 0xff22, 0xff23, 0xff24, 0xff25, 0xff26, 0xff27, 0xff28, 0xff29, 0xff2a, 0xff2b, 0xff2c, 0xff2d, 0xff2e, 0xff2f,
+    0xff30, 0xff31, 0xff32, 0xff33, 0xff34, 0xff35, 0xff36, 0xff37, 0xff38, 0xff39, 0xff3a, 0xff5b, 0xff5c, 0xff5d, 0xff5e, 0xff5f
+};
+
+
+static const USHORT diff_table_range_low[] =
+{
+    0x0060, 0x00e0, 0x0370, 0x03a0, 0x0430, 0x0560, 0x1d70, 0x1e00, 0x2140, 0x2170, 0x24d0, 0x2c30, 0xff40
+};
+
+static const USHORT diff_table_range_high[] =
+{
+    0x007f, 0x029f, 0x037f, 0x03ff, 0x051f, 0x058f, 0x1d7f, 0x1fff, 0x214f, 0x218f, 0x24ef, 0x2d2f, 0xff5f
+};
+
+static const USHORT diff_table_offset[] =
+{
+    0,      32,     480,    496,    592,    832,    880,    896,    1408,   1424,   1456,   1488,   1744
+};
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_utility_exFAT_upcase_get                        PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function return the upper case character of the input          */
+/*    character.                                                          */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    character                             Input character               */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return upper case character                                         */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    _fx_utility_exFAT_name_hash_get                                     */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+USHORT _fx_utility_exFAT_upcase_get(USHORT character)
+{
+
+UINT i;
+
+
+    /* Loop to find if the character is in the range of the differential table.  */
+    for (i = 0; i < sizeof(diff_table_range_low) / sizeof(USHORT); i++)
+    {
+
+        /* Check the range.  */
+        if (character >= diff_table_range_low[i] && character <= diff_table_range_high[i])
+        {
+
+            /* Return the character from table.  */
+            return(_fx_utility_exFAT_upcase_table_differential[diff_table_offset[i] + character - diff_table_range_low[i]]);
+        }
+    }
+
+    /* Lower case and upper case are the same, return directly.  */
+    return(character);
+}
+
+
+
+
+#endif /* FX_ENABLE_EXFAT */
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_logical_sector_cache_entry_read.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_logical_sector_cache_entry_read.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_logical_sector_cache_entry_read.c	(revision 30)
@@ -0,0 +1,359 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Utility                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_utility.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_utility_logical_sector_cache_entry_read         PORTABLE C      */
+/*                                                           6.1.10       */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function handles logical sector cache read requests for the    */
+/*    logical sector read function. If the function finds the requested   */
+/*    sector in the cache, it setup the appropriate pointers and          */
+/*    returns a FX_NULL.                                                  */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    logical_sector                        Logical sector number         */
+/*    previous_cache_entry                  Pointer to previous entry in  */
+/*                                            non-hashed cache            */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    FX_CACHED_SECTOR *                    Cache entry to setup          */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    _fx_utility_logical_sector_read       Logical sector read function  */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s), and      */
+/*                                            added conditional to        */
+/*                                            disable cache,              */
+/*                                            resulting in version 6.1    */
+/*  01-31-2022     William E. Lamie         Modified comment(s), fixed    */
+/*                                            errors without cache,       */
+/*                                            resulting in version 6.1.10 */
+/*                                                                        */
+/**************************************************************************/
+FX_CACHED_SECTOR  *_fx_utility_logical_sector_cache_entry_read(FX_MEDIA *media_ptr, ULONG64 logical_sector,
+                                                               FX_CACHED_SECTOR **previous_cache_entry)
+{
+
+#ifndef FX_DISABLE_CACHE
+FX_CACHED_SECTOR *cache_entry;
+FX_CACHED_SECTOR  temp_storage;
+ULONG             cache_size;
+ULONG             index;
+
+
+    /* Determine if the logical sector cache access should use the hash function.  */
+    if (media_ptr -> fx_media_sector_cache_hashed)
+    {
+
+        /* Calculate the area of the cache for this logical sector.  */
+
+        /* First compute the hashed value of this index by simply using the lower bits of
+           the sector number.  */
+        index =  (ULONG)(logical_sector & media_ptr -> fx_media_sector_cache_hash_mask);
+
+        /* Set the bit indicating there is one or more valid sectors at this cache index.  */
+        media_ptr -> fx_media_sector_cache_hashed_sector_valid |=  ((ULONG)1) << (index % 32);
+
+        /* Compute the actual array index by multiplying by the cache depth.  */
+        index =  index * FX_SECTOR_CACHE_DEPTH;
+
+        /* Build a pointer to the cache entry.  */
+        cache_entry =  &(media_ptr -> fx_media_sector_cache[index]);
+
+        /* Determine if the logical sector is in the cache - assuming the depth of the
+           sector cache is 4 entries.  */
+        if ((cache_entry -> fx_cached_sector_valid) && (cache_entry -> fx_cached_sector == logical_sector))
+        {
+
+            /* Yes, we found a match.  Simply setup the pointer to this
+               buffer and return.  */
+            media_ptr -> fx_media_memory_buffer =  cache_entry -> fx_cached_sector_memory_buffer;
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+            /* Increment the number of logical sectors cache read hits.  */
+            media_ptr -> fx_media_logical_sector_cache_read_hits++;
+#endif
+            /* Success, return to caller immediately!  */
+            return(FX_NULL);
+        }
+        else if (((cache_entry + 1) -> fx_cached_sector_valid) && ((cache_entry + 1) -> fx_cached_sector == logical_sector))
+        {
+
+            /* Yes, we found a match.  Simply setup the pointer to this
+               buffer and return.  */
+            media_ptr -> fx_media_memory_buffer =  (cache_entry + 1) -> fx_cached_sector_memory_buffer;
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+            /* Increment the number of logical sectors cache read hits.  */
+            media_ptr -> fx_media_logical_sector_cache_read_hits++;
+#endif
+
+            /* Swap the first and second cache entries to keep the most recently used
+               at the top.  */
+            temp_storage.fx_cached_sector_memory_buffer =           (cache_entry) -> fx_cached_sector_memory_buffer;
+            temp_storage.fx_cached_sector =                         (cache_entry) -> fx_cached_sector;
+            temp_storage.fx_cached_sector_buffer_dirty =            (cache_entry) -> fx_cached_sector_buffer_dirty;
+            temp_storage.fx_cached_sector_valid =                   (cache_entry) -> fx_cached_sector_valid;
+            temp_storage.fx_cached_sector_type =                    (cache_entry) -> fx_cached_sector_type;
+
+            (cache_entry) -> fx_cached_sector_memory_buffer =       (cache_entry + 1) -> fx_cached_sector_memory_buffer;
+            (cache_entry) -> fx_cached_sector =                     (cache_entry + 1) -> fx_cached_sector;
+            (cache_entry) -> fx_cached_sector_buffer_dirty =        (cache_entry + 1) -> fx_cached_sector_buffer_dirty;
+            (cache_entry) -> fx_cached_sector_valid =               (cache_entry + 1) -> fx_cached_sector_valid;
+            (cache_entry) -> fx_cached_sector_type =                (cache_entry + 1) -> fx_cached_sector_type;
+
+            (cache_entry + 1) -> fx_cached_sector_memory_buffer =   temp_storage.fx_cached_sector_memory_buffer;
+            (cache_entry + 1) -> fx_cached_sector =                 temp_storage.fx_cached_sector;
+            (cache_entry + 1) -> fx_cached_sector_buffer_dirty =    temp_storage.fx_cached_sector_buffer_dirty;
+            (cache_entry + 1) -> fx_cached_sector_valid =           temp_storage.fx_cached_sector_valid;
+            (cache_entry + 1) -> fx_cached_sector_type =            temp_storage.fx_cached_sector_type;
+
+            /* Success, return to caller immediately!  */
+            return(FX_NULL);
+        }
+        else if (((cache_entry + 2) -> fx_cached_sector_valid) && ((cache_entry + 2) -> fx_cached_sector == logical_sector))
+        {
+
+            /* Yes, we found a match.  Simply setup the pointer to this
+               buffer and return.  */
+            media_ptr -> fx_media_memory_buffer =  (cache_entry + 2) -> fx_cached_sector_memory_buffer;
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+            /* Increment the number of logical sectors cache read hits.  */
+            media_ptr -> fx_media_logical_sector_cache_read_hits++;
+#endif
+
+            /* Move the third entry to the top and the first two entries down.  */
+            temp_storage.fx_cached_sector_memory_buffer =           (cache_entry) -> fx_cached_sector_memory_buffer;
+            temp_storage.fx_cached_sector =                         (cache_entry) -> fx_cached_sector;
+            temp_storage.fx_cached_sector_buffer_dirty =            (cache_entry) -> fx_cached_sector_buffer_dirty;
+            temp_storage.fx_cached_sector_valid =                   (cache_entry) -> fx_cached_sector_valid;
+            temp_storage.fx_cached_sector_type =                    (cache_entry) -> fx_cached_sector_type;
+
+            (cache_entry) -> fx_cached_sector_memory_buffer =       (cache_entry + 2) -> fx_cached_sector_memory_buffer;
+            (cache_entry) -> fx_cached_sector =                     (cache_entry + 2) -> fx_cached_sector;
+            (cache_entry) -> fx_cached_sector_buffer_dirty =        (cache_entry + 2) -> fx_cached_sector_buffer_dirty;
+            (cache_entry) -> fx_cached_sector_valid =               (cache_entry + 2) -> fx_cached_sector_valid;
+            (cache_entry) -> fx_cached_sector_type =                (cache_entry + 2) -> fx_cached_sector_type;
+
+            (cache_entry + 2) -> fx_cached_sector_memory_buffer =   (cache_entry + 1) -> fx_cached_sector_memory_buffer;
+            (cache_entry + 2) -> fx_cached_sector =                 (cache_entry + 1) -> fx_cached_sector;
+            (cache_entry + 2) -> fx_cached_sector_buffer_dirty =    (cache_entry + 1) -> fx_cached_sector_buffer_dirty;
+            (cache_entry + 2) -> fx_cached_sector_valid =           (cache_entry + 1) -> fx_cached_sector_valid;
+            (cache_entry + 2) -> fx_cached_sector_type =            (cache_entry + 1) -> fx_cached_sector_type;
+
+            (cache_entry + 1) -> fx_cached_sector_memory_buffer =   temp_storage.fx_cached_sector_memory_buffer;
+            (cache_entry + 1) -> fx_cached_sector =                 temp_storage.fx_cached_sector;
+            (cache_entry + 1) -> fx_cached_sector_buffer_dirty =    temp_storage.fx_cached_sector_buffer_dirty;
+            (cache_entry + 1) -> fx_cached_sector_valid =           temp_storage.fx_cached_sector_valid;
+            (cache_entry + 1) -> fx_cached_sector_type =            temp_storage.fx_cached_sector_type;
+
+            /* Success, return to caller immediately!  */
+            return(FX_NULL);
+        }
+        else if (((cache_entry + 3) -> fx_cached_sector_valid) && ((cache_entry + 3) -> fx_cached_sector == logical_sector))
+        {
+
+            /* Yes, we found a match.  Simply setup the pointer to this
+               buffer and return.  */
+            media_ptr -> fx_media_memory_buffer =  (cache_entry + 3) -> fx_cached_sector_memory_buffer;
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+            /* Increment the number of logical sectors cache read hits.  */
+            media_ptr -> fx_media_logical_sector_cache_read_hits++;
+#endif
+
+            /* Move the last entry to the top and the first three entries down.  */
+            temp_storage.fx_cached_sector_memory_buffer =           (cache_entry) -> fx_cached_sector_memory_buffer;
+            temp_storage.fx_cached_sector =                         (cache_entry) -> fx_cached_sector;
+            temp_storage.fx_cached_sector_buffer_dirty =            (cache_entry) -> fx_cached_sector_buffer_dirty;
+            temp_storage.fx_cached_sector_valid =                   (cache_entry) -> fx_cached_sector_valid;
+            temp_storage.fx_cached_sector_type =                    (cache_entry) -> fx_cached_sector_type;
+
+            (cache_entry) -> fx_cached_sector_memory_buffer =       (cache_entry + 3) -> fx_cached_sector_memory_buffer;
+            (cache_entry) -> fx_cached_sector =                     (cache_entry + 3) -> fx_cached_sector;
+            (cache_entry) -> fx_cached_sector_buffer_dirty =        (cache_entry + 3) -> fx_cached_sector_buffer_dirty;
+            (cache_entry) -> fx_cached_sector_valid =               (cache_entry + 3) -> fx_cached_sector_valid;
+            (cache_entry) -> fx_cached_sector_type =                (cache_entry + 3) -> fx_cached_sector_type;
+
+            (cache_entry + 3) -> fx_cached_sector_memory_buffer =   (cache_entry + 2) -> fx_cached_sector_memory_buffer;
+            (cache_entry + 3) -> fx_cached_sector =                 (cache_entry + 2) -> fx_cached_sector;
+            (cache_entry + 3) -> fx_cached_sector_buffer_dirty =    (cache_entry + 2) -> fx_cached_sector_buffer_dirty;
+            (cache_entry + 3) -> fx_cached_sector_valid =           (cache_entry + 2) -> fx_cached_sector_valid;
+            (cache_entry + 3) -> fx_cached_sector_type =            (cache_entry + 2) -> fx_cached_sector_type;
+
+            (cache_entry + 2) -> fx_cached_sector_memory_buffer =   (cache_entry + 1) -> fx_cached_sector_memory_buffer;
+            (cache_entry + 2) -> fx_cached_sector =                 (cache_entry + 1) -> fx_cached_sector;
+            (cache_entry + 2) -> fx_cached_sector_buffer_dirty =    (cache_entry + 1) -> fx_cached_sector_buffer_dirty;
+            (cache_entry + 2) -> fx_cached_sector_valid =           (cache_entry + 1) -> fx_cached_sector_valid;
+            (cache_entry + 2) -> fx_cached_sector_type =            (cache_entry + 1) -> fx_cached_sector_type;
+
+            (cache_entry + 1) -> fx_cached_sector_memory_buffer =   temp_storage.fx_cached_sector_memory_buffer;
+            (cache_entry + 1) -> fx_cached_sector =                 temp_storage.fx_cached_sector;
+            (cache_entry + 1) -> fx_cached_sector_buffer_dirty =    temp_storage.fx_cached_sector_buffer_dirty;
+            (cache_entry + 1) -> fx_cached_sector_valid =           temp_storage.fx_cached_sector_valid;
+            (cache_entry + 1) -> fx_cached_sector_type =            temp_storage.fx_cached_sector_type;
+
+            /* Success, return to caller immediately!  */
+            return(FX_NULL);
+        }
+
+        /* At this point we have a cache miss.  We need to move all of the sectors down one slot, swapping
+           the 4th entry with the first.  */
+        temp_storage.fx_cached_sector_memory_buffer =           (cache_entry + 3) -> fx_cached_sector_memory_buffer;
+        temp_storage.fx_cached_sector =                         (cache_entry + 3) -> fx_cached_sector;
+        temp_storage.fx_cached_sector_buffer_dirty =            (cache_entry + 3) -> fx_cached_sector_buffer_dirty;
+        temp_storage.fx_cached_sector_valid =                   (cache_entry + 3) -> fx_cached_sector_valid;
+        temp_storage.fx_cached_sector_type =                    (cache_entry + 3) -> fx_cached_sector_type;
+
+        (cache_entry + 3) -> fx_cached_sector_memory_buffer =   (cache_entry + 2) -> fx_cached_sector_memory_buffer;
+        (cache_entry + 3) -> fx_cached_sector =                 (cache_entry + 2) -> fx_cached_sector;
+        (cache_entry + 3) -> fx_cached_sector_buffer_dirty =    (cache_entry + 2) -> fx_cached_sector_buffer_dirty;
+        (cache_entry + 3) -> fx_cached_sector_valid =           (cache_entry + 2) -> fx_cached_sector_valid;
+        (cache_entry + 3) -> fx_cached_sector_type =            (cache_entry + 2) -> fx_cached_sector_type;
+
+        (cache_entry + 2) -> fx_cached_sector_memory_buffer =   (cache_entry + 1) -> fx_cached_sector_memory_buffer;
+        (cache_entry + 2) -> fx_cached_sector =                 (cache_entry + 1) -> fx_cached_sector;
+        (cache_entry + 2) -> fx_cached_sector_buffer_dirty =    (cache_entry + 1) -> fx_cached_sector_buffer_dirty;
+        (cache_entry + 2) -> fx_cached_sector_valid =           (cache_entry + 1) -> fx_cached_sector_valid;
+        (cache_entry + 2) -> fx_cached_sector_type =            (cache_entry + 1) -> fx_cached_sector_type;
+
+        (cache_entry + 1) -> fx_cached_sector_memory_buffer =   (cache_entry) -> fx_cached_sector_memory_buffer;
+        (cache_entry + 1) -> fx_cached_sector =                 (cache_entry) -> fx_cached_sector;
+        (cache_entry + 1) -> fx_cached_sector_buffer_dirty =    (cache_entry) -> fx_cached_sector_buffer_dirty;
+        (cache_entry + 1) -> fx_cached_sector_valid =           (cache_entry) -> fx_cached_sector_valid;
+        (cache_entry + 1) -> fx_cached_sector_type =            (cache_entry) -> fx_cached_sector_type;
+
+        (cache_entry) -> fx_cached_sector_memory_buffer =       temp_storage.fx_cached_sector_memory_buffer;
+        (cache_entry) -> fx_cached_sector =                     temp_storage.fx_cached_sector;
+        (cache_entry) -> fx_cached_sector_buffer_dirty =        temp_storage.fx_cached_sector_buffer_dirty;
+        (cache_entry) -> fx_cached_sector_valid =               temp_storage.fx_cached_sector_valid;
+        (cache_entry) -> fx_cached_sector_type =                temp_storage.fx_cached_sector_type;
+
+        /* Set the previous pointer to NULL to avoid the linked list update below.  */
+        *previous_cache_entry =  FX_NULL;
+    }
+    else
+    {
+
+        /* Search for an entry in the cache that matches this request.  */
+        cache_size =            media_ptr -> fx_media_sector_cache_size;
+        cache_entry =           media_ptr -> fx_media_sector_cache_list_ptr;
+        *previous_cache_entry =  FX_NULL;
+
+        /* Look at the cache entries until a match is found or the end of
+           the cache is reached.  */
+        while (cache_size--)
+        {
+
+            /* Determine if the requested sector has been found.  */
+            if ((cache_entry -> fx_cached_sector_valid) && (cache_entry -> fx_cached_sector == logical_sector))
+            {
+
+                /* Yes, we found a match.  Simply setup the pointer to this
+                   buffer and return.  */
+                media_ptr -> fx_media_memory_buffer =  cache_entry -> fx_cached_sector_memory_buffer;
+
+                /* Determine if we need to update the last used list.  */
+                if (*previous_cache_entry)
+                {
+
+                    /* Yes, the current entry is not at the front of the list
+                       so we need to change the order.  */
+
+                    /* Link the previous entry to this entry's next pointer.  */
+                    (*previous_cache_entry) -> fx_cached_sector_next_used =
+                        cache_entry -> fx_cached_sector_next_used;
+
+                    /* Place this entry at the head of the list.  */
+                    cache_entry -> fx_cached_sector_next_used =
+                        media_ptr -> fx_media_sector_cache_list_ptr;
+                    media_ptr -> fx_media_sector_cache_list_ptr =  cache_entry;
+                }
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+                /* Increment the number of logical sectors cache read hits.  */
+                media_ptr -> fx_media_logical_sector_cache_read_hits++;
+#endif
+
+                /* Success, return to caller immediately!  */
+                return(FX_NULL);
+            }
+
+            /* Otherwise, we have not found the cached entry yet.  */
+
+            /* If there are more entries, move to the next one.  */
+            if (cache_entry -> fx_cached_sector_next_used)
+            {
+
+                *previous_cache_entry =  cache_entry;
+                cache_entry =           cache_entry -> fx_cached_sector_next_used;
+            }
+        }
+    }
+
+    /* The requested sector is not in cache, return the last cache entry.  */
+    return(cache_entry);
+#else
+    FX_PARAMETER_NOT_USED(media_ptr);
+    FX_PARAMETER_NOT_USED(logical_sector);
+    FX_PARAMETER_NOT_USED(previous_cache_entry);
+    return(FX_NULL);
+#endif /* FX_DISABLE_CACHE */
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_logical_sector_flush.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_logical_sector_flush.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_logical_sector_flush.c	(revision 30)
@@ -0,0 +1,522 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Utility                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_utility.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_utility_logical_sector_flush                    PORTABLE C      */
+/*                                                           6.1.10       */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function handles logical sector flush requests for all FileX   */
+/*    components. It will process all dirty logical sectors in the        */
+/*    logical sector cache within the range specified. This function      */
+/*    optionally invalidates sectors.                                     */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    starting_sector                       Starting sector number        */
+/*    sectors                               Number of sectors             */
+/*    invalidate                            Invalidate flag               */
+/*                                            (FX_TRUE -> invalidate)     */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    I/O Driver                                                          */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    FileX System Functions                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s), and      */
+/*                                            added conditional to        */
+/*                                            disable cache,              */
+/*                                            resulting in version 6.1    */
+/*  01-31-2022     William E. Lamie         Modified comment(s), fixed    */
+/*                                            errors without cache,       */
+/*                                            resulting in version 6.1.10 */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_utility_logical_sector_flush(FX_MEDIA *media_ptr, ULONG64 starting_sector, ULONG64 sectors, UINT invalidate)
+{
+
+#ifndef FX_DISABLE_CACHE
+FX_CACHED_SECTOR *cache_entry;
+UINT              cache_size;
+UINT              i, bit_set, use_starting_sector;
+ULONG             index;
+ULONG             remaining_valid;
+ULONG             remaining_dirty;
+ULONG64           ending_sector;
+ULONG             valid_bit_map;
+
+
+    /* Extended port-specific processing macro, which is by default defined to white space.  */
+    FX_UTILITY_LOGICAL_SECTOR_FLUSH_EXTENSION
+
+    /* Calculate the ending sector.  */
+    ending_sector =  starting_sector + sectors - 1;
+
+    /* Pickup the number of dirty sectors currently in the cache.  */
+    remaining_dirty =  media_ptr -> fx_media_sector_cache_dirty_count;
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_MEDIA_FLUSH, media_ptr, media_ptr -> fx_media_sector_cache_dirty_count, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+    /* Determine what type of cache configuration we have.  */
+    if (media_ptr -> fx_media_sector_cache_hashed == FX_FALSE)
+    {
+
+        /* Linear cache present, simply walk through the search list until
+           an unused cache entry is present.  */
+
+        /* Flush and invalidate the internal logical sector cache.  */
+        cache_size =            media_ptr -> fx_media_sector_cache_size;
+        cache_entry =           media_ptr -> fx_media_sector_cache_list_ptr;
+
+        /* Look at the cache entries that have been written to.  */
+        while ((cache_size--) && (cache_entry -> fx_cached_sector))
+        {
+
+            /* Determine if invalidation is not required and there are no
+               more dirty sectors. */
+            if ((remaining_dirty == 0) && (invalidate == FX_FALSE))
+            {
+
+                /* Yes, nothing left to do.  */
+                break;
+            }
+
+            /* Determine if there are any more sectors to process.  */
+            if (sectors == 0)
+            {
+
+                /* No more sectors required to process.  */
+                break;
+            }
+
+            /* Determine if this cached sector is within the specified range and is valid.  */
+            if ((cache_entry -> fx_cached_sector_valid) &&
+                (cache_entry -> fx_cached_sector >= starting_sector) &&
+                (cache_entry -> fx_cached_sector <= ending_sector))
+            {
+
+                /* Yes, the cache entry is valid and within the specified range. Determine if
+                   the requested sector has been written to.  */
+                if (cache_entry -> fx_cached_sector_buffer_dirty)
+                {
+
+                    /* Yes, write the cached sector out to the media.  */
+
+                    /* Check for write protect at the media level (set by driver).  */
+                    if (media_ptr -> fx_media_driver_write_protect == FX_FALSE)
+                    {
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+                        /* Increment the number of driver write sector(s) requests.  */
+                        media_ptr -> fx_media_driver_write_requests++;
+#endif
+
+                        /* Build write request to the driver.  */
+                        media_ptr -> fx_media_driver_request =          FX_DRIVER_WRITE;
+                        media_ptr -> fx_media_driver_status =           FX_IO_ERROR;
+                        media_ptr -> fx_media_driver_buffer =           cache_entry -> fx_cached_sector_memory_buffer;
+#ifdef FX_DRIVER_USE_64BIT_LBA
+                        media_ptr -> fx_media_driver_logical_sector =   cache_entry -> fx_cached_sector;
+#else
+                        media_ptr -> fx_media_driver_logical_sector =   (ULONG)cache_entry -> fx_cached_sector;
+#endif
+                        media_ptr -> fx_media_driver_sectors =          1;
+                        media_ptr -> fx_media_driver_sector_type =      cache_entry -> fx_cached_sector_type;
+
+                        /* Sectors other than FX_DATA_SECTOR will never be dirty when FX_FAULT_TOLERANT is defined. */
+#ifndef FX_FAULT_TOLERANT
+                        /* Determine if the system write flag needs to be set.  */
+                        if (cache_entry -> fx_cached_sector_type != FX_DATA_SECTOR)
+                        {
+
+                            /* Yes, a system sector write is present so set the flag.  The driver
+                               can use this flag to make extra safeguards in writing the sector
+                               out, yielding more fault tolerance.  */
+                            media_ptr -> fx_media_driver_system_write =  FX_TRUE;
+                        }
+#endif /* FX_FAULT_TOLERANT */
+
+                        /* If trace is enabled, insert this event into the trace buffer.  */
+                        FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_WRITE, media_ptr, cache_entry -> fx_cached_sector, 1, cache_entry -> fx_cached_sector_memory_buffer, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+                        /* Invoke the driver to write the sector.  */
+                        (media_ptr -> fx_media_driver_entry) (media_ptr);
+
+                        /* Clear the system write flag.  */
+                        media_ptr -> fx_media_driver_system_write =  FX_FALSE;
+
+                        /* Check for successful completion.  */
+                        if (media_ptr -> fx_media_driver_status)
+                        {
+
+                            /* Error writing a cached sector out.  Return the
+                               error status.  */
+                            return(media_ptr -> fx_media_driver_status);
+                        }
+
+                        /* Clear the buffer dirty flag since it has been flushed
+                           out.  */
+                        cache_entry -> fx_cached_sector_buffer_dirty =  FX_FALSE;
+
+                        /* Decrement the number of dirty sectors currently in the cache.  */
+                        media_ptr -> fx_media_sector_cache_dirty_count--;
+                        remaining_dirty--;
+                    }
+                }
+
+                /* Determine if the invalidate option is specified.  */
+                if (invalidate)
+                {
+
+                    /* Invalidate the cache entry.  */
+                    cache_entry -> fx_cached_sector_valid =  FX_FALSE;
+
+                    /* Place all ones in the sector number.  */
+                    cache_entry -> fx_cached_sector =  (~(ULONG64)0);
+
+                    /* Determine if this sector is still dirty, this could be the case if
+                       write protection was turned on.  */
+                    if (cache_entry -> fx_cached_sector_buffer_dirty)
+                    {
+
+                        /* Yes, clear the dirty flag.  */
+                        cache_entry -> fx_cached_sector_buffer_dirty =  FX_FALSE;
+
+                        /* Decrement the number of dirty sectors currently in the cache.  */
+                        media_ptr -> fx_media_sector_cache_dirty_count--;
+                        remaining_dirty--;
+                    }
+                }
+
+                /* Decrement the number of sectors in the range that have been processed.  */
+                sectors--;
+            }
+
+            /* Move to the next entry in the sector cache.  */
+            cache_entry =  cache_entry -> fx_cached_sector_next_used;
+        }
+    }
+    else
+    {
+
+        /* Hashed cache is present. Pickup the cache size.  */
+        cache_size =            media_ptr -> fx_media_sector_cache_size;
+
+        /* Initialize the loop control parameters.  */
+        bit_set =  0;
+        valid_bit_map =  media_ptr -> fx_media_sector_cache_hashed_sector_valid;
+
+        /* Determine how to process the hashed cache based on the number of sectors
+           to process. If the sequential sector range is less than the bit map size,
+           simply use the starting sector to derive the index into the cache.  */
+        if (sectors < 32)
+        {
+            use_starting_sector =  FX_TRUE;
+        }
+        else
+        {
+            use_starting_sector =  FX_FALSE;
+        }
+
+        /* Determine if there is anything valid in the cache.  */
+        while (valid_bit_map)
+        {
+
+            /* Determine if invalidation is not required and there are no
+               more dirty sectors. */
+            if ((remaining_dirty == 0) && (invalidate == FX_FALSE))
+            {
+
+                /* Yes, nothing left to do.  */
+                break;
+            }
+
+            /* Determine if there are any more sectors to process.  */
+            if ((sectors == 0) || (starting_sector > ending_sector))
+            {
+
+                /* No more sectors required to process.  */
+                break;
+            }
+
+            /* Determine how to compute the hash index.  */
+            if (use_starting_sector)
+            {
+
+                /* Calculate the hash value of this sector using the lower bits.  */
+                index =  (ULONG)(starting_sector & media_ptr -> fx_media_sector_cache_hash_mask);
+
+                /* Calculate the bit set indicating there is one or more valid sectors at this cache index.  */
+                bit_set =  (index % 32);
+
+                /* Compute the actual array index by multiplying by the cache depth.  */
+                index =  (bit_set * FX_SECTOR_CACHE_DEPTH);
+            }
+            else
+            {
+
+                /* Walk the bit map to find the next valid entry.  */
+
+                /* Find the next set bit.  */
+                while ((valid_bit_map & 1) == 0)
+                {
+
+                    /* Otherwise, shift down the bit in the bit map.  */
+                    valid_bit_map =  valid_bit_map >> 1;
+
+                    /* Increment the set bit marker.  */
+                    bit_set++;
+                }
+
+                /* Compute the first actual index into the hashed cache.  */
+                index =  (bit_set * FX_SECTOR_CACHE_DEPTH);
+            }
+
+            /* At this point, bit_set represents the next group of hashed sectors that could
+               have valid cache entries and index represents the index into the sector cache
+               of that sector group.  */
+
+            /* Clear the remaining valid sectors for this entry in the bit map.  */
+            remaining_valid =  0;
+
+            /* Loop to check the corresponding hash entries.  */
+            do
+            {
+
+                /* Setup pointer to the cache entry.  */
+                cache_entry =  &(media_ptr -> fx_media_sector_cache[index]);
+
+                /* Loop to examine the full depth of the hashed cache.  */
+                for (i = 0; i < 4; i++)
+                {
+
+                    /* Determine if this cached sector is within the specified range and is valid.  */
+                    if ((cache_entry -> fx_cached_sector_valid) &&
+                        (cache_entry -> fx_cached_sector >= starting_sector) &&
+                        (cache_entry -> fx_cached_sector <= ending_sector))
+                    {
+
+                        /* Determine if the requested sector has been written to.  */
+                        if (cache_entry -> fx_cached_sector_buffer_dirty)
+                        {
+
+
+                            /* Yes, write the cached sector out to the media.  */
+
+                            /* Check for write protect at the media level (set by driver).  */
+                            if (media_ptr -> fx_media_driver_write_protect == FX_FALSE)
+                            {
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+                                /* Increment the number of driver write sector(s) requests.  */
+                                media_ptr -> fx_media_driver_write_requests++;
+#endif
+
+                                /* Build Write request to the driver.  */
+                                media_ptr -> fx_media_driver_request =          FX_DRIVER_WRITE;
+                                media_ptr -> fx_media_driver_status =           FX_IO_ERROR;
+                                media_ptr -> fx_media_driver_buffer =           cache_entry -> fx_cached_sector_memory_buffer;
+#ifdef FX_DRIVER_USE_64BIT_LBA
+                                media_ptr -> fx_media_driver_logical_sector =   cache_entry -> fx_cached_sector;
+#else
+                                media_ptr -> fx_media_driver_logical_sector =   (ULONG)cache_entry -> fx_cached_sector;
+#endif
+                                media_ptr -> fx_media_driver_sectors =          1;
+                                media_ptr -> fx_media_driver_sector_type =      cache_entry -> fx_cached_sector_type;
+
+                                /* Sectors other than FX_DATA_SECTOR will never be dirty when FX_FAULT_TOLERANT is defined. */
+#ifndef FX_FAULT_TOLERANT
+                                /* Determine if the system write flag needs to be set.  */
+                                if (cache_entry -> fx_cached_sector_type != FX_DATA_SECTOR)
+                                {
+
+                                    /* Yes, a system sector write is present so set the flag.  The driver
+                                       can use this flag to make extra safeguards in writing the sector
+                                       out, yielding more fault tolerance.  */
+                                    media_ptr -> fx_media_driver_system_write =  FX_TRUE;
+                                }
+#endif /* FX_FAULT_TOLERANT */
+
+                                /* If trace is enabled, insert this event into the trace buffer.  */
+                                FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_WRITE, media_ptr, cache_entry -> fx_cached_sector, 1, cache_entry -> fx_cached_sector_memory_buffer, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+                                /* Invoke the driver to write the sector.  */
+                                (media_ptr -> fx_media_driver_entry) (media_ptr);
+
+                                /* Clear the system write flag.  */
+                                media_ptr -> fx_media_driver_system_write =  FX_FALSE;
+
+                                /* Check for successful completion.  */
+                                if (media_ptr -> fx_media_driver_status)
+                                {
+
+                                    /* Error writing a cached sector out.  Return the
+                                       error status.  */
+                                    return(media_ptr -> fx_media_driver_status);
+                                }
+
+                                /* Clear the buffer dirty flag since it has been flushed
+                                   out.  */
+                                cache_entry -> fx_cached_sector_buffer_dirty =  FX_FALSE;
+
+                                /* Decrement the number of dirty sectors currently in the cache.  */
+                                media_ptr -> fx_media_sector_cache_dirty_count--;
+                                remaining_dirty--;
+                            }
+                        }
+
+                        /* Determine if the invalidate option is specified.  */
+                        if (invalidate)
+                        {
+
+                            /* Invalidate the cache entry.  */
+                            cache_entry -> fx_cached_sector_valid =  FX_FALSE;
+
+                            /* Place all ones in the sector number.  */
+                            cache_entry -> fx_cached_sector =  (~(ULONG64)0);
+
+                            /* Determine if this sector is still dirty, this could be the case if
+                               write protection was turned on.  */
+                            if (cache_entry -> fx_cached_sector_buffer_dirty)
+                            {
+
+                                /* Yes, clear the dirty flag.  */
+                                cache_entry -> fx_cached_sector_buffer_dirty =  FX_FALSE;
+
+                                /* Decrement the number of dirty sectors currently in the cache.  */
+                                media_ptr -> fx_media_sector_cache_dirty_count--;
+                                remaining_dirty--;
+                            }
+                        }
+
+                        /* Decrement the number of sectors in the range that have been processed.  */
+                        sectors--;
+                    }
+                    else
+                    {
+
+                        /* Determine if the sector is valid.  */
+                        if (cache_entry -> fx_cached_sector_valid)
+                        {
+
+                            /* Increment the number of still remaining but out of range sectors.  */
+                            remaining_valid++;
+                        }
+                    }
+
+                    /* Determine if invalidation is not required and there are no
+                       more dirty sectors. */
+                    if ((remaining_dirty == 0) && (invalidate == FX_FALSE))
+                    {
+
+                        /* Yes, nothing left to do.  */
+                        break;
+                    }
+
+                    /* Determine if there are any more sectors to process.  */
+                    if ((sectors == 0) && (invalidate == FX_FALSE))
+                    {
+
+                        /* No more sectors required to process.  */
+                        break;
+                    }
+
+                    /* Move to the next cache entry.  */
+                    cache_entry++;
+                }
+
+                /* Move the index to the next position since the bit map can only represent 32
+                   cache entries.  */
+                index =  index + (32 * FX_SECTOR_CACHE_DEPTH);
+            } while (index < cache_size);
+
+            /* Determine if invalidation was required and there are no more valid sectors
+               associated with this bit position.  */
+            if ((invalidate) && (remaining_valid == 0))
+            {
+
+                /* Clear this bit position.  */
+                media_ptr -> fx_media_sector_cache_hashed_sector_valid &=  ~(((ULONG)1) << bit_set);
+            }
+
+            /* Determine if the starting sector is being used for examination of the hash.  */
+            if (use_starting_sector)
+            {
+
+                /* Move to the next sector.  */
+                starting_sector++;
+            }
+            else
+            {
+
+                /* Move to next bit in the map.  */
+                valid_bit_map =  valid_bit_map >> 1;
+
+                /* Increment the set bit marker.  */
+                bit_set++;
+            }
+        }
+    }
+#else
+    FX_PARAMETER_NOT_USED(media_ptr);
+    FX_PARAMETER_NOT_USED(starting_sector);
+    FX_PARAMETER_NOT_USED(sectors);
+    FX_PARAMETER_NOT_USED(invalidate);
+#endif /* FX_DISABLE_CACHE */
+
+    /* If we get here, return successful status to the caller.  */
+    return(FX_SUCCESS);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_logical_sector_read.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_logical_sector_read.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_logical_sector_read.c	(revision 30)
@@ -0,0 +1,647 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Utility                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_utility.h"
+#ifdef FX_ENABLE_FAULT_TOLERANT
+#include "fx_fault_tolerant.h"
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_utility_logical_sector_read                     PORTABLE C      */
+/*                                                           6.2.0        */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function handles logical sector read requests for all FileX    */
+/*    components.  If the logical sector is currently in the logical      */
+/*    sector cache, the function simply sets the appropriate pointer and  */
+/*    returns a successful status to the caller.  Otherwise, physical I/O */
+/*    is requested through the corresponding I/O driver.                  */
+/*                                                                        */
+/*    Note: Conversion of the logical sector is done inside the driver.   */
+/*          This results in a performance boost for FLASH or RAM media    */
+/*          devices.                                                      */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    logical_sector                        Logical sector number         */
+/*    buffer_ptr                            Pointer of receiving buffer   */
+/*    sectors                               Number of sectors to read     */
+/*    sector_type                           Type of sector(s) to read     */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_logical_sector_cache_entry_read                         */
+/*                                          Read logical sector cache     */
+/*    _fx_utility_logical_sector_flush      Flush and invalidate sectors  */
+/*                                          that overlap with non-cache   */
+/*                                          sector I/O.                   */
+/*    _fx_utility_memory_copy               Copy cache sector             */
+/*    _fx_fault_tolerant_read_directory_sector                            */
+/*                                          Read directory sector         */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    FileX System Functions                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            verified memcpy usage, and  */
+/*                                            added conditional to        */
+/*                                            disable cache,              */
+/*                                            resulting in version 6.1    */
+/*  04-02-2021     Bhupendra Naphade        Modified comment(s),          */
+/*                                            updated check for logical   */
+/*                                            sector value,               */
+/*                                            resulting in version 6.1.6  */
+/*  10-31-2022     Tiejun Zhou              Modified comment(s),          */
+/*                                            fixed memory buffer when    */
+/*                                            cache is disabled,          */
+/*                                            resulting in version 6.2.0  */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_utility_logical_sector_read(FX_MEDIA *media_ptr, ULONG64 logical_sector,
+                                      VOID *buffer_ptr, ULONG sectors, UCHAR sector_type)
+{
+#ifndef FX_DISABLE_CACHE
+FX_CACHED_SECTOR *cache_entry;
+FX_CACHED_SECTOR *previous_cache_entry;
+ULONG64           end_sector;
+#endif /* FX_DISABLE_CACHE */
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+UINT              status;
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Determine if the request is for FAT sector.  */
+    if (sector_type == FX_FAT_SECTOR)
+    {
+
+        /* Increment the number of FAT sector reads.  */
+        media_ptr -> fx_media_fat_sector_reads++;
+    }
+
+    /* Increment the number of logical sectors read.  */
+    media_ptr -> fx_media_logical_sector_reads++;
+#endif
+
+    /* Extended port-specific processing macro, which is by default defined to white space.  */
+    FX_UTILITY_LOGICAL_SECTOR_READ_EXTENSION
+
+#ifndef FX_DISABLE_CACHE
+    /* Determine if the request is for the internal media buffer area.  */
+    if ((((UCHAR *)buffer_ptr) >= media_ptr -> fx_media_memory_buffer) &&
+        (((UCHAR *)buffer_ptr) <= media_ptr -> fx_media_sector_cache_end))
+    {
+
+        /* Internal cache buffer is requested.  */
+
+        /* Examine the logical sector cache.  */
+        cache_entry = _fx_utility_logical_sector_cache_entry_read(media_ptr, logical_sector, &previous_cache_entry);
+
+        /* Was the sector found?  */
+        if (cache_entry == FX_NULL)
+        {
+
+            /* Yes, the sector was found. Return success!  */
+            return(FX_SUCCESS);
+        }
+
+        /* At this point, we need to read in a sector from the media.  */
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+        /* Increment the number of logical sectors cache read misses.  */
+        media_ptr -> fx_media_logical_sector_cache_read_misses++;
+#endif
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+        /* If trace is enabled, insert this event into the trace buffer.  */
+        FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_LOG_SECTOR_CACHE_MISS, media_ptr, logical_sector, media_ptr -> fx_media_logical_sector_cache_read_misses, media_ptr -> fx_media_sector_cache_size, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+#else
+
+        /* If trace is enabled, insert this event into the trace buffer.  */
+        FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_LOG_SECTOR_CACHE_MISS, media_ptr, logical_sector, 0, media_ptr -> fx_media_sector_cache_size, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+#endif
+
+        /* First, check and see if the last used entry has been
+           modified.  */
+        if ((cache_entry -> fx_cached_sector_valid) &&
+            (cache_entry -> fx_cached_sector_buffer_dirty))
+        {
+
+            /* Yes, we need to flush this buffer out to the physical media
+               before we read in the new buffer.  */
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+            /* Increment the number of driver write sector(s) requests.  */
+            media_ptr -> fx_media_driver_write_requests++;
+#endif
+
+            /* Build write request to the driver.  */
+            media_ptr -> fx_media_driver_request =          FX_DRIVER_WRITE;
+            media_ptr -> fx_media_driver_status =           FX_IO_ERROR;
+            media_ptr -> fx_media_driver_buffer =           cache_entry -> fx_cached_sector_memory_buffer;
+#ifdef FX_DRIVER_USE_64BIT_LBA
+            media_ptr -> fx_media_driver_logical_sector =   cache_entry -> fx_cached_sector;
+#else
+            media_ptr -> fx_media_driver_logical_sector =   (ULONG)cache_entry -> fx_cached_sector;
+#endif
+            media_ptr -> fx_media_driver_sectors =          1;
+            media_ptr -> fx_media_driver_sector_type =      cache_entry -> fx_cached_sector_type;
+
+            /* Determine if the sector is a data sector or a system sector.  */
+            if (cache_entry -> fx_cached_sector_type != FX_DATA_SECTOR)
+            {
+
+                /* System sector is present.  */
+                media_ptr -> fx_media_driver_system_write =  FX_TRUE;
+            }
+
+            /* If trace is enabled, insert this event into the trace buffer.  */
+            FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_WRITE, media_ptr, cache_entry -> fx_cached_sector, 1, cache_entry -> fx_cached_sector_memory_buffer, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+            /* Invoke the driver to write the sector.  */
+            (media_ptr -> fx_media_driver_entry) (media_ptr);
+
+            /* Clear the system write flag.  */
+            media_ptr -> fx_media_driver_system_write =  FX_FALSE;
+
+            /* Check for successful completion.  */
+            if (media_ptr -> fx_media_driver_status)
+            {
+
+                /* Error writing a cached sector out.  Return the
+                   error status.  */
+                return(media_ptr -> fx_media_driver_status);
+            }
+
+            /* Clear the buffer dirty flag since it has been flushed
+               out.  */
+            cache_entry -> fx_cached_sector_buffer_dirty =  FX_FALSE;
+
+            /* Decrement the number of outstanding dirty cache entries.  */
+            media_ptr -> fx_media_sector_cache_dirty_count--;
+        }
+
+        /* At this point, we can go out and setup this cached sector
+           entry.  */
+
+        /* Compare against logical sector to make sure it is valid.  */
+        if (logical_sector >= media_ptr -> fx_media_total_sectors)
+        {
+            return(FX_SECTOR_INVALID);
+        }
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+        /* Increment the number of driver read sector(s) requests.  */
+        media_ptr -> fx_media_driver_read_requests++;
+#endif
+
+        /* Build Read request to the driver.  */
+        media_ptr -> fx_media_driver_request =          FX_DRIVER_READ;
+        media_ptr -> fx_media_driver_status =           FX_IO_ERROR;
+        media_ptr -> fx_media_driver_buffer =           cache_entry -> fx_cached_sector_memory_buffer;
+#ifdef FX_DRIVER_USE_64BIT_LBA
+        media_ptr -> fx_media_driver_logical_sector =   logical_sector;
+#else
+        media_ptr -> fx_media_driver_logical_sector =   (ULONG)logical_sector;
+#endif
+        media_ptr -> fx_media_driver_sectors =          1;
+        media_ptr -> fx_media_driver_sector_type =      sector_type;
+
+        /* Determine if the sector is a data sector or a system sector.  */
+        if (sector_type == FX_DATA_SECTOR)
+        {
+
+            /* Data sector is present.  */
+            media_ptr -> fx_media_driver_data_sector_read =  FX_TRUE;
+        }
+
+        /* If trace is enabled, insert this event into the trace buffer.  */
+        FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_READ, media_ptr, logical_sector, 1, cache_entry -> fx_cached_sector_memory_buffer, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+        /* Invoke the driver to read the sector.  */
+        (media_ptr -> fx_media_driver_entry) (media_ptr);
+
+        /* Clear data sector is present flag.  */
+        media_ptr -> fx_media_driver_data_sector_read =  FX_FALSE;
+
+        /* Determine if the read was successful.  */
+        if (media_ptr -> fx_media_driver_status == FX_SUCCESS)
+        {
+
+            /* Remember the sector number.  */
+            cache_entry -> fx_cached_sector =  logical_sector;
+
+            /* Make the cache entry valid.  */
+            cache_entry -> fx_cached_sector_valid =  FX_TRUE;
+
+            /* Remember the sector type.  */
+            cache_entry -> fx_cached_sector_type =  sector_type;
+
+            /* Place this entry that the head of the cached sector
+               list.  */
+
+            /* Determine if we need to update the last used list.  */
+            if (previous_cache_entry)
+            {
+
+                /* Yes, the current entry is not at the front of the list
+                   so we need to change the order.  */
+
+                /* Link the previous entry to this entry's next pointer.  */
+                previous_cache_entry -> fx_cached_sector_next_used =
+                    cache_entry -> fx_cached_sector_next_used;
+
+                /* Place this entry at the head of the list.  */
+                cache_entry -> fx_cached_sector_next_used =
+                    media_ptr -> fx_media_sector_cache_list_ptr;
+                media_ptr -> fx_media_sector_cache_list_ptr =  cache_entry;
+            }
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+            if (media_ptr -> fx_media_fault_tolerant_enabled &&
+                (media_ptr -> fx_media_fault_tolerant_state & FX_FAULT_TOLERANT_STATE_STARTED) &&
+                (sector_type == FX_DIRECTORY_SECTOR))
+            {
+
+                /* Read sector from log file. */
+                status = _fx_fault_tolerant_read_directory_sector(media_ptr, logical_sector, cache_entry -> fx_cached_sector_memory_buffer, 1);
+
+                /* Check for successful completion.  */
+                if (status)
+                {
+
+                    /* Return the error status. */
+                    return(status);
+                }
+            }
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+        }
+        else
+        {
+
+            /* Invalidate the cache entry on read errors.  */
+            cache_entry -> fx_cached_sector_valid =  FX_FALSE;
+
+            /* Put all ones in the sector value.  */
+            cache_entry -> fx_cached_sector =  (~(ULONG64)0);
+        }
+
+        /* Simply setup the pointer to this buffer and return.  */
+        media_ptr -> fx_media_memory_buffer =  cache_entry -> fx_cached_sector_memory_buffer;
+
+        /* Return the driver status.  */
+        return(media_ptr -> fx_media_driver_status);
+    }
+#else
+    if ((logical_sector == media_ptr -> fx_media_memory_buffer_sector) && (sectors == 1) && (buffer_ptr == media_ptr -> fx_media_memory_buffer))
+    {
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        if (media_ptr -> fx_media_fault_tolerant_enabled &&
+            (media_ptr -> fx_media_fault_tolerant_state & FX_FAULT_TOLERANT_STATE_STARTED) &&
+            (sector_type == FX_DIRECTORY_SECTOR))
+        {
+
+            /* Read sector from log file. */
+            status = _fx_fault_tolerant_read_directory_sector(media_ptr, logical_sector, buffer_ptr, 1);
+
+            /* Check for successful completion.  */
+            if (status)
+            {
+
+                /* Return the error status. */
+                return(status);
+            }
+        }
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+        return(FX_SUCCESS);
+    }
+#endif
+    else
+    {
+
+        /* Direct I/O to application buffer area.  */
+
+        /* Compare against logical sector to make sure it is valid.  */
+        if ((logical_sector + sectors - 1) > (ULONG)media_ptr -> fx_media_total_sectors)
+        {
+            return(FX_SECTOR_INVALID);
+        }
+
+#ifndef FX_DISABLE_CACHE
+        /* Attempt to fill the beginning of the buffer from cached sectors.  */
+        while (sectors)
+        {
+
+            /* Determine if the sector is in the cache.  */
+            if (_fx_utility_logical_sector_cache_entry_read(media_ptr, logical_sector, &previous_cache_entry))
+            {
+
+                /* Not in the cache - get out of the loop!  */
+                break;
+            }
+
+            /* Yes, sector is in the cache. Copy the data from the cache to the destination buffer.  */
+            _fx_utility_memory_copy(media_ptr -> fx_media_memory_buffer, buffer_ptr, media_ptr -> fx_media_bytes_per_sector); /* Use case of memcpy is verified. */
+
+            /* Advance the destination buffer.  */
+            buffer_ptr =  ((UCHAR *)buffer_ptr) + media_ptr -> fx_media_bytes_per_sector;
+
+            /* Advance the sector and decrement the number of sectors left.  */
+            logical_sector++;
+            sectors--;
+        }
+
+        /* Calculate the end sector.  */
+        end_sector = logical_sector + sectors - 1;
+
+        /* Attempt to fill the end of the buffer from the opposite direction.  */
+        while (sectors)
+        {
+
+            /* Determine if the sector is in the cache.  */
+            if (_fx_utility_logical_sector_cache_entry_read(media_ptr, end_sector, &previous_cache_entry))
+            {
+
+                /* Not in the cache - get out of the loop!  */
+                break;
+            }
+
+            /* Yes, sector is in the cache. Copy the data from the cache to the destination buffer.  */
+            _fx_utility_memory_copy(media_ptr -> fx_media_memory_buffer, /* Use case of memcpy is verified. */
+                                    ((UCHAR *)buffer_ptr) + ((sectors - 1) * media_ptr -> fx_media_bytes_per_sector),
+                                    media_ptr -> fx_media_bytes_per_sector);
+
+            /* Move sector to previous sector and decrement the number of sectors left.  */
+            end_sector--;
+            sectors--;
+        }
+
+        /* Determine if there are still sectors left to read.  */
+        if (sectors == 0)
+        {
+
+            /* No more sectors to read - return success!  */
+            return(FX_SUCCESS);
+        }
+
+        /* Flush and invalidate any entries in the cache that are in this direct I/O read request range.  */
+        _fx_utility_logical_sector_flush(media_ptr, logical_sector, (ULONG64) sectors, FX_TRUE);
+#endif /* FX_DISABLE_CACHE */
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+        /* Increment the number of driver read sector(s) requests.  */
+        media_ptr -> fx_media_driver_read_requests++;
+#endif
+
+        /* Build read request to the driver.  */
+        media_ptr -> fx_media_driver_request =          FX_DRIVER_READ;
+        media_ptr -> fx_media_driver_status =           FX_IO_ERROR;
+        media_ptr -> fx_media_driver_buffer =           buffer_ptr;
+#ifdef FX_DRIVER_USE_64BIT_LBA
+        media_ptr -> fx_media_driver_logical_sector =   logical_sector;
+#else
+        media_ptr -> fx_media_driver_logical_sector =   (ULONG)logical_sector;
+#endif
+        media_ptr -> fx_media_driver_sectors =          sectors;
+        media_ptr -> fx_media_driver_sector_type =      sector_type;
+
+        /* Determine if the sector is a data sector or a system sector.  */
+        if (sector_type == FX_DATA_SECTOR)
+        {
+
+            /* Data sector is present.  */
+            media_ptr -> fx_media_driver_data_sector_read =  FX_TRUE;
+        }
+
+        /* If trace is enabled, insert this event into the trace buffer.  */
+        FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_READ, media_ptr, logical_sector, sectors, buffer_ptr, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+        /* Invoke the driver to read the sector.  */
+        (media_ptr -> fx_media_driver_entry) (media_ptr);
+
+        /* Clear data sector is present flag.  */
+        media_ptr -> fx_media_driver_data_sector_read =  FX_FALSE;
+
+#ifdef FX_DISABLE_CACHE
+        if ((media_ptr -> fx_media_driver_status == FX_SUCCESS) && (sectors == 1) && (buffer_ptr == media_ptr -> fx_media_memory_buffer))
+        {
+            media_ptr -> fx_media_memory_buffer_sector = logical_sector;
+#ifdef FX_ENABLE_FAULT_TOLERANT
+            if (media_ptr -> fx_media_fault_tolerant_enabled &&
+                (media_ptr -> fx_media_fault_tolerant_state & FX_FAULT_TOLERANT_STATE_STARTED) &&
+                (sector_type == FX_DIRECTORY_SECTOR))
+            {
+
+                /* Read sector from log file. */
+                status = _fx_fault_tolerant_read_directory_sector(media_ptr, logical_sector, buffer_ptr, 1);
+
+                /* Check for successful completion.  */
+                if (status)
+                {
+
+                    /* Return the error status. */
+                    return(status);
+                }
+            }
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+            return(FX_SUCCESS);
+        }
+#endif /* FX_DISABLE_CACHE */
+
+#ifndef FX_DISABLE_DIRECT_DATA_READ_CACHE_FILL
+
+        /* Determine if the read was successful and if number of sectors just read will
+           reasonably fit into the cache.  */
+        if ((media_ptr -> fx_media_driver_status == FX_SUCCESS) && (sectors < (media_ptr -> fx_media_sector_cache_size / 4)))
+        {
+
+            /* Yes, read of direct sectors was successful.  */
+
+            /* Copy the sectors directly read into the cache so they are available on
+               subsequent read requests.  */
+            while (sectors)
+            {
+
+                /* Attempt to read the cache entry.  */
+                cache_entry =  _fx_utility_logical_sector_cache_entry_read(media_ptr, logical_sector, &previous_cache_entry);
+
+                /* Extended port-specific processing macro, which is by default defined to white space.  */
+                FX_UTILITY_LOGICAL_SECTOR_READ_EXTENSION_1
+
+                /* At this point, a cache entry should always be present since we invalidated
+                   the cache over this sector range previously. In any case, check for the error
+                   condition.  */
+                if (cache_entry == FX_NULL)
+                {
+
+                    /* This case should never happen, however, if it does simply give up on updating the
+                       cache with the sectors from the direct read.  */
+                    return(FX_SUCCESS);
+                }
+
+                /* Determine if the cache entry is dirty and needs to be written out before it is used.  */
+                if ((cache_entry -> fx_cached_sector_valid) &&
+                    (cache_entry -> fx_cached_sector_buffer_dirty))
+                {
+
+                    /* Yes, we need to flush this buffer out to the physical media
+                       before we read in the new buffer.  */
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+                    /* Increment the number of driver write sector(s) requests.  */
+                    media_ptr -> fx_media_driver_write_requests++;
+#endif
+
+                    /* Build write request to the driver.  */
+                    media_ptr -> fx_media_driver_request =          FX_DRIVER_WRITE;
+                    media_ptr -> fx_media_driver_status =           FX_IO_ERROR;
+                    media_ptr -> fx_media_driver_buffer =           cache_entry -> fx_cached_sector_memory_buffer;
+#ifdef FX_DRIVER_USE_64BIT_LBA
+                    media_ptr -> fx_media_driver_logical_sector =   cache_entry -> fx_cached_sector;
+#else
+                    media_ptr -> fx_media_driver_logical_sector =   (ULONG)cache_entry -> fx_cached_sector;
+#endif
+                    media_ptr -> fx_media_driver_sectors =          1;
+                    media_ptr -> fx_media_driver_sector_type =      cache_entry -> fx_cached_sector_type;
+
+                    /* Only data sectors may be dirty when FX_FAULT_TOLERANT is defined */
+#ifndef FX_FAULT_TOLERANT
+                    /* Determine if the sector is a data sector or a system sector.  */
+                    if (cache_entry -> fx_cached_sector_type != FX_DATA_SECTOR)
+                    {
+
+                        /* System sector is present.  */
+                        media_ptr -> fx_media_driver_system_write =  FX_TRUE;
+                    }
+#endif /* FX_FAULT_TOLERANT */
+
+                    /* If trace is enabled, insert this event into the trace buffer.  */
+                    FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_WRITE, media_ptr, cache_entry -> fx_cached_sector, 1, cache_entry -> fx_cached_sector_memory_buffer, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+                    /* Invoke the driver to write the sector.  */
+                    (media_ptr -> fx_media_driver_entry) (media_ptr);
+
+                    /* Clear the system write flag.  */
+                    media_ptr -> fx_media_driver_system_write =  FX_FALSE;
+
+                    /* Check for successful completion.  */
+                    if (media_ptr -> fx_media_driver_status)
+                    {
+
+                        /* Error writing a cached sector out.  Return the
+                           error status.  */
+                        return(media_ptr -> fx_media_driver_status);
+                    }
+
+                    /* Clear the buffer dirty flag since it has been flushed
+                       out.  */
+                    cache_entry -> fx_cached_sector_buffer_dirty =  FX_FALSE;
+
+                    /* Decrement the number of outstanding dirty cache entries.  */
+                    media_ptr -> fx_media_sector_cache_dirty_count--;
+                }
+
+                /* Now setup the cache entry with information from the new sector.  */
+
+                /* Remember the sector number.  */
+                cache_entry -> fx_cached_sector =  logical_sector;
+
+                /* Make the cache entry valid.  */
+                cache_entry -> fx_cached_sector_valid =  FX_TRUE;
+
+                /* Remember the sector type.  */
+                cache_entry -> fx_cached_sector_type =  sector_type;
+
+                /* Place this entry that the head of the cached sector
+                   list.  */
+
+                /* Determine if we need to update the last used list.  */
+                if (previous_cache_entry)
+                {
+
+                    /* Yes, the current entry is not at the front of the list
+                       so we need to change the order.  */
+
+                    /* Link the previous entry to this entry's next pointer.  */
+                    previous_cache_entry -> fx_cached_sector_next_used =
+                        cache_entry -> fx_cached_sector_next_used;
+
+                    /* Place this entry at the head of the list.  */
+                    cache_entry -> fx_cached_sector_next_used =
+                        media_ptr -> fx_media_sector_cache_list_ptr;
+                    media_ptr -> fx_media_sector_cache_list_ptr =  cache_entry;
+                }
+
+                /* Copy the data from the destination buffer to the cache entry.  */
+                _fx_utility_memory_copy(buffer_ptr, /* Use case of memcpy is verified. */
+                                        cache_entry -> fx_cached_sector_memory_buffer,
+                                        media_ptr -> fx_media_bytes_per_sector);
+
+                /* Advance the destination buffer.  */
+                buffer_ptr =  ((UCHAR *)buffer_ptr) + media_ptr -> fx_media_bytes_per_sector;
+
+                /* Advance the source sector and decrement the sector count.  */
+                logical_sector++;
+                sectors--;
+            }
+        }
+#endif
+
+        /* Return the driver status.  */
+        return(media_ptr -> fx_media_driver_status);
+    }
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_logical_sector_write.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_logical_sector_write.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_logical_sector_write.c	(revision 30)
@@ -0,0 +1,444 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Utility                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_utility.h"
+#ifdef FX_ENABLE_FAULT_TOLERANT
+#include "fx_fault_tolerant.h"
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_utility_logical_sector_write                    PORTABLE C      */
+/*                                                           6.1.6        */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function handles logical sector write requests for all FileX   */
+/*    components.  If the logical sector is currently in the media's      */
+/*    buffer supplied by the caller, the function simply marks the buffer */
+/*    as written to.  Otherwise, physical I/O is requested through the    */
+/*    corresponding I/O driver.                                           */
+/*                                                                        */
+/*    Note: Conversion of the logical sector is done inside the driver.   */
+/*          This results in a performance boost for FLASH or RAM media    */
+/*          devices.                                                      */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    logical_sector                        Logical sector number         */
+/*    buffer_ptr                            Pointer of sector buffer      */
+/*    sectors                               Number of sectors to write    */
+/*    sector_type                           Type of sector(s) to write    */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_logical_sector_flush      Flush and invalidate sectors  */
+/*                                          that overlap with non-cache   */
+/*                                          sector I/O.                   */
+/*    I/O Driver                                                          */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    FileX System Functions                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s), and      */
+/*                                            added conditional to        */
+/*                                            disable cache,              */
+/*                                            resulting in version 6.1    */
+/*  04-02-2021     Bhupendra Naphade        Modified comment(s),          */
+/*                                            updated check for logical   */
+/*                                            sector value,               */
+/*                                            resulting in version 6.1.6  */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_utility_logical_sector_write(FX_MEDIA *media_ptr, ULONG64 logical_sector,
+                                       VOID *buffer_ptr, ULONG sectors, UCHAR sector_type)
+{
+
+#ifndef FX_DISABLE_CACHE
+FX_CACHED_SECTOR *cache_entry;
+UINT              cache_size;
+UINT              index;
+UINT              i;
+UCHAR             cache_found = FX_FALSE;
+#endif /* FX_DISABLE_CACHE */
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Determine if the request is for FAT sector.  */
+    if (sector_type == FX_FAT_SECTOR)
+    {
+
+        /* Increment the number of FAT sector writes.  */
+        media_ptr -> fx_media_fat_sector_writes++;
+    }
+
+    /* Increment the number of logical sectors written.  */
+    media_ptr -> fx_media_logical_sector_writes++;
+#endif
+
+    /* Extended port-specific processing macro, which is by default defined to white space.  */
+    FX_UTILITY_LOGICAL_SECTOR_WRITE_EXTENSION
+
+#ifndef FX_DISABLE_CACHE
+    /* Determine if the request is from the internal media buffer area.  */
+    if ((((UCHAR *)buffer_ptr) >= media_ptr -> fx_media_memory_buffer) &&
+        (((UCHAR *)buffer_ptr) <= media_ptr -> fx_media_sector_cache_end))
+    {
+
+        /* Internal cache buffer is requested.  */
+
+        /* Determine if the logical sector cache access should use the hash function.  */
+        if (media_ptr -> fx_media_sector_cache_hashed)
+        {
+
+            /* Calculate the area of the cache for this logical sector.  */
+            index =  (ULONG)(logical_sector & media_ptr -> fx_media_sector_cache_hash_mask) * FX_SECTOR_CACHE_DEPTH;
+
+            /* Build a pointer to the cache entry.  */
+            cache_entry =  &(media_ptr -> fx_media_sector_cache[index]);
+
+            for (i = 0; i < FX_SECTOR_CACHE_DEPTH; i++, cache_entry++)
+            {
+
+
+                /* Determine if the logical sector is in the cache - assuming the depth of the
+                   sector cache is 4 entries.  */
+                if ((cache_entry -> fx_cached_sector_valid) && (cache_entry -> fx_cached_sector == logical_sector))
+                {
+                    cache_found = FX_TRUE;
+                    break;
+                }
+            }
+        }
+        else
+        {
+
+            /* Search for an entry in the cache that matches this request.  */
+            cache_size =            media_ptr -> fx_media_sector_cache_size;
+            cache_entry =           media_ptr -> fx_media_sector_cache_list_ptr;
+
+            /* Look at the cache entries until a match is found or the end of
+               the cache is reached.  */
+            while (cache_size--)
+            {
+
+                /* Determine if the requested sector has been found.  */
+                if ((cache_entry -> fx_cached_sector_valid) && (cache_entry -> fx_cached_sector == logical_sector))
+                {
+                    cache_found = FX_TRUE;
+                    break;
+                }
+
+                /* Otherwise, we have not found the cached entry yet.  */
+
+                /* If there are more entries, move to the next one.  */
+                if (cache_entry -> fx_cached_sector_next_used)
+                {
+
+                    /* Move to the next cache entry.  */
+                    cache_entry =  cache_entry -> fx_cached_sector_next_used;
+                }
+            }
+        }
+
+#ifdef FX_ENABLE_FAULT_TOLERANT
+        if (media_ptr -> fx_media_fault_tolerant_enabled &&
+            (media_ptr -> fx_media_fault_tolerant_state & FX_FAULT_TOLERANT_STATE_STARTED) &&
+            (sector_type == FX_DATA_SECTOR) &&
+            !(cache_found && (cache_entry -> fx_cached_sector_memory_buffer == buffer_ptr)))
+        {
+
+            /* Special use case for file write when fault tolerant is enabled. */
+            /* Data are read from one sector but write to another sector. */
+            /* Need to invalidate both of original and new caches. */
+            if (cache_found)
+            {
+
+                /* Invalidate the new cache. */
+                cache_entry -> fx_cached_sector_valid = FX_FALSE;
+                cache_found = FX_FALSE;
+            }
+
+            /* Search for original cache.  */
+            cache_size =            media_ptr -> fx_media_sector_cache_size;
+            cache_entry =           media_ptr -> fx_media_sector_cache_list_ptr;
+
+            /* Look at the cache entries until a match is found or the end of
+               the cache is reached.  */
+            while (cache_size--)
+            {
+
+                /* Determine if the original sector has been found.  */
+                if ((cache_entry -> fx_cached_sector_valid) &&
+                    (cache_entry -> fx_cached_sector_memory_buffer == buffer_ptr))
+                {
+
+                    /* Invalidate the original cache. */
+                    cache_entry -> fx_cached_sector_valid = FX_FALSE;
+                    break;
+                }
+
+                /* Otherwise, we have not found the cached entry yet.  */
+
+                /* If there are more entries, move to the next one.  */
+                if (cache_entry -> fx_cached_sector_next_used)
+                {
+
+                    /* Move to the next cache entry.  */
+                    cache_entry =  cache_entry -> fx_cached_sector_next_used;
+                }
+            }
+        }
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
+        if (cache_found)
+        {
+
+            /* Yes, we found a match.  */
+
+#ifdef FX_FAULT_TOLERANT
+
+            /* Check for a system sector. Data sector fault tolerance is selected with
+               the FX_FAULT_TOLERANT_DATA option.  */
+            if (sector_type != FX_DATA_SECTOR)
+            {
+
+                /* With the fault tolerant option enabled, system sectors are written immediately to
+                   the media.  */
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+                /* Increment the number of driver write sector(s) requests.  */
+                media_ptr -> fx_media_driver_write_requests++;
+#endif
+
+                /* Build write request to the driver.  */
+                media_ptr -> fx_media_driver_request =          FX_DRIVER_WRITE;
+                media_ptr -> fx_media_driver_status =           FX_IO_ERROR;
+                media_ptr -> fx_media_driver_buffer =           cache_entry -> fx_cached_sector_memory_buffer;
+#ifdef FX_DRIVER_USE_64BIT_LBA
+                media_ptr -> fx_media_driver_logical_sector =   logical_sector;
+#else
+                media_ptr -> fx_media_driver_logical_sector =   (ULONG)logical_sector;
+#endif
+                media_ptr -> fx_media_driver_sectors =          1;
+                media_ptr -> fx_media_driver_sector_type =      sector_type;
+
+                /* Yes, a system sector write is present so set the flag.  The driver
+                   can use this flag to make extra safeguards in writing the sector
+                   out, yielding more fault tolerance.  */
+                media_ptr -> fx_media_driver_system_write =  FX_TRUE;
+
+                /* If trace is enabled, insert this event into the trace buffer.  */
+                FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_WRITE, media_ptr, logical_sector, 1, cache_entry -> fx_cached_sector_memory_buffer, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+                /* Invoke the driver to write the sector(s).  */
+                (media_ptr -> fx_media_driver_entry) (media_ptr);
+
+                /* Clear the system write flag.  */
+                media_ptr -> fx_media_driver_system_write =  FX_FALSE;
+
+                /* Return success.  */
+                return(media_ptr -> fx_media_driver_status);
+            }
+#endif
+
+            /* Determine if this is the first write of this logical sector.  */
+            if (cache_entry -> fx_cached_sector_buffer_dirty == FX_FALSE)
+            {
+
+                /* Yes, increment the number of outstanding dirty sectors.  */
+                media_ptr -> fx_media_sector_cache_dirty_count++;
+
+                /* Simply mark this entry as dirty.  */
+                cache_entry -> fx_cached_sector_buffer_dirty =  FX_TRUE;
+            }
+
+            /* Don't bother updating the cache linked list since writes are
+               preceded by reads anyway.  */
+
+            /* Success, return to caller immediately!  */
+            return(FX_SUCCESS);
+        }
+
+
+        /* Okay, so if we are here the request must be for the additional FAT writes, since this is the
+           only time a write request is made without a preceding read request.  */
+
+        /* Is the logical sector valid?  */
+        if ((logical_sector == 0) || (logical_sector == ((ULONG)0xFFFFFFFF)))
+        {
+            return(FX_SECTOR_INVALID);
+        }
+
+        /* Compare logical sector against total sectors to make sure it is valid.  */
+        if ((logical_sector + sectors - 1) >= media_ptr -> fx_media_total_sectors)
+        {
+            return(FX_SECTOR_INVALID);
+        }
+
+        /* Just write the buffer to the media.  */
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+        /* Increment the number of driver write sector(s) requests.  */
+        media_ptr -> fx_media_driver_write_requests++;
+#endif
+
+        /* Build write request to the driver.  */
+        media_ptr -> fx_media_driver_request =          FX_DRIVER_WRITE;
+        media_ptr -> fx_media_driver_status =           FX_IO_ERROR;
+        media_ptr -> fx_media_driver_buffer =           buffer_ptr;
+#ifdef FX_DRIVER_USE_64BIT_LBA
+        media_ptr -> fx_media_driver_logical_sector =   logical_sector;
+#else
+        media_ptr -> fx_media_driver_logical_sector =   (ULONG)logical_sector;
+#endif
+        media_ptr -> fx_media_driver_sectors =          sectors;
+        media_ptr -> fx_media_driver_sector_type =      sector_type;
+
+        /* Determine if the system write flag needs to be set.  */
+        if (sector_type != FX_DATA_SECTOR)
+        {
+
+            /* Yes, a system sector write is present so set the flag.  The driver
+               can use this flag to make extra safeguards in writing the sector
+               out, yielding more fault tolerance.  */
+            media_ptr -> fx_media_driver_system_write =  FX_TRUE;
+        }
+
+        /* If trace is enabled, insert this event into the trace buffer.  */
+        FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_WRITE, media_ptr, logical_sector, sectors, buffer_ptr, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+        /* Invoke the driver to write the sector(s).  */
+        (media_ptr -> fx_media_driver_entry) (media_ptr);
+
+        /* Clear the system write flag.  */
+        media_ptr -> fx_media_driver_system_write =  FX_FALSE;
+
+        /* Check for successful completion.  */
+        if (media_ptr -> fx_media_driver_status)
+        {
+
+            /* Error writing a internal sector out.  Return the
+               error status.  */
+            return(media_ptr -> fx_media_driver_status);
+        }
+
+        /* At this point, we have a successful write.  */
+        return(FX_SUCCESS);
+    }
+    else
+#endif /* FX_DISABLE_CACHE */
+    {
+
+        /* Otherwise, the write request is being made directly from an application
+           buffer. Determine if the logical sector is valid.  */
+
+        /* Is the logical sector valid? */
+        if ((logical_sector == 0) || (logical_sector == ((ULONG)0xFFFFFFFF)))
+        {
+            return(FX_SECTOR_INVALID);
+        }
+
+        /* Compare logical sector against total sectors to make sure it is valid.  */
+        if ((logical_sector + sectors - 1) >= media_ptr -> fx_media_total_sectors)
+        {
+            return(FX_SECTOR_INVALID);
+        }
+
+        /* Flush and invalidate for any entries in the cache that are in this direct I/O read request range.  */
+        _fx_utility_logical_sector_flush(media_ptr, logical_sector, (ULONG64) sectors, FX_TRUE);
+
+#ifdef FX_DISABLE_CACHE
+        if ((logical_sector <= media_ptr -> fx_media_memory_buffer_sector) && (logical_sector + sectors >= media_ptr -> fx_media_memory_buffer_sector))
+        {
+            media_ptr -> fx_media_memory_buffer_sector = (ULONG64)-1;
+        }
+#endif /* FX_DISABLE_CACHE */
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+        /* Increment the number of driver write sector(s) requests.  */
+        media_ptr -> fx_media_driver_write_requests++;
+#endif
+
+        /* Build request to the driver.  */
+        media_ptr -> fx_media_driver_request =          FX_DRIVER_WRITE;
+        media_ptr -> fx_media_driver_status =           FX_IO_ERROR;
+        media_ptr -> fx_media_driver_buffer =           buffer_ptr;
+#ifdef FX_DRIVER_USE_64BIT_LBA
+        media_ptr -> fx_media_driver_logical_sector =   logical_sector;
+#else
+        media_ptr -> fx_media_driver_logical_sector =   (ULONG)logical_sector;
+#endif
+        media_ptr -> fx_media_driver_sectors =          sectors;
+        media_ptr -> fx_media_driver_sector_type =      sector_type;
+
+        /* Determine if the system write flag needs to be set.  */
+        if (sector_type != FX_DATA_SECTOR)
+        {
+
+            /* Yes, a system sector write is present so set the flag.  The driver
+               can use this flag to make extra safeguards in writing the sector
+               out, yielding more fault tolerance.  */
+            media_ptr -> fx_media_driver_system_write =  FX_TRUE;
+        }
+
+        /* If trace is enabled, insert this event into the trace buffer.  */
+        FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_WRITE, media_ptr, logical_sector, sectors, buffer_ptr, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+        /* Invoke the driver to write the sector(s).  */
+        (media_ptr -> fx_media_driver_entry) (media_ptr);
+
+        /* Clear the system write flag.  */
+        media_ptr -> fx_media_driver_system_write =  FX_FALSE;
+
+        /* Return driver status.  */
+        return(media_ptr -> fx_media_driver_status);
+    }
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_memory_copy.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_memory_copy.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_memory_copy.c	(revision 30)
@@ -0,0 +1,89 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Utility                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_utility.h"
+#include "string.h"
+
+
+/* Remove any previous remapping for memory copy when compiling this
+   module.  */
+
+#undef _fx_utility_memory_copy
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_utility_memory_copy                             PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function copies the specified number of bytes from the source  */
+/*    to the destination.                                                 */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    source_ptr                            Source memory pointer         */
+/*    dest_ptr                              Destination memory pointer    */
+/*    size                                  number of bytes to copy       */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    FileX System Functions                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s), verified */
+/*                                            memcpy usage,               */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+VOID  _fx_utility_memory_copy(UCHAR *source_ptr, UCHAR *dest_ptr, ULONG size)
+{
+
+    /* Copy the memory.  */
+    memcpy(dest_ptr, source_ptr, size); /* Use case of memcpy is verified. */
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_memory_set.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_memory_set.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_memory_set.c	(revision 30)
@@ -0,0 +1,93 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Utility                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_utility.h"
+#include "string.h"
+
+
+/* Remove any previous remapping for memory copy when compiling this
+   module.  */
+
+#undef _fx_utility_memory_set
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_utility_memory_set                              PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function copies the specified number of bytes from the source  */
+/*    to the destination.                                                 */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    dest_ptr                              Destination memory pointer    */
+/*    value                                 Value to fill                 */
+/*    size                                  Number of bytes to set        */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    FileX System Functions                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+VOID  _fx_utility_memory_set(UCHAR *dest_ptr, UCHAR value, ULONG size)
+{
+
+    /* Loop to set memory.  */
+    while (size--)
+    {
+
+        /* Set byte.  */
+        *dest_ptr++ =  value;
+    }
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_string_length_get.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_string_length_get.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_string_length_get.c	(revision 30)
@@ -0,0 +1,94 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Utility                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_utility.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_utility_string_length_get                       PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function returns length of string up to the maximum length.    */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    string                                Pointer to string             */
+/*    max_length                            Maximum length which can be   */
+/*                                            returned by function        */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return length of string                                             */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    _fx_directory_exFAT_unicode_entry_write                             */
+/*    _fx_directory_exFAT_free_search                                     */
+/*    _fx_utility_absolute_path_get         Get absolute path             */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_utility_string_length_get(CHAR *string, UINT max_length)
+{
+
+UINT length;
+
+    /* Initialize length to 0.  */
+    length = 0;
+
+    /* Loop to calculate the length.  */
+    while (string[length] && (length < max_length))
+    {
+
+        /* Increment the length (index).  */
+        length++;
+    }
+
+    /* Return length.  */
+    return(length);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_token_length_get.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_token_length_get.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fx_utility_token_length_get.c	(revision 30)
@@ -0,0 +1,95 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Utility                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#ifdef FX_ENABLE_EXFAT
+#include "fx_utility.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_utility_token_length_get                        PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function returns the length of the next part of the file       */
+/*    name.                                                               */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    path                                  Base (current) path           */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    length                                Length of the string          */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    _fx_utility_absolute_path_get         Get absolute path             */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_utility_token_length_get(CHAR *path)
+{
+
+UINT length;
+
+
+    /* Initialize the length to 0.  */
+    length =  0;
+
+    /* Walk to the next sub-directory break.  */
+    while (path[length] && (path[length] != '\\') && (path[length] != '/') && (length < FX_MAXIMUM_PATH))
+    {
+
+        /* Increment length (index).  */
+        length++;
+    }
+
+    /* Return length.  */
+    return(length);
+}
+
+#endif
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_attributes_read.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_attributes_read.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_attributes_read.c	(revision 30)
@@ -0,0 +1,96 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_directory.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_directory_attributes_read                      PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the directory attributes read    */
+/*    call.                                                               */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    directory_name                        Directory name pointer        */
+/*    attributes_ptr                        Return attributes pointer     */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_attributes_read         Actual read directory         */
+/*                                            attributes service          */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_directory_attributes_read(FX_MEDIA *media_ptr, CHAR *directory_name, UINT *attributes_ptr)
+{
+
+UINT status;
+
+    /* Check for a null media or attributes pointer.  */
+    if ((media_ptr == FX_NULL) || (attributes_ptr == FX_NULL))
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual read file attributes service.  */
+    status =  _fx_directory_attributes_read(media_ptr, directory_name, attributes_ptr);
+
+    /* File attribute read is complete, return status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_attributes_set.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_attributes_set.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_attributes_set.c	(revision 30)
@@ -0,0 +1,104 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_directory.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_directory_attributes_set                       PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the directory attribute set      */
+/*    call.                                                               */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    directory_name                        Directory name pointer        */
+/*    attributes                            New file attributes           */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_attributes_set          Actual directory attributes   */
+/*                                            set service                 */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_directory_attributes_set(FX_MEDIA *media_ptr, CHAR *directory_name, UINT attributes)
+{
+
+UINT status;
+
+
+    /* Check for a null media pointer.  */
+    if (media_ptr == FX_NULL)
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for invalid attributes.  */
+    if ((INT)attributes & ~(FX_DIRECTORY | FX_READ_ONLY | FX_HIDDEN | FX_SYSTEM | FX_ARCHIVE))
+    {
+        return(FX_INVALID_ATTR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual set attributes service.  */
+    status =  _fx_directory_attributes_set(media_ptr, directory_name, attributes);
+
+    /* File attribute set is complete, return status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_create.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_create.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_create.c	(revision 30)
@@ -0,0 +1,95 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_directory.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_directory_create                               PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the directory create call.       */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    directory_name                        Directory name                */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_create                  Actual directory create call  */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_directory_create(FX_MEDIA *media_ptr, CHAR *directory_name)
+{
+
+UINT status;
+
+
+    /* Check for a null media pointer.  */
+    if (media_ptr == FX_NULL)
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual directory create service.  */
+    status =  _fx_directory_create(media_ptr, directory_name);
+
+    /* Directory create is complete, return status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_default_get.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_default_get.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_default_get.c	(revision 30)
@@ -0,0 +1,97 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_directory.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_directory_default_get                          PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the directory default get call.  */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    return_path_name                      Destination string pointer    */
+/*                                            address                     */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_default_get             Actual default directory get  */
+/*                                            service                     */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_directory_default_get(FX_MEDIA *media_ptr, CHAR **return_path_name)
+{
+
+UINT status;
+
+
+    /* Check for a null media pointer or null destination for the default path.  */
+    if ((media_ptr == FX_NULL) || (return_path_name == FX_NULL))
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual default directory get service.  */
+    status =  _fx_directory_default_get(media_ptr, return_path_name);
+
+    /* Return default directory get status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_default_get_copy.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_default_get_copy.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_default_get_copy.c	(revision 30)
@@ -0,0 +1,97 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_directory.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_directory_default_get_copy                     PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the directory default get copy   */
+/*    call.                                                               */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    return_path_name_buffer               Destination buffer for name   */
+/*    return_path_name_buffer_size          Size of buffer pointed to by  */
+/*                                            return_path_name_buffer     */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_directory_default_get_copy(FX_MEDIA *media_ptr, CHAR *return_path_name_buffer, UINT return_path_name_buffer_size)
+{
+
+UINT    status;
+
+
+    /* Check for a null media pointer or name buffer pointer.  */
+    if ((media_ptr == FX_NULL) || (return_path_name_buffer == FX_NULL))
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual default directory get copy service.  */
+    status =  _fx_directory_default_get_copy(media_ptr, return_path_name_buffer, return_path_name_buffer_size);
+
+    /* Return successful status.  */
+    return(status);
+}
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_default_set.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_default_set.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_default_set.c	(revision 30)
@@ -0,0 +1,97 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_directory.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_directory_default_set                          PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the default directory set call.  */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    new_path_name                         New path to set current       */
+/*                                            working directory to        */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_default_set             Actual default directory set  */
+/*                                            service                     */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_directory_default_set(FX_MEDIA *media_ptr, CHAR *new_path_name)
+{
+
+UINT status;
+
+
+    /* Check for a null media pointer.  */
+    if (media_ptr == FX_NULL)
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual default directory set service.  */
+    status =  _fx_directory_default_set(media_ptr, new_path_name);
+
+    /* Default directory set is complete, return status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_delete.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_delete.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_delete.c	(revision 30)
@@ -0,0 +1,94 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_directory.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_directory_delete                               PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the directory delete call.       */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    directory_name                        Directory name to delete      */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_delete                  Actual directory delete call  */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_directory_delete(FX_MEDIA *media_ptr, CHAR *directory_name)
+{
+
+UINT status;
+
+
+    /* Check for a null media pointer.  */
+    if (media_ptr == FX_NULL)
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual directory delete service.  */
+    status =  _fx_directory_delete(media_ptr, directory_name);
+
+    /* Directory delete is complete, return status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_first_entry_find.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_first_entry_find.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_first_entry_find.c	(revision 30)
@@ -0,0 +1,96 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_directory.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_directory_first_entry_find                     PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the directory find first call.   */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    directory_name                        Destination for directory     */
+/*                                            name                        */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_first_entry_find        Actual first find service     */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_directory_first_entry_find(FX_MEDIA *media_ptr, CHAR *directory_name)
+{
+
+UINT status;
+
+
+    /* Check for a null media pointer.  */
+    if (media_ptr == FX_NULL)
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual directory find first service.  */
+    status =  _fx_directory_first_entry_find(media_ptr, directory_name);
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_first_full_entry_find.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_first_full_entry_find.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_first_full_entry_find.c	(revision 30)
@@ -0,0 +1,108 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_directory.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_directory_first_full_entry_find                PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the directory find first full    */
+/*    entry call.                                                         */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    directory_name                        Destination for directory     */
+/*                                            name                        */
+/*    attributes                            Destination for attributes    */
+/*    size                                  Destination for size          */
+/*    year                                  Destination for year          */
+/*    month                                 Destination for month         */
+/*    day                                   Destination for day           */
+/*    hour                                  Destination for hour          */
+/*    minute                                Destination for minute        */
+/*    second                                Destination for second        */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_first_full_entry_find   Actual first find service     */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_directory_first_full_entry_find(FX_MEDIA *media_ptr,
+                                           CHAR *directory_name, UINT *attributes, ULONG *size,
+                                           UINT *year, UINT *month, UINT *day, UINT *hour, UINT *minute, UINT *second)
+{
+
+UINT status;
+
+
+    /* Check for a null media pointer.  */
+    if (media_ptr == FX_NULL)
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual directory find first full entry service.  */
+    status =  _fx_directory_first_full_entry_find(media_ptr, directory_name,
+                                                  attributes, size, year, month, day, hour, minute, second);
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_information_get.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_information_get.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_information_get.c	(revision 30)
@@ -0,0 +1,111 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_directory.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_directory_information_get                      PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the directory information        */
+/*    get call.                                                           */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    directory_name                        Directory name pointer        */
+/*    attributes                            Pointer to attributes         */
+/*    size                                  Pointer to size               */
+/*    year                                  Pointer to year               */
+/*    month                                 Pointer to month              */
+/*    day                                   Pointer to day                */
+/*    hour                                  Pointer to hour               */
+/*    minute                                Pointer to minute             */
+/*    second                                Pointer to second             */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_information_get         Actual directory information  */
+/*                                            get service                 */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_directory_information_get(FX_MEDIA *media_ptr, CHAR *directory_name,
+                                     UINT *attributes, ULONG *size,
+                                     UINT *year, UINT *month, UINT *day,
+                                     UINT *hour, UINT *minute, UINT *second)
+{
+
+UINT status;
+
+
+    /* Check for a null media pointer or all null return parameter pointers.  */
+    if ((media_ptr == FX_NULL) ||
+        ((attributes == FX_NULL) && (size == FX_NULL) && (year == FX_NULL) && (month == FX_NULL) &&
+         (day == FX_NULL) && (hour == FX_NULL) && (minute == FX_NULL) && (second == FX_NULL)))
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual directory information get service.  */
+    status =  _fx_directory_information_get(media_ptr, directory_name, attributes, size,
+                                            year, month, day, hour, minute, second);
+
+    /* Directory information get is complete, return status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_local_path_clear.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_local_path_clear.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_local_path_clear.c	(revision 30)
@@ -0,0 +1,92 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_file.h"
+#include "fx_utility.h"
+#include "fx_directory.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_directory_local_path_clear                     PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the local path clear call.       */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_local_path_set          Actual core service call      */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_directory_local_path_clear(FX_MEDIA *media_ptr)
+{
+
+UINT status;
+
+
+    /* Check for a null media pointer.  */
+    if (media_ptr == FX_NULL)
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Call actual local path clear service.  */
+    status =  _fx_directory_local_path_clear(media_ptr);
+
+    /* Return status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_local_path_get.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_local_path_get.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_local_path_get.c	(revision 30)
@@ -0,0 +1,93 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_file.h"
+#include "fx_utility.h"
+#include "fx_directory.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_directory_local_path_get                       PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the local path get call.         */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    return_path_name                      Return local path name        */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_local_path_get          Actual core service call      */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_directory_local_path_get(FX_MEDIA *media_ptr, CHAR **return_path_name)
+{
+
+UINT status;
+
+
+    /* Check for a null media pointer or null destination for the default path.  */
+    if ((media_ptr == FX_NULL) || (return_path_name == FX_NULL))
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Call actual local path get service.  */
+    status =  _fx_directory_local_path_get(media_ptr, return_path_name);
+
+    /* Return status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_local_path_get_copy.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_local_path_get_copy.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_local_path_get_copy.c	(revision 30)
@@ -0,0 +1,95 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_directory.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_directory_local_path_get_copy                  PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the local path get copy call.    */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    return_path_name_buffer               Destination buffer for name   */
+/*    return_path_name_buffer_size          Size of buffer pointed to by  */
+/*                                            return_path_name_buffer     */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_directory_local_path_get_copy(FX_MEDIA *media_ptr, CHAR *return_path_name_buffer, UINT return_path_name_buffer_size)
+{
+
+UINT    status;
+
+
+    /* Check for a null media pointer or name buffer pointer.  */
+    if ((media_ptr == FX_NULL) || (return_path_name_buffer == FX_NULL))
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual default directory get copy service.  */
+    status =  _fx_directory_local_path_get_copy(media_ptr, return_path_name_buffer, return_path_name_buffer_size);
+
+    /* Return successful status.  */
+    return(status);
+}
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_local_path_restore.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_local_path_restore.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_local_path_restore.c	(revision 30)
@@ -0,0 +1,93 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_file.h"
+#include "fx_utility.h"
+#include "fx_directory.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_directory_local_path_restore                   PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the local path restore call.     */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    local_path_ptr                        Local path control block ptr  */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fxe_directory_local_path_restore     Actual core service call      */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_directory_local_path_restore(FX_MEDIA *media_ptr, FX_LOCAL_PATH *local_path_ptr)
+{
+
+UINT status;
+
+
+    /* Check for a null media pointer or a null local path.  */
+    if ((media_ptr == FX_NULL) || (local_path_ptr == FX_NULL))
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Call actual local path restore service.  */
+    status =  _fx_directory_local_path_restore(media_ptr, local_path_ptr);
+
+    /* Return status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_local_path_set.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_local_path_set.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_local_path_set.c	(revision 30)
@@ -0,0 +1,97 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_file.h"
+#include "fx_utility.h"
+#include "fx_directory.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_directory_local_path_set                       PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the local path set call.         */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    local_path_ptr                        Local path control block ptr  */
+/*    new_path_name                         New path to set current local */
+/*                                            working directory to        */
+/*    local_path_control_block_size         Size of the FX_LOCAL_PATH     */
+/*                                            structure                   */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_local_path_set          Actual core service call      */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_directory_local_path_set(FX_MEDIA *media_ptr, FX_LOCAL_PATH *local_path_ptr, CHAR *new_path_name, UINT local_path_control_block_size)
+{
+
+UINT status;
+
+
+    /* Check for a null media pointer or null local path.  */
+    if ((media_ptr == FX_NULL) || (local_path_ptr == FX_NULL) || (local_path_control_block_size != sizeof(FX_LOCAL_PATH)))
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Call actual local path set service.  */
+    status =  _fx_directory_local_path_set(media_ptr, local_path_ptr, new_path_name);
+
+    /* Return status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_long_name_get.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_long_name_get.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_long_name_get.c	(revision 30)
@@ -0,0 +1,97 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_directory.h"
+
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_directory_long_name_get                        PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the long name get service.       */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    short_file_name                       Pointer to short (8.3) name   */
+/*    long_file_name                        Pointer to long (max 255) name*/
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_long_name_get           Actual long name get service  */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_directory_long_name_get(FX_MEDIA *media_ptr, CHAR *short_file_name, CHAR *long_file_name)
+{
+
+UINT status;
+
+
+    /* Check for a NULL media or file name pointer.  */
+    if ((media_ptr == FX_NULL) || (short_file_name == FX_NULL) || (long_file_name == FX_NULL))
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual long name get service.  */
+    status =  _fx_directory_long_name_get(media_ptr, short_file_name, long_file_name);
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_long_name_get_extended.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_long_name_get_extended.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_long_name_get_extended.c	(revision 30)
@@ -0,0 +1,104 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_directory.h"
+
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_directory_long_name_get_extended               PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the long name get service.       */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    short_file_name                       Pointer to short (8.3) name   */
+/*    long_file_name                        Pointer to long (max 255) name*/
+/*    long_file_name_buffer_length          Buffer length for long name   */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_long_name_get_extended  Actual long name get service  */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_directory_long_name_get_extended(FX_MEDIA *media_ptr, CHAR *short_file_name, CHAR *long_file_name, UINT long_file_name_buffer_length)
+{
+
+UINT status;
+
+
+    /* Check for a NULL media or file name pointer.  */
+    if ((media_ptr == FX_NULL) || (short_file_name == FX_NULL) || (long_file_name == FX_NULL))
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for zero length buffer.  */
+    if (long_file_name_buffer_length == 0)
+    {
+        return(FX_BUFFER_ERROR);
+    }
+    
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual long name get service.  */
+    status =  _fx_directory_long_name_get_extended(media_ptr, short_file_name, long_file_name, long_file_name_buffer_length);
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_name_test.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_name_test.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_name_test.c	(revision 30)
@@ -0,0 +1,96 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_directory.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_directory_name_test                            PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the directory name test call.    */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    directory_name                        Directory name pointer        */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_name_test               Actual directory name test    */
+/*                                            service                     */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_directory_name_test(FX_MEDIA *media_ptr, CHAR *directory_name)
+{
+
+UINT status;
+
+
+    /* Check for a null media pointer.  */
+    if (media_ptr == FX_NULL)
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual directory name test service.  */
+    status =  _fx_directory_name_test(media_ptr, directory_name);
+
+    /* Directory name test is complete, return status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_next_entry_find.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_next_entry_find.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_next_entry_find.c	(revision 30)
@@ -0,0 +1,96 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_directory.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_directory_next_entry_find                      PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks the next directory entry find call for errors. */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    directory_name                        Destination for directory     */
+/*                                            name                        */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_next_entry_find         Actual entry find service     */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_directory_next_entry_find(FX_MEDIA *media_ptr, CHAR *directory_name)
+{
+
+UINT status;
+
+
+    /* Check for a null media pointer.  */
+    if (media_ptr == FX_NULL)
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual next directory entry find service.  */
+    status =  _fx_directory_next_entry_find(media_ptr, directory_name);
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_next_full_entry_find.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_next_full_entry_find.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_next_full_entry_find.c	(revision 30)
@@ -0,0 +1,108 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_directory.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_directory_next_full_entry_find                 PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks the next directory full entry find call for    */
+/*    errors.                                                             */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    directory_name                        Destination for directory     */
+/*                                            name                        */
+/*    attributes                            Destination for attributes    */
+/*    size                                  Destination for size          */
+/*    year                                  Destination for year          */
+/*    month                                 Destination for month         */
+/*    day                                   Destination for day           */
+/*    hour                                  Destination for hour          */
+/*    minute                                Destination for minute        */
+/*    second                                Destination for second        */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_next_full_entry_find    Actual full entry find service*/
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_directory_next_full_entry_find(FX_MEDIA *media_ptr,
+                                          CHAR *directory_name, UINT *attributes, ULONG *size,
+                                          UINT *year, UINT *month, UINT *day, UINT *hour, UINT *minute, UINT *second)
+{
+
+UINT status;
+
+
+    /* Check for a null media pointer.  */
+    if (media_ptr == FX_NULL)
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual next directory full entry find service.  */
+    status =  _fx_directory_next_full_entry_find(media_ptr, directory_name,
+                                                 attributes, size, year, month, day, hour, minute, second);
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_rename.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_rename.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_rename.c	(revision 30)
@@ -0,0 +1,96 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_directory.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_directory_rename                               PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the directory rename call.       */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    old_directory_name                    Old file directory pointer    */
+/*    new_directory_name                    New file directory pointer    */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_rename                  Actual directory rename call  */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_directory_rename(FX_MEDIA *media_ptr, CHAR *old_directory_name, CHAR *new_directory_name)
+{
+
+UINT status;
+
+
+    /* Check for a null media pointer.  */
+    if (media_ptr == FX_NULL)
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual directory rename service.  */
+    status =  _fx_directory_rename(media_ptr, old_directory_name, new_directory_name);
+
+    /* Directory rename is complete, return status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_short_name_get.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_short_name_get.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_short_name_get.c	(revision 30)
@@ -0,0 +1,97 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_directory.h"
+
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_directory_short_name_get                       PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the short name get service.      */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    long_file_name                        Pointer to long (max 255) name*/
+/*    short_file_name                       Pointer to short (8.3) name   */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_short_name_get          Actual short name get service */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_directory_short_name_get(FX_MEDIA *media_ptr, CHAR *long_file_name, CHAR *short_file_name)
+{
+
+UINT status;
+
+
+    /* Check for a NULL media or file name pointer.  */
+    if ((media_ptr == FX_NULL) || (short_file_name == FX_NULL) || (long_file_name == FX_NULL))
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual short name get service.  */
+    status =  _fx_directory_short_name_get(media_ptr, long_file_name, short_file_name);
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_short_name_get_extended.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_short_name_get_extended.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_short_name_get_extended.c	(revision 30)
@@ -0,0 +1,104 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_directory.h"
+
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_directory_short_name_get_extended              PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the short name get service.      */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    long_file_name                        Pointer to long (max 255) name*/
+/*    short_file_name                       Pointer to short (8.3) name   */
+/*    short_file_name_length                Buffer length for short name  */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_short_name_get_extended Actual short name get service */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_directory_short_name_get_extended(FX_MEDIA *media_ptr, CHAR *long_file_name, CHAR *short_file_name, UINT short_file_name_length)
+{
+
+UINT status;
+
+
+    /* Check for a NULL media or file name pointer.  */
+    if ((media_ptr == FX_NULL) || (short_file_name == FX_NULL) || (long_file_name == FX_NULL))
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for zero length buffer.  */
+    if (short_file_name_length == 0)
+    {
+        return(FX_BUFFER_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual short name get service.  */
+    status =  _fx_directory_short_name_get_extended(media_ptr, long_file_name, short_file_name, short_file_name_length);
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_fault_tolerant_enable.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_fault_tolerant_enable.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_fault_tolerant_enable.c	(revision 30)
@@ -0,0 +1,99 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Fault Tolerant                                                      */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#ifdef FX_ENABLE_FAULT_TOLERANT
+#include "fx_fault_tolerant.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_fault_tolerant_enable                          PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the fault tolerant enable call.  */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    memory_buffer                         Pointer to memory buffer.     */
+/*    memory_size                           Size of memory buffer. It must*/
+/*                                            be one sector.              */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_fault_tolerant_enable             Actual enable service         */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_fault_tolerant_enable(FX_MEDIA *media_ptr, VOID *memory_buffer, UINT memory_size)
+{
+
+UINT status;
+
+
+    /* Check for a null media pointer or buffer pointer.  */
+    if ((media_ptr == FX_NULL) || (memory_buffer == FX_NULL))
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual fault tolerant enable service.  */
+    status =  _fx_fault_tolerant_enable(media_ptr, memory_buffer, memory_size);
+
+    /* Return status to the caller.  */
+    return(status);
+}
+#endif /* FX_ENABLE_FAULT_TOLERANT */
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_allocate.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_allocate.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_allocate.c	(revision 30)
@@ -0,0 +1,95 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_file.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_file_allocate                                  PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the file allocate service.       */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    file_ptr                              File control block pointer    */
+/*    size                                  Number of bytes to allocate   */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_file_allocate                     Actual file allocate service  */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_file_allocate(FX_FILE *file_ptr, ULONG size)
+{
+
+UINT status;
+
+
+    /* Check for a null file pointer.  */
+    if (file_ptr == FX_NULL)
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual file allocate service.  */
+    status =  _fx_file_allocate(file_ptr, size);
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_attributes_read.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_attributes_read.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_attributes_read.c	(revision 30)
@@ -0,0 +1,96 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_file.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_file_attributes_read                           PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the file attributes read call.   */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    file_name                             File name pointer             */
+/*    attributes_ptr                        Return attributes pointer     */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_file_attributes_read              Actual read file attributes   */
+/*                                            service                     */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_file_attributes_read(FX_MEDIA *media_ptr, CHAR *file_name, UINT *attributes_ptr)
+{
+
+UINT status;
+
+    /* Check for a null media or attributes pointer.  */
+    if ((media_ptr == FX_NULL) || (attributes_ptr == FX_NULL))
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual read file attributes service.  */
+    status =  _fx_file_attributes_read(media_ptr, file_name, attributes_ptr);
+
+    /* File attribute read is complete, return status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_attributes_set.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_attributes_set.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_attributes_set.c	(revision 30)
@@ -0,0 +1,103 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_file.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_file_attributes_set                            PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the file attribute set call.     */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    file_name                             File name pointer             */
+/*    attributes                            New file attributes           */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_file_attributes_set               Actual file attributes set    */
+/*                                            service                     */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_file_attributes_set(FX_MEDIA *media_ptr, CHAR *file_name, UINT attributes)
+{
+
+UINT status;
+
+
+    /* Check for a null media pointer.  */
+    if (media_ptr == FX_NULL)
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for invalid attributes.  */
+    if ((INT)attributes & ~(FX_READ_ONLY | FX_HIDDEN | FX_SYSTEM | FX_ARCHIVE))
+    {
+        return(FX_INVALID_ATTR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual set attributes service.  */
+    status =  _fx_file_attributes_set(media_ptr, file_name, attributes);
+
+    /* File attribute set is complete, return status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_best_effort_allocate.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_best_effort_allocate.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_best_effort_allocate.c	(revision 30)
@@ -0,0 +1,98 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_file.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_file_best_effort_allocate                      PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the file best effort allocate    */
+/*    service.                                                            */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    file_ptr                              File control block pointer    */
+/*    size                                  Number of bytes to allocate   */
+/*    actual_size_allocated                 Number of bytes allocated     */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_file_best_effort_allocate         Actual best effort file       */
+/*                                            allocate service            */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_file_best_effort_allocate(FX_FILE *file_ptr, ULONG size, ULONG *actual_size_allocated)
+{
+
+UINT status;
+
+
+    /* Check for a null file pointer.  */
+    if ((file_ptr == FX_NULL) || (actual_size_allocated == FX_NULL))
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual best effort file allocate service.  */
+    status =  _fx_file_best_effort_allocate(file_ptr, size, actual_size_allocated);
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_close.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_close.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_close.c	(revision 30)
@@ -0,0 +1,94 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_file.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_file_close                                     PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the close file call.             */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    file_ptr                              File control block pointer    */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_file_close                        Actual file close service     */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_file_close(FX_FILE *file_ptr)
+{
+
+UINT status;
+
+
+    /* Check for a null file pointer.  */
+    if (file_ptr == FX_NULL)
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual file close service.  */
+    status =  _fx_file_close(file_ptr);
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_create.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_create.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_create.c	(revision 30)
@@ -0,0 +1,95 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_file.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_file_create                                    PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the file create call.            */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    file_name                             File name                     */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_file_create                       Actual file create call       */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_file_create(FX_MEDIA *media_ptr, CHAR *file_name)
+{
+
+UINT status;
+
+
+    /* Check for a null media pointer.  */
+    if (media_ptr == FX_NULL)
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual file create service.  */
+    status =  _fx_file_create(media_ptr, file_name);
+
+    /* File create is complete, return status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_date_time_set.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_date_time_set.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_date_time_set.c	(revision 30)
@@ -0,0 +1,293 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_file.h"
+
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_file_date_time_set                             PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the file date/time set service.  */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    file_name                             File name pointer             */
+/*    year                                  Year                          */
+/*    month                                 Month                         */
+/*    day                                   Day                           */
+/*    hour                                  Hour                          */
+/*    minute                                Minute                        */
+/*    second                                Second                        */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_file_date_time_set                Actual file date/time set     */
+/*                                            service                     */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_file_date_time_set(FX_MEDIA *media_ptr, CHAR *file_name,
+                              UINT year, UINT month, UINT day, UINT hour, UINT minute, UINT second)
+{
+
+UINT status;
+
+
+    /* Check for a NULL media or file name pointer.  */
+    if ((media_ptr == FX_NULL) || (file_name == FX_NULL))
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for invalid year.  */
+    if ((year < FX_BASE_YEAR) || (year > FX_MAXIMUM_YEAR))
+    {
+        return(FX_INVALID_YEAR);
+    }
+
+    /* Check for invalid day.  */
+    if (day < 1)
+    {
+        return(FX_INVALID_DAY);
+    }
+
+    /* Check for invalid day.  */
+    switch (month)
+    {
+
+    case 1:
+    {
+
+        /* Check for 31 days.  */
+        if (day > 31)
+        {
+            return(FX_INVALID_DAY);
+        }
+        break;
+    }
+
+    case 2:
+    {
+
+        /* Check for leap year.  */
+        if ((year % 4) == 0)
+        {
+
+            /* Leap year, February has 29 days.  */
+            if (day > 29)
+            {
+                return(FX_INVALID_DAY);
+            }
+        }
+        else
+        {
+
+            /* Otherwise, non-leap year.  February has
+               28 days.  */
+            if (day > 28)
+            {
+                return(FX_INVALID_DAY);
+            }
+        }
+        break;
+    }
+
+    case 3:
+    {
+
+        /* Check for 31 days.  */
+        if (day > 31)
+        {
+            return(FX_INVALID_DAY);
+        }
+        break;
+    }
+
+    case 4:
+    {
+
+        /* Check for 30 days.  */
+        if (day > 30)
+        {
+            return(FX_INVALID_DAY);
+        }
+        break;
+    }
+
+    case 5:
+    {
+
+        /* Check for 31 days.  */
+        if (day > 31)
+        {
+            return(FX_INVALID_DAY);
+        }
+        break;
+    }
+
+    case 6:
+    {
+
+        /* Check for 30 days.  */
+        if (day > 30)
+        {
+            return(FX_INVALID_DAY);
+        }
+        break;
+    }
+
+    case 7:
+    {
+
+        /* Check for 31 days.  */
+        if (day > 31)
+        {
+            return(FX_INVALID_DAY);
+        }
+        break;
+    }
+
+    case 8:
+    {
+
+        /* Check for 31 days.  */
+        if (day > 31)
+        {
+            return(FX_INVALID_DAY);
+        }
+        break;
+    }
+
+    case 9:
+    {
+
+        /* Check for 30 days.  */
+        if (day > 30)
+        {
+            return(FX_INVALID_DAY);
+        }
+        break;
+    }
+
+    case 10:
+    {
+
+        /* Check for 31 days.  */
+        if (day > 31)
+        {
+            return(FX_INVALID_DAY);
+        }
+        break;
+    }
+
+    case 11:
+    {
+
+        /* Check for 30 days.  */
+        if (day > 30)
+        {
+            return(FX_INVALID_DAY);
+        }
+        break;
+    }
+
+    case 12:
+    {
+
+        /* Check for 31 days.  */
+        if (day > 31)
+        {
+            return(FX_INVALID_DAY);
+        }
+        break;
+    }
+    
+    default:
+    
+        /* Invalid month.  */
+        return(FX_INVALID_MONTH);
+    }
+
+    /* Check for invalid hour.  */
+    if (hour > FX_MAXIMUM_HOUR)
+    {
+        return(FX_INVALID_HOUR);
+    }
+
+    /* Check for invalid minute.  */
+    if (minute > FX_MAXIMUM_MINUTE)
+    {
+        return(FX_INVALID_MINUTE);
+    }
+
+    /* Check for invalid second.  */
+    if (second > FX_MAXIMUM_SECOND)
+    {
+        return(FX_INVALID_SECOND);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual file date/time set service.  */
+    status =  _fx_file_date_time_set(media_ptr, file_name,
+                                     year, month, day,
+                                     hour, minute, second);
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_delete.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_delete.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_delete.c	(revision 30)
@@ -0,0 +1,94 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_file.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_file_delete                                    PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the file delete call.            */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    file_name                             File name pointer             */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_file_delete                       Actual file delete service    */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_file_delete(FX_MEDIA *media_ptr, CHAR *file_name)
+{
+
+UINT status;
+
+
+    /* Check for a null media pointer.  */
+    if (media_ptr == FX_NULL)
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual file delete service.  */
+    status =  _fx_file_delete(media_ptr, file_name);
+
+    /* File delete is complete, return status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_extended_allocate.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_extended_allocate.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_extended_allocate.c	(revision 30)
@@ -0,0 +1,95 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_file.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_file_extended_allocate                         PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the file allocate service.       */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    file_ptr                              File control block pointer    */
+/*    size                                  Number of bytes to allocate   */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_file_extended_allocate            Actual file allocate service  */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_file_extended_allocate(FX_FILE *file_ptr, ULONG64 size)
+{
+
+UINT status;
+
+
+    /* Check for a null file pointer.  */
+    if (file_ptr == FX_NULL)
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual file allocate service.  */
+    status =  _fx_file_extended_allocate(file_ptr, size);
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_extended_best_effort_allocate.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_extended_best_effort_allocate.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_extended_best_effort_allocate.c	(revision 30)
@@ -0,0 +1,98 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_file.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_file_extended_best_effort_allocate             PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the file best effort allocate    */
+/*    service.                                                            */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    file_ptr                              File control block pointer    */
+/*    size                                  Number of bytes to allocate   */
+/*    actual_size_allocated                 Number of bytes allocated     */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_file_extended_best_effort_allocate Actual best effort file      */
+/*                                            allocate service            */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_file_extended_best_effort_allocate(FX_FILE *file_ptr, ULONG64 size, ULONG64 *actual_size_allocated)
+{
+
+UINT status;
+
+
+    /* Check for a null file pointer.  */
+    if ((file_ptr == FX_NULL) || (actual_size_allocated == FX_NULL))
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual best effort file allocate service.  */
+    status =  _fx_file_extended_best_effort_allocate(file_ptr, size, actual_size_allocated);
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_extended_relative_seek.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_extended_relative_seek.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_extended_relative_seek.c	(revision 30)
@@ -0,0 +1,110 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_file.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_file_extended_relative_seek                    PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the file relative seek call.     */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    file_ptr                              File control block pointer    */
+/*    byte_offset                           Byte offset of the seek       */
+/*    seek_from                             Direction for relative seek,  */
+/*                                          legal values are:             */
+/*                                                                        */
+/*                                              FX_SEEK_BEGIN             */
+/*                                              FX_SEEK_END               */
+/*                                              FX_SEEK_FORWARD           */
+/*                                              FX_SEEK_BACK              */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_file_extended_relative_seek       Actual relative file seek     */
+/*                                            service                     */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_file_extended_relative_seek(FX_FILE *file_ptr, ULONG64 byte_offset, UINT seek_from)
+{
+
+UINT status;
+
+
+    /* Check for a null file pointer.  */
+    if (file_ptr == FX_NULL)
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for valid seek from option.  */
+    if ((seek_from != FX_SEEK_BEGIN) && (seek_from != FX_SEEK_END) &&
+        (seek_from != FX_SEEK_FORWARD) && (seek_from != FX_SEEK_BACK))
+    {
+        return(FX_INVALID_OPTION);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual file relative seek service.  */
+    status =  _fx_file_extended_relative_seek(file_ptr, byte_offset, seek_from);
+
+    /* Seek is complete, return status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_extended_seek.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_extended_seek.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_extended_seek.c	(revision 30)
@@ -0,0 +1,95 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_file.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_file_extended_seek                             PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the file seek call.              */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    file_ptr                              File control block pointer    */
+/*    byte_offset                           Byte offset into the file     */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_file_extended_seek                Actual file seek service      */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_file_extended_seek(FX_FILE *file_ptr, ULONG64 byte_offset)
+{
+
+UINT status;
+
+
+    /* Check for a null file pointer.  */
+    if (file_ptr == FX_NULL)
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual file seek service.  */
+    status =  _fx_file_extended_seek(file_ptr, byte_offset);
+
+    /* Seek is complete, return status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_extended_truncate.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_extended_truncate.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_extended_truncate.c	(revision 30)
@@ -0,0 +1,95 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_file.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_file_extended_truncate                         PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the file truncate call.          */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    file_ptr                              File control block pointer    */
+/*    size                                  New size of the file in bytes */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_file_extended_truncate            Actual file truncate service  */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_file_extended_truncate(FX_FILE *file_ptr, ULONG64 size)
+{
+
+UINT status;
+
+
+    /* Check for a null file pointer.  */
+    if (file_ptr == FX_NULL)
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual file truncate service.  */
+    status =  _fx_file_extended_truncate(file_ptr, size);
+
+    /* Truncate is complete, return status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_extended_truncate_release.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_extended_truncate_release.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_extended_truncate_release.c	(revision 30)
@@ -0,0 +1,96 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_file.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_file_extended_truncate_release                 PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the file truncate release call.  */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    file_ptr                              File control block pointer    */
+/*    size                                  New size of the file in bytes */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_file_extended_truncate_release    Actual file truncate release  */
+/*                                            service                     */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_file_extended_truncate_release(FX_FILE *file_ptr, ULONG64 size)
+{
+
+UINT status;
+
+
+    /* Check for a null file pointer.  */
+    if (file_ptr == FX_NULL)
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual file truncate release service.  */
+    status =  _fx_file_extended_truncate_release(file_ptr, size);
+
+    /* Truncate is complete, return status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_open.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_open.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_open.c	(revision 30)
@@ -0,0 +1,137 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_file.h"
+
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_file_open                                      PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the file open call.              */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    file_ptr                              File control block pointer    */
+/*    file_name                             Name pointer                  */
+/*    open_type                             Type of open requested        */
+/*    file_control_block_size               Size of FX_FILE structure     */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_file_open                         Actual open file service      */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_file_open(FX_MEDIA *media_ptr, FX_FILE *file_ptr, CHAR *file_name, UINT open_type, UINT file_control_block_size)
+{
+
+UINT     status;
+FX_FILE *current_file;
+ULONG    open_count;
+
+
+    /* Check for a null media or file pointer.  */
+    if ((media_ptr == FX_NULL) || (media_ptr -> fx_media_id != FX_MEDIA_ID) || (file_ptr == FX_NULL) || (file_control_block_size != sizeof(FX_FILE)))
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for an invalid open type.  */
+    if ((open_type != FX_OPEN_FOR_READ) && (open_type != FX_OPEN_FOR_READ_FAST) && (open_type != FX_OPEN_FOR_WRITE))
+    {
+        return(FX_ACCESS_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Get protection.  */
+    FX_PROTECT
+
+    /* Check for a duplicate file open.  */
+
+    /* Loop to search the list for the same file handle.  */
+    current_file =  media_ptr -> fx_media_opened_file_list;
+    open_count =    media_ptr -> fx_media_opened_file_count;
+
+    while (open_count--)
+    {
+
+        /* See if a match exists.  */
+        if (file_ptr == current_file)
+        {
+
+            /* Release protection.  */
+            FX_UNPROTECT
+
+            /* Return error.  */
+            return(FX_PTR_ERROR);
+        }
+
+        /* Move to the next opened file.  */
+        current_file =  current_file -> fx_file_opened_next;
+    }
+
+    /* Release protection.  */
+    FX_UNPROTECT
+
+    /* Call actual file open service.  */
+    status =  _fx_file_open(media_ptr, file_ptr, file_name, open_type);
+
+    /* Open is complete, return status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_read.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_read.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_read.c	(revision 30)
@@ -0,0 +1,98 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_file.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_file_read                                      PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the read file call.              */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    file_ptr                              File control block pointer    */
+/*    buffer_ptr                            Buffer pointer                */
+/*    request_size                          Number of bytes requested     */
+/*    actual_size                           Pointer to variable for the   */
+/*                                            number of bytes read        */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_file_read                         Actual file read service      */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_file_read(FX_FILE *file_ptr, VOID *buffer_ptr, ULONG request_size, ULONG *actual_size)
+{
+
+UINT status;
+
+
+    /* Check for a null file or buffer pointer.  */
+    if ((file_ptr == FX_NULL) || (buffer_ptr == FX_NULL) || (actual_size == FX_NULL))
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual file read service.  */
+    status =  _fx_file_read(file_ptr, buffer_ptr, request_size, actual_size);
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_relative_seek.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_relative_seek.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_relative_seek.c	(revision 30)
@@ -0,0 +1,110 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_file.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_file_relative_seek                             PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the file relative seek call.     */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    file_ptr                              File control block pointer    */
+/*    byte_offset                           Byte offset of the seek       */
+/*    seek_from                             Direction for relative seek,  */
+/*                                          legal values are:             */
+/*                                                                        */
+/*                                              FX_SEEK_BEGIN             */
+/*                                              FX_SEEK_END               */
+/*                                              FX_SEEK_FORWARD           */
+/*                                              FX_SEEK_BACK              */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_file_relative_seek                Actual relative file seek     */
+/*                                            service                     */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_file_relative_seek(FX_FILE *file_ptr, ULONG byte_offset, UINT seek_from)
+{
+
+UINT status;
+
+
+    /* Check for a null file pointer.  */
+    if (file_ptr == FX_NULL)
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for valid seek from option.  */
+    if ((seek_from != FX_SEEK_BEGIN) && (seek_from != FX_SEEK_END) &&
+        (seek_from != FX_SEEK_FORWARD) && (seek_from != FX_SEEK_BACK))
+    {
+        return(FX_INVALID_OPTION);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual file relative seek service.  */
+    status =  _fx_file_relative_seek(file_ptr, byte_offset, seek_from);
+
+    /* Seek is complete, return status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_rename.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_rename.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_rename.c	(revision 30)
@@ -0,0 +1,96 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_file.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_file_rename                                    PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the file rename call.            */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    old_file_name                         Old file name pointer         */
+/*    new_file_name                         New file name pointer         */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_file_rename                       Actual file rename service    */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_file_rename(FX_MEDIA *media_ptr, CHAR *old_file_name, CHAR *new_file_name)
+{
+
+UINT status;
+
+
+    /* Check for a null media pointer.  */
+    if (media_ptr == FX_NULL)
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual file rename service.  */
+    status =  _fx_file_rename(media_ptr, old_file_name, new_file_name);
+
+    /* File rename is complete, return status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_seek.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_seek.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_seek.c	(revision 30)
@@ -0,0 +1,95 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_file.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_file_seek                                      PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the file seek call.              */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    file_ptr                              File control block pointer    */
+/*    byte_offset                           Byte offset into the file     */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_file_seek                         Actual file seek service      */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_file_seek(FX_FILE *file_ptr, ULONG byte_offset)
+{
+
+UINT status;
+
+
+    /* Check for a null file pointer.  */
+    if (file_ptr == FX_NULL)
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual file seek service.  */
+    status =  _fx_file_seek(file_ptr, byte_offset);
+
+    /* Seek is complete, return status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_truncate.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_truncate.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_truncate.c	(revision 30)
@@ -0,0 +1,95 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_file.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_file_truncate                                  PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the file truncate call.          */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    file_ptr                              File control block pointer    */
+/*    size                                  New size of the file in bytes */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_file_truncate                     Actual file truncate service  */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_file_truncate(FX_FILE *file_ptr, ULONG size)
+{
+
+UINT status;
+
+
+    /* Check for a null file pointer.  */
+    if (file_ptr == FX_NULL)
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual file truncate service.  */
+    status =  _fx_file_truncate(file_ptr, size);
+
+    /* Truncate is complete, return status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_truncate_release.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_truncate_release.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_truncate_release.c	(revision 30)
@@ -0,0 +1,96 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_file.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_file_truncate_release                          PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the file truncate release call.  */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    file_ptr                              File control block pointer    */
+/*    size                                  New size of the file in bytes */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_file_truncate_release             Actual file truncate release  */
+/*                                            service                     */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_file_truncate_release(FX_FILE *file_ptr, ULONG size)
+{
+
+UINT status;
+
+
+    /* Check for a null file pointer.  */
+    if (file_ptr == FX_NULL)
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual file truncate release service.  */
+    status =  _fx_file_truncate_release(file_ptr, size);
+
+    /* Truncate is complete, return status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_write.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_write.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_write.c	(revision 30)
@@ -0,0 +1,96 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_file.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_file_write                                     PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the file write call.             */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    file_ptr                              File control block pointer    */
+/*    buffer_ptr                            Buffer pointer                */
+/*    size                                  Number of bytes to write      */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_file_write                        Actual file write service     */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_file_write(FX_FILE *file_ptr, VOID *buffer_ptr, ULONG size)
+{
+
+UINT status;
+
+
+    /* Check for a null file or buffer pointer.  */
+    if ((file_ptr == FX_NULL) || (buffer_ptr == FX_NULL))
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual file write service.  */
+    status =  _fx_file_write(file_ptr, buffer_ptr, size);
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_write_notify_set.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_write_notify_set.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_file_write_notify_set.c	(revision 30)
@@ -0,0 +1,96 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   File                                                                */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_file.h"
+
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_file_write_notify_set                          PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the file write notify set.       */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    file_ptr                              File control block pointer    */
+/*    file_write_notify                     Notify function called when   */
+/*                                            file is written to          */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    FX_PTR_ERROR                          media_ptr is NULL             */
+/*    status                                Actual completion status      */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_file_write_notify                 Actual file write notify set  */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_file_write_notify_set(FX_FILE *file_ptr, VOID (*file_write_notify)(FX_FILE *file))
+{
+UINT status;
+
+    /* Check for invalid input pointers.  */
+    if (file_ptr == FX_NULL)
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual file write notify set service.  */
+    status =  _fx_file_write_notify_set(file_ptr, file_write_notify);
+
+    /* Return status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_abort.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_abort.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_abort.c	(revision 30)
@@ -0,0 +1,94 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_media.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_media_abort                                    PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the media abort call.            */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_media_abort                       Actual media abort service    */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_media_abort(FX_MEDIA  *media_ptr)
+{
+
+UINT status;
+
+
+    /* Check for a null media pointer.  */
+    if (media_ptr == FX_NULL)
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual media abort service.  */
+    status =  _fx_media_abort(media_ptr);
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_cache_invalidate.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_cache_invalidate.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_cache_invalidate.c	(revision 30)
@@ -0,0 +1,96 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_media.h"
+
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_media_cache_invalidate                         PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the media invalidate service.    */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_media_cache_invalidate            Actual media invalidate       */
+/*                                            service                     */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_media_cache_invalidate(FX_MEDIA *media_ptr)
+{
+
+UINT status;
+
+
+    /* Check for a NULL media pointer.  */
+    if (media_ptr == FX_NULL)
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual media invalidate service.  */
+    status =  _fx_media_cache_invalidate(media_ptr);
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_check.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_check.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_check.c	(revision 30)
@@ -0,0 +1,136 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_media.h"
+
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_media_check                                    PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the media check call.            */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Pointer to a previously       */
+/*                                            opened media                */
+/*    scratch_memory_ptr                    Pointer to memory area for    */
+/*                                            check disk to use (as       */
+/*                                            mentioned above)            */
+/*    scratch_memory_size                   Size of the scratch memory    */
+/*    error_correction_option               Specifies which - if any -    */
+/*                                            errors are corrected by     */
+/*                                            the check disk function.    */
+/*                                            Setting the following bit   */
+/*                                            causes that error to be     */
+/*                                            corrected:                  */
+/*                                                                        */
+/*                                            0x01 -> Fix FAT Chain Errors*/
+/*                                            0x02 -> Fix Directory Entry */
+/*                                                      Errors            */
+/*                                            0x04 -> Fix Lost Clusters   */
+/*                                                                        */
+/*    errors_detected                       Specifies the destination     */
+/*                                            ULONG to place the error    */
+/*                                            report from check disk.     */
+/*                                            This has a similar bit map  */
+/*                                            as before:                  */
+/*                                                                        */
+/*                                            0x01 -> FAT Chain Error(s)  */
+/*                                            0x02 -> Directory Entry     */
+/*                                                      Error(s)          */
+/*                                            0x04 -> Lost Cluster(s)     */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    FX_SUCCESS                            Check disk performed its      */
+/*                                            operation successfully.     */
+/*                                            This does not mean that     */
+/*                                            there were no errors. The   */
+/*                                            errors_detected variable    */
+/*                                            needs to be examined.       */
+/*    FX_MEDIA_NOT_OPEN                     The media was not open.       */
+/*    FX_NOT_ENOUGH_MEMORY                  The scratch memory was not    */
+/*                                            large enough or the nesting */
+/*                                            depth was greater than the  */
+/*                                            maximum specified.          */
+/*    FX_IO_ERROR                           I/O Error reading/writing to  */
+/*                                            the media.                  */
+/*    FX_ERROR_NOT_FIXED                    Fundamental problem with      */
+/*                                            media that couldn't be fixed*/
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_media_check                       Actual media check service    */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_media_check(FX_MEDIA *media_ptr, UCHAR *scratch_memory_ptr, ULONG scratch_memory_size, ULONG error_correction_option, ULONG *errors_detected)
+{
+
+UINT status;
+
+
+    /* Check for a NULL media or scratch pointer.  */
+    if ((media_ptr == FX_NULL) || (scratch_memory_ptr == FX_NULL))
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual media check service.  */
+    status =  _fx_media_check(media_ptr, scratch_memory_ptr, scratch_memory_size, error_correction_option, errors_detected);
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_close.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_close.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_close.c	(revision 30)
@@ -0,0 +1,94 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_media.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_media_close                                    PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the media close call.            */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_media_close                       Actual media close service    */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_media_close(FX_MEDIA  *media_ptr)
+{
+
+UINT status;
+
+
+    /* Check for a null media pointer.  */
+    if (media_ptr == FX_NULL)
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual media close service.  */
+    status =  _fx_media_close(media_ptr);
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_close_notify_set.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_close_notify_set.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_close_notify_set.c	(revision 30)
@@ -0,0 +1,96 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_media.h"
+
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_media_close_notify_set                         PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the media close notify set.      */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    media_close_notify                    Notify function called when   */
+/*                                            media is closed             */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    FX_PTR_ERROR                          media_ptr is NULL             */
+/*    status                                Actual completion status      */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_media_close_notify                Actual media close notify set */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_media_close_notify_set(FX_MEDIA *media_ptr, VOID (*media_close_notify)(FX_MEDIA *media))
+{
+UINT status;
+
+    /* Check for invalid input pointers.  */
+    if (media_ptr == FX_NULL)
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual media close notify set service.  */
+    status =  _fx_media_close_notify_set(media_ptr, media_close_notify);
+
+    /* Return status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_exFAT_format.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_exFAT_format.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_exFAT_format.c	(revision 30)
@@ -0,0 +1,123 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+
+
+#ifdef FX_ENABLE_EXFAT
+#include "fx_media.h"
+
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_media_exFAT_format                             PORTABLE C      */
+/*                                                           6.1.5        */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the exFAT media format call.     */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Pointer to media control block*/
+/*                                            (does not need to be opened)*/
+/*    driver                                Pointer to FileX driver (must */
+/*                                            be able to field requests   */
+/*                                            prior to opening)           */
+/*    driver_info_ptr                       Optional information pointer  */
+/*    memory_ptr                            Pointer to memory used by the */
+/*                                            FileX for this media.       */
+/*    memory_size                           Size of media memory - must   */
+/*                                            at least 512 bytes and      */
+/*                                            one sector size.            */
+/*    volume_name                           Name of the volume            */
+/*    number_of_fats                        Number of FAT tables          */
+/*    hidden_sectors                        Number of hidden sectors      */
+/*    total_sectors                         Total number of sectors       */
+/*    bytes_per_sector                      Number of bytes per sector    */
+/*    sectors_per_cluster                   Number of sectors per cluster */
+/*    volume_serial_number                  Volume Serial Number          */
+/*    boundary_unit                         Data area alignment in sectors*/
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    Completion Status                                                   */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_media_exFAT_format                Actual media format service   */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*  03-02-2021     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1.5  */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_media_exFAT_format(FX_MEDIA *media_ptr, VOID (*driver)(FX_MEDIA *media), VOID *driver_info_ptr,
+                              UCHAR *memory_ptr, UINT memory_size, CHAR *volume_name, UINT number_of_fats,
+                              ULONG64 hidden_sectors, ULONG64 total_sectors, UINT bytes_per_sector,
+                              UINT sectors_per_cluster, UINT volume_serial_number, UINT boundary_unit)
+{
+
+UINT status;
+
+
+    /* Check for invalid input pointers.  */
+    if ((media_ptr == FX_NULL) || (driver == FX_NULL) || (memory_ptr == FX_NULL))
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual media format service.  */
+    status =  _fx_media_exFAT_format(media_ptr, driver, driver_info_ptr, memory_ptr, memory_size,
+                                     volume_name, number_of_fats, hidden_sectors, total_sectors, bytes_per_sector, sectors_per_cluster, volume_serial_number, boundary_unit);
+
+    /* Return completion status.  */
+    return(status);
+}
+
+#endif /* FX_ENABLE_EXFAT */
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_extended_space_available.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_extended_space_available.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_extended_space_available.c	(revision 30)
@@ -0,0 +1,96 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_media.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_media_extended_space_available                 PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the media space available call.  */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    available_bytes_ptr                   Pointer to available bytes    */
+/*                                            destination                 */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_media_extended_space_available    Actual space available service*/
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_media_extended_space_available(FX_MEDIA *media_ptr, ULONG64 *available_bytes_ptr)
+{
+
+UINT status;
+
+
+    /* Check for a null media pointer or destination pointer.  */
+    if ((media_ptr == FX_NULL) || (available_bytes_ptr == FX_NULL))
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual media space available service.  */
+    status =  _fx_media_extended_space_available(media_ptr, available_bytes_ptr);
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_flush.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_flush.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_flush.c	(revision 30)
@@ -0,0 +1,96 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_media.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_media_flush                                    PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the flush media call.            */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    FX_PTR_ERROR                          Supplied pointer is invalid   */
+/*    FX_CALLER_ERROR                       Caller is not a thread        */
+/*    status                                Actual completion status      */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_media_flush                       Actual media flush service    */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_media_flush(FX_MEDIA  *media_ptr)
+{
+
+UINT status;
+
+
+    /* Check for a null media pointer.  */
+    if (media_ptr == FX_NULL)
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual media flush service.  */
+    status =  _fx_media_flush(media_ptr);
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_format.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_format.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_format.c	(revision 30)
@@ -0,0 +1,122 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_media.h"
+
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_media_format                                   PORTABLE C      */
+/*                                                           6.1.5        */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the media format call.           */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Pointer to media control block*/
+/*                                            (does not need to be opened)*/
+/*    driver                                Pointer to FileX driver (must */
+/*                                            be able to field requests   */
+/*                                            prior to opening)           */
+/*    driver_info_ptr                       Optional information pointer  */
+/*    memory_ptr                            Pointer to memory used by the */
+/*                                            FileX for this media.       */
+/*    memory_size                           Size of media memory - must   */
+/*                                            at least 512 bytes and      */
+/*                                            one sector size.            */
+/*    volume_name                           Name of the volume            */
+/*    number_of_fats                        Number of FAT tables          */
+/*    directory_entries                     Number of directory entries   */
+/*    hidden_sectors                        Number of hidden sectors      */
+/*    total_sectors                         Total number of sectors       */
+/*    bytes_per_sector                      Number of bytes per sector    */
+/*    sectors_per_cluster                   Number of sectors per cluster */
+/*    heads                                 Number of heads               */
+/*    sectors_per_track                     Number of sectors per track   */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    Completion Status                                                   */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_media_format                      Actual media format service   */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*  03-02-2021     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1.5  */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_media_format(FX_MEDIA *media_ptr, VOID (*driver)(FX_MEDIA *media), VOID *driver_info_ptr, UCHAR *memory_ptr, UINT memory_size,
+                        CHAR *volume_name, UINT number_of_fats, UINT directory_entries, UINT hidden_sectors,
+                        ULONG total_sectors, UINT bytes_per_sector, UINT sectors_per_cluster,
+                        UINT heads, UINT sectors_per_track)
+{
+
+UINT status;
+
+
+    /* Check for invalid input pointers.  */
+    if ((media_ptr == FX_NULL) || (driver == FX_NULL) || (memory_ptr == FX_NULL))
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual media format service.  */
+    status =  _fx_media_format(media_ptr, driver, driver_info_ptr, memory_ptr, memory_size,
+                               volume_name, number_of_fats, directory_entries, hidden_sectors,
+                               total_sectors, bytes_per_sector, sectors_per_cluster,
+                               heads, sectors_per_track);
+
+    /* Return completion status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_open.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_open.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_open.c	(revision 30)
@@ -0,0 +1,189 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_media.h"
+#include "fx_system.h"
+
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_media_open                                     PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the media open call.             */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    media_name                            Pointer to media name string  */
+/*    media_driver                          Media driver entry function   */
+/*    driver_info_ptr                       Optional information pointer  */
+/*                                            supplied to media driver    */
+/*    memory_ptr                            Pointer to memory used by the */
+/*                                            FileX for this media.       */
+/*    memory_size                           Size of media memory - must   */
+/*                                            at least 512 bytes and      */
+/*                                            one sector size.            */
+/*    media_control_block_size              Size of FX_MEDIA structure    */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    FX_PTR_ERROR                          One or more input parameters  */
+/*                                            are NULL                    */
+/*    status                                Actual completion status      */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    tx_thread_identify                    Get current thread            */
+/*    tx_thread_preemption_change           Disable/restore preemption    */
+/*    _fx_media_open                        Actual media open service     */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_media_open(FX_MEDIA *media_ptr, CHAR *media_name,
+                      VOID (*media_driver)(FX_MEDIA *), VOID *driver_info_ptr,
+                      VOID *memory_ptr, ULONG memory_size, UINT media_control_block_size)
+{
+
+UINT       status;
+ULONG      temp;
+FX_MEDIA  *current_media;
+ULONG      open_count;
+
+#ifndef FX_SINGLE_THREAD
+TX_THREAD *current_thread;
+UINT       old_threshold;
+#endif
+
+
+    /* Check for invalid input pointers.  */
+    if ((media_ptr == FX_NULL) || (media_driver == FX_NULL) || (memory_ptr == FX_NULL) || (media_control_block_size != sizeof(FX_MEDIA)))
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Check for proper size of the logical sector cache.  */
+    temp =  _fx_system_media_max_sector_cache;
+
+    /* Isolate the lowest set bit.  */
+    temp =  (temp & ((~temp) + ((ULONG) 1)));
+
+    /* If FX_MAX_SECTOR_CACHE is a power of 2, the value of temp should be unchanged.  */
+    if ((temp == 1) || (temp != _fx_system_media_max_sector_cache))
+    {
+
+        /* Not a power of 2, return an error.  */
+        return(FX_MEDIA_INVALID);
+    }
+
+    /* Check for proper size of the FAT cache.  */
+    temp =  _fx_system_media_max_fat_cache;
+
+    /* Isolate the lowest set bit.  */
+    temp =  (temp & ((~temp) + ((ULONG) 1)));
+
+    /* If FX_MAX_FAT_CACHE is a power of 2, the value of temp should be unchanged.  */
+    if ((temp == 1) || (temp != _fx_system_media_max_fat_cache))
+    {
+
+        /* Not a power of 2, return an error.  */
+        return(FX_MEDIA_INVALID);
+    }
+
+#ifndef FX_SINGLE_THREAD
+
+    /* Pickup current thread pointer. At this point we know the current thread pointer is non-null since 
+       it was checked by code in FX_CALLER_CHECKING_CODE macro.  */
+    current_thread =  tx_thread_identify();
+
+    /* Disable preemption temporarily.  */
+    tx_thread_preemption_change(current_thread, 0, &old_threshold);
+#endif
+
+    /* Loop to check for the media already opened.  */
+    current_media =  _fx_system_media_opened_ptr;
+    open_count =     _fx_system_media_opened_count;
+    while (open_count--)
+    {
+
+        /* Is the new media pointer already open?  */
+        if (media_ptr == current_media)
+        {
+
+#ifndef FX_SINGLE_THREAD
+
+            /* Restore preemption.  */
+            tx_thread_preemption_change(current_thread, old_threshold, &old_threshold);
+#endif
+
+            /* Duplicate media open, return an error!  */
+            return(FX_PTR_ERROR);
+        }
+
+        /* Move to next entry.  */
+        current_media =  current_media -> fx_media_opened_next;
+    }
+
+#ifndef FX_SINGLE_THREAD
+
+    /* Restore preemption.  */
+    tx_thread_preemption_change(current_thread, old_threshold, &old_threshold);
+#endif
+
+    /* Call actual media open service.  */
+    status =  _fx_media_open(media_ptr, media_name, media_driver, driver_info_ptr,
+                             memory_ptr, memory_size);
+
+    /* Return status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_open_notify_set.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_open_notify_set.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_open_notify_set.c	(revision 30)
@@ -0,0 +1,96 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_media.h"
+
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_media_open_notify_set                          PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the media open notify set.       */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    media_open_notify                     Notify function called when   */
+/*                                            media is open               */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    FX_PTR_ERROR                          media_ptr is NULL             */
+/*    status                                Actual completion status      */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_media_open_notify                 Actual media open notify set  */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_media_open_notify_set(FX_MEDIA *media_ptr, VOID (*media_open_notify)(FX_MEDIA *media))
+{
+UINT status;
+
+    /* Check for invalid input pointers.  */
+    if (media_ptr == FX_NULL)
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual media open notify set service.  */
+    status =  _fx_media_open_notify_set(media_ptr, media_open_notify);
+
+    /* Return status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_read.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_read.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_read.c	(revision 30)
@@ -0,0 +1,96 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_media.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_media_read                                     PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the media read call.             */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    logical_sector                        Logical sector to read        */
+/*    buffer_ptr                            Pointer to caller's buffer    */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_media_read                        Actual media read service     */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_media_read(FX_MEDIA *media_ptr, ULONG logical_sector, VOID *buffer_ptr)
+{
+
+UINT status;
+
+
+    /* Check for a null media pointer or buffer pointer.  */
+    if ((media_ptr == FX_NULL) || (buffer_ptr == FX_NULL))
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual media read service.  */
+    status =  _fx_media_read(media_ptr, logical_sector, buffer_ptr);
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_space_available.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_space_available.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_space_available.c	(revision 30)
@@ -0,0 +1,96 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_media.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_media_space_available                          PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the media space available call.  */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    available_bytes_ptr                   Pointer to available bytes    */
+/*                                            destination                 */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_media_space_available             Actual space available service*/
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_media_space_available(FX_MEDIA *media_ptr, ULONG *available_bytes_ptr)
+{
+
+UINT status;
+
+
+    /* Check for a null media pointer or destination pointer.  */
+    if ((media_ptr == FX_NULL) || (available_bytes_ptr == FX_NULL))
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual media space available service.  */
+    status =  _fx_media_space_available(media_ptr, available_bytes_ptr);
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_volume_get.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_volume_get.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_volume_get.c	(revision 30)
@@ -0,0 +1,100 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_media.h"
+
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_media_volume_get                               PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the media volume get service.    */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    volume_name                           Pointer to destination for    */
+/*                                            the volume name (maximum    */
+/*                                            11 characters + NULL)       */
+/*    volume_source                         Source of volume              */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_media_volume_get                  Actual media volume get       */
+/*                                            service                     */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_media_volume_get(FX_MEDIA *media_ptr, CHAR *volume_name, UINT volume_source)
+{
+
+UINT status;
+
+
+    /* Check for a NULL media or volume name pointer.  */
+    if ((media_ptr == FX_NULL) || (volume_name == FX_NULL))
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual media volume get service.  */
+    status =  _fx_media_volume_get(media_ptr, volume_name, volume_source);
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_volume_get_extended.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_volume_get_extended.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_volume_get_extended.c	(revision 30)
@@ -0,0 +1,107 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_media.h"
+
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_media_volume_get_extended                      PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the media volume get service.    */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    volume_name                           Pointer to destination for    */
+/*                                            the volume name (maximum    */
+/*                                            11 characters + NULL)       */
+/*    volume_name_buffer_length             Buffer length for volume_name */
+/*    volume_source                         Source of volume              */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_media_volume_get_extended         Actual media volume get       */
+/*                                            service                     */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_media_volume_get_extended(FX_MEDIA *media_ptr, CHAR *volume_name, UINT volume_name_buffer_length, UINT volume_source)
+{
+
+UINT status;
+
+
+    /* Check for a NULL media or volume name pointer.  */
+    if ((media_ptr == FX_NULL) || (volume_name == FX_NULL))
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for zero length buffer.  */
+    if (volume_name_buffer_length == 0)
+    {
+        return(FX_BUFFER_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual media volume get service.  */
+    status =  _fx_media_volume_get_extended(media_ptr, volume_name, volume_name_buffer_length, volume_source);
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_volume_set.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_volume_set.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_volume_set.c	(revision 30)
@@ -0,0 +1,97 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_media.h"
+
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_media_volume_set                               PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the media volume set service.    */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    volume_name                           New volume name               */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_media_volume_set                  Actual media volume name set  */
+/*                                            service                     */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_media_volume_set(FX_MEDIA *media_ptr, CHAR *volume_name)
+{
+
+UINT status;
+
+
+    /* Check for a NULL media or volume name pointer.  */
+    if ((media_ptr == FX_NULL) || (volume_name == FX_NULL) || (volume_name[0] == FX_NULL))
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual media volume set service.  */
+    status =  _fx_media_volume_set(media_ptr, volume_name);
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_write.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_write.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_media_write.c	(revision 30)
@@ -0,0 +1,97 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_media.h"
+
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_media_write                                    PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the media write call.            */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    logical_sector                        Logical sector to read        */
+/*    buffer_ptr                            Pointer to caller's buffer    */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_media_write                       Actual media write service    */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_media_write(FX_MEDIA *media_ptr, ULONG logical_sector, VOID *buffer_ptr)
+{
+
+UINT status;
+
+
+    /* Check for a null media pointer.  */
+    if (media_ptr == FX_NULL)
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual media write service.  */
+    status =  _fx_media_write(media_ptr, logical_sector, buffer_ptr);
+
+    /* Return a successful status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_system_date_get.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_system_date_get.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_system_date_get.c	(revision 30)
@@ -0,0 +1,92 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   System                                                              */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_system_date_get                                PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the get system date call.        */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    year                                  Pointer to year               */
+/*    month                                 Pointer to month              */
+/*    day                                   Pointer to day                */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    FX_PTR_ERROR                          Invalid destination pointer   */
+/*    status                                Actual completion status      */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_system_date_get                   Actual get system date call   */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_system_date_get(UINT *year, UINT *month, UINT *day)
+{
+
+UINT status;
+
+
+    /* Check for an invalid pointer.  */
+    if ((year == FX_NULL) || (month == FX_NULL) || (day == FX_NULL))
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Call actual service to get the system date.  */
+    status =  _fx_system_date_get(year, month, day);
+
+    /* Return status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_system_date_set.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_system_date_set.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_system_date_set.c	(revision 30)
@@ -0,0 +1,257 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   System                                                              */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_system_date_set                                PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the set system date call.        */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    year                                  Year (1980-2107)              */
+/*    month                                 Month (1-12)                  */
+/*    day                                   Day (1-28/29/30/31)           */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    FX_INVALID_YEAR                       Supplied year is invalid      */
+/*    FX_INVALID_MONTH                      Supplied month is invalid     */
+/*    FX_INVALID_DAY                        Supplied day is invalid       */
+/*    status                                Actual completion status      */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_system_date_set                   Actual system date set call   */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_system_date_set(UINT year, UINT month, UINT day)
+{
+
+UINT  status;
+
+
+    /* Check for invalid year.  */
+    if ((year < FX_BASE_YEAR) || (year > FX_MAXIMUM_YEAR))
+    {
+        return(FX_INVALID_YEAR);
+    }
+
+    /* Check for invalid day.  */
+    if (day < 1)
+    {
+        return(FX_INVALID_DAY);
+    }
+
+    /* Check for invalid day.  */
+    switch (month)
+    {
+
+    case 1:
+    {
+
+        /* Check for 31 days.  */
+        if (day > 31)
+        {
+            return(FX_INVALID_DAY);
+        }
+        break;
+    }
+
+    case 2:
+    {
+
+        /* Check for leap year.  */
+        if ((year % 4) == 0)
+        {
+
+            /* Leap year, February has 29 days.  */
+            if (day > 29)
+            {
+                return(FX_INVALID_DAY);
+            }
+        }
+        else
+        {
+
+            /* Otherwise, non-leap year.  February has
+               28 days.  */
+            if (day > 28)
+            {
+                return(FX_INVALID_DAY);
+            }
+        }
+        break;
+    }
+
+    case 3:
+    {
+
+        /* Check for 31 days.  */
+        if (day > 31)
+        {
+            return(FX_INVALID_DAY);
+        }
+        break;
+    }
+
+    case 4:
+    {
+
+        /* Check for 30 days.  */
+        if (day > 30)
+        {
+            return(FX_INVALID_DAY);
+        }
+        break;
+    }
+
+    case 5:
+    {
+
+        /* Check for 31 days.  */
+        if (day > 31)
+        {
+            return(FX_INVALID_DAY);
+        }
+        break;
+    }
+
+    case 6:
+    {
+
+        /* Check for 30 days.  */
+        if (day > 30)
+        {
+            return(FX_INVALID_DAY);
+        }
+        break;
+    }
+
+    case 7:
+    {
+
+        /* Check for 31 days.  */
+        if (day > 31)
+        {
+            return(FX_INVALID_DAY);
+        }
+        break;
+    }
+
+    case 8:
+    {
+
+        /* Check for 31 days.  */
+        if (day > 31)
+        {
+            return(FX_INVALID_DAY);
+        }
+        break;
+    }
+
+    case 9:
+    {
+
+        /* Check for 30 days.  */
+        if (day > 30)
+        {
+            return(FX_INVALID_DAY);
+        }
+        break;
+    }
+
+    case 10:
+    {
+
+        /* Check for 31 days.  */
+        if (day > 31)
+        {
+            return(FX_INVALID_DAY);
+        }
+        break;
+    }
+
+    case 11:
+    {
+
+        /* Check for 30 days.  */
+        if (day > 30)
+        {
+            return(FX_INVALID_DAY);
+        }
+        break;
+    }
+
+    case 12:
+    {
+
+        /* Check for 31 days.  */
+        if (day > 31)
+        {
+            return(FX_INVALID_DAY);
+        }
+        break;
+    }
+    
+    default:
+    
+        /* Invalid month.  */
+        return(FX_INVALID_MONTH);
+    }
+
+    /* Call actual system date set service.  */
+    status =  _fx_system_date_set(year, month, day);
+
+    /* Return status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_system_time_get.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_system_time_get.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_system_time_get.c	(revision 30)
@@ -0,0 +1,92 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   System                                                              */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_system_time_get                                PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks of errors in the get system time call.         */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    hour                                  Pointer to hour               */
+/*    minute                                Pointer to minute             */
+/*    second                                Pointer to second             */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    FX_PTR_ERROR                          Invalid destination pointer   */
+/*    status                                Actual completion status      */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_system_time_get                   Actual get time service       */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_system_time_get(UINT *hour, UINT *minute, UINT *second)
+{
+
+UINT status;
+
+
+    /* Check for an invalid destination pointer.  */
+    if ((hour == FX_NULL) || (minute == FX_NULL) || (second == FX_NULL))
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Call actual get time service.  */
+    status =  _fx_system_time_get(hour, minute, second);
+
+    /* Return status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_system_time_set.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_system_time_set.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_system_time_set.c	(revision 30)
@@ -0,0 +1,106 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   System                                                              */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_system_time_set                                PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the set the system time call.    */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    hour                                  Hour (0-23)                   */
+/*    minute                                Minute (0-59)                 */
+/*    second                                Second (0-59)                 */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    FX_INVALID_HOUR                       Supplied hour is invalid      */
+/*    FX_INVALID_MINUTE                     Supplied minute is invalid    */
+/*    FX_INVALID_SECOND                     Supplied second is invalid    */
+/*    status                                Actual completion status      */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_system_time_set                   Actual system time set call   */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_system_time_set(UINT hour, UINT minute, UINT second)
+{
+
+UINT status;
+
+
+    /* Check for invalid hour.  */
+    if (hour > FX_MAXIMUM_HOUR)
+    {
+        return(FX_INVALID_HOUR);
+    }
+
+    /* Check for invalid minute.  */
+    if (minute > FX_MAXIMUM_MINUTE)
+    {
+        return(FX_INVALID_MINUTE);
+    }
+
+    /* Check for invalid second.  */
+    if (second > FX_MAXIMUM_SECOND)
+    {
+        return(FX_INVALID_SECOND);
+    }
+
+    /* Call the actual set system time service.  */
+    status =  _fx_system_time_set(hour, minute, second);
+
+    /* Return status.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_unicode_directory_create.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_unicode_directory_create.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_unicode_directory_create.c	(revision 30)
@@ -0,0 +1,108 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Unicode                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_unicode.h"
+
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_unicode_directory_create                       PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the Unicode directory create     */
+/*    service.                                                            */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Pointer to media              */
+/*    source_unicode_name                   Pointer to source unicode name*/
+/*    source_unicode_length                 Unicode name length           */
+/*    short_name                            Designated short name         */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    Completion Status                                                   */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_unicode_directory_create          Actual Unicode directory      */
+/*                                            create service              */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_unicode_directory_create(FX_MEDIA *media_ptr, UCHAR *source_unicode_name, ULONG source_unicode_length, CHAR *short_name)
+{
+
+UINT status, i;
+
+    /* Check for a NULL media or name pointers.  */
+    if ((media_ptr == FX_NULL) || (source_unicode_name == FX_NULL) || (source_unicode_length == 0) || (short_name == FX_NULL))
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Check unicode zero in source_unicode_name */
+    for (i = 0; i < (source_unicode_length << 1); i += 2)
+    {
+        if ((source_unicode_name[i] == 0) && (source_unicode_name[i + 1] == 0))
+        {
+            return(FX_INVALID_NAME);
+        }
+    }
+
+    /* Call actual Unicode directory create service.  */
+    status =  _fx_unicode_directory_create(media_ptr, source_unicode_name, source_unicode_length, short_name);
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_unicode_directory_rename.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_unicode_directory_rename.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_unicode_directory_rename.c	(revision 30)
@@ -0,0 +1,122 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Unicode                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_unicode.h"
+
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_unicode_directory_rename                       PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the Unicode directory rename     */
+/*    service.                                                            */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Pointer to media              */
+/*    old_unicode_name                      Pointer to old unicode name   */
+/*    old_unicode_length                    Old unicode name length       */
+/*    new_unicode_name                      Pointer to new unicode name   */
+/*    new_unicode_length                    Old unicode name length       */
+/*    new_short_name                        Pointer to new short name     */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    Completion Status                                                   */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_unicode_directory_rename          Actual Unicode directory      */
+/*                                            rename service              */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_unicode_directory_rename(FX_MEDIA *media_ptr, UCHAR *old_unicode_name, ULONG old_unicode_length,
+                                    UCHAR *new_unicode_name, ULONG new_unicode_length, CHAR *new_short_name)
+{
+
+UINT status, i;
+
+
+    /* Check for a NULL media or name pointers.  */
+    if ((media_ptr == FX_NULL) || (old_unicode_name == FX_NULL) || (old_unicode_length == 0) ||
+        (new_unicode_name == FX_NULL) || (new_unicode_length == 0) || (new_short_name == FX_NULL))
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Check unicode zero in old_unicode_name */
+    for (i = 0; i < (old_unicode_length << 1); i += 2)
+    {
+        if ((old_unicode_name[i] == 0) && (old_unicode_name[i + 1] == 0))
+        {
+            return(FX_INVALID_NAME);
+        }
+    }
+
+    /* Check unicode zero in new_unicode_name */
+    for (i = 0; i < (new_unicode_length << 1); i += 2)
+    {
+        if ((new_unicode_name[i] == 0) && (new_unicode_name[i + 1] == 0))
+        {
+            return(FX_INVALID_NAME);
+        }
+    }
+
+    /* Call actual Unicode directory rename service.  */
+    status =  _fx_unicode_directory_rename(media_ptr, old_unicode_name, old_unicode_length, new_unicode_name, new_unicode_length, new_short_name);
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_unicode_file_create.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_unicode_file_create.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_unicode_file_create.c	(revision 30)
@@ -0,0 +1,108 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Unicode                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_unicode.h"
+
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_unicode_file_create                            PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the Unicode file create service. */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Pointer to media              */
+/*    source_unicode_name                   Pointer to source unicode name*/
+/*    source_unicode_length                 Unicode name length           */
+/*    short_name                            Designated short name         */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    Completion Status                                                   */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_unicode_file_create               Actual Unicode file create    */
+/*                                            service                     */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_unicode_file_create(FX_MEDIA *media_ptr, UCHAR *source_unicode_name, ULONG source_unicode_length, CHAR *short_name)
+{
+
+UINT status, i;
+
+
+    /* Check for a NULL media or name pointers.  */
+    if ((media_ptr == FX_NULL) || (source_unicode_name == FX_NULL) || (source_unicode_length == 0) || (short_name == FX_NULL))
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Check unicode zero in source_unicode_name */
+    for (i = 0; i < (source_unicode_length << 1); i += 2)
+    {
+        if ((source_unicode_name[i] == 0) && (source_unicode_name[i + 1] == 0))
+        {
+            return(FX_INVALID_NAME);
+        }
+    }
+
+    /* Call actual Unicode file create service.  */
+    status =  _fx_unicode_file_create(media_ptr, source_unicode_name, source_unicode_length, short_name);
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_unicode_file_rename.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_unicode_file_rename.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_unicode_file_rename.c	(revision 30)
@@ -0,0 +1,122 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Unicode                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_unicode.h"
+
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_unicode_file_create                            PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the Unicode file rename service. */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Pointer to media              */
+/*    old_unicode_name                      Pointer to old unicode name   */
+/*    old_unicode_length                    Old unicode name length       */
+/*    new_unicode_name                      Pointer to new unicode name   */
+/*    new_unicode_length                    New unicode name length       */
+/*    new_short_name                        Designated new short name     */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    Completion Status                                                   */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_unicode_file_rename               Actual Unicode file rename    */
+/*                                            service                     */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT _fxe_unicode_file_rename(FX_MEDIA *media_ptr, UCHAR *old_unicode_name, ULONG old_unicode_length,
+                              UCHAR *new_unicode_name, ULONG new_unicode_length, CHAR *new_short_name)
+{
+
+UINT status, i;
+
+
+    /* Check for a NULL media or name pointers.  */
+    if ((media_ptr == FX_NULL) || (old_unicode_name == FX_NULL) || (old_unicode_length == 0) ||
+        (new_unicode_name == FX_NULL) || (new_unicode_length == 0) || (new_short_name == FX_NULL))
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Check unicode zero in old_unicode_name */
+    for (i = 0; i < (old_unicode_length << 1); i += 2)
+    {
+        if ((old_unicode_name[i] == 0) && (old_unicode_name[i + 1] == 0))
+        {
+            return(FX_INVALID_NAME);
+        }
+    }
+
+    /* Check unicode zero in new_unicode_name */
+    for (i = 0; i < (new_unicode_length << 1); i += 2)
+    {
+        if ((new_unicode_name[i] == 0) && (new_unicode_name[i + 1] == 0))
+        {
+            return(FX_INVALID_NAME);
+        }
+    }
+
+    /* Call actual Unicode file rename service.  */
+    status =  _fx_unicode_file_rename(media_ptr, old_unicode_name, old_unicode_length,
+                                      new_unicode_name, new_unicode_length, new_short_name);
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_unicode_name_get.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_unicode_name_get.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_unicode_name_get.c	(revision 30)
@@ -0,0 +1,101 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Unicode                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_unicode.h"
+
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_unicode_name_get                               PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the Unicode name get             */
+/*    service.                                                            */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Pointer to media              */
+/*    source_short_name                     Pointer to short file name    */
+/*    destination_unicode_name              Pointer to destination name   */
+/*    destination_unicode_length            Destination for name length   */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    Completion Status                                                   */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_unicode_search          Search for unicode name       */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_unicode_name_get(FX_MEDIA *media_ptr, CHAR *source_short_name,
+                            UCHAR *destination_unicode_name, ULONG *destination_unicode_length)
+{
+
+UINT status;
+
+
+    /* Check for a NULL media or name pointers.  */
+    if ((media_ptr == FX_NULL) || (source_short_name == FX_NULL) || (destination_unicode_name == FX_NULL) || (destination_unicode_length == FX_NULL))
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual Unicode name get service.  */
+    status =  _fx_unicode_name_get(media_ptr, source_short_name,
+                                   destination_unicode_name, destination_unicode_length);
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_unicode_name_get_extended.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_unicode_name_get_extended.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_unicode_name_get_extended.c	(revision 30)
@@ -0,0 +1,109 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Unicode                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_unicode.h"
+
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_unicode_name_get_extended                      PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the Unicode name get             */
+/*    service.                                                            */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Pointer to media              */
+/*    source_short_name                     Pointer to short file name    */
+/*    destination_unicode_name              Pointer to destination name   */
+/*    destination_unicode_length            Destination for name length   */
+/*    unicode_name_buffer_length            Buffer length of unicode name */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    Completion Status                                                   */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_unicode_name_get_extended         Actual unicode name get       */ 
+/*                                            service                     */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_unicode_name_get_extended(FX_MEDIA *media_ptr, CHAR *source_short_name,
+                            UCHAR *destination_unicode_name, ULONG *destination_unicode_length, ULONG unicode_name_buffer_length)
+{
+
+UINT status;
+
+
+    /* Check for a NULL media or name pointers.  */
+    if ((media_ptr == FX_NULL) || (source_short_name == FX_NULL) || (destination_unicode_name == FX_NULL) || (destination_unicode_length == FX_NULL))
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for zero length buffer.  */
+    if (unicode_name_buffer_length == 0)
+    {
+        return(FX_BUFFER_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual Unicode name get service.  */
+    status =  _fx_unicode_name_get_extended(media_ptr, source_short_name,
+                                   destination_unicode_name, destination_unicode_length, unicode_name_buffer_length);
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_unicode_short_name_get.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_unicode_short_name_get.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_unicode_short_name_get.c	(revision 30)
@@ -0,0 +1,109 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Unicode                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_unicode.h"
+
+
+FX_CALLER_CHECKING_EXTERNS
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_unicode_short_name_get                         PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the Unicode short name get       */
+/*    service.                                                            */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Pointer to media              */
+/*    source_unicode_name                   Pointer to unicode name       */
+/*    source_unicode_length                 Length of unicode name        */
+/*    destination_short_name                Pointer to destination name   */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    Completion Status                                                   */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_unicode_short_name_get            Actual unicode short name get */
+/*                                            service                     */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_unicode_short_name_get(FX_MEDIA *media_ptr, UCHAR *source_unicode_name, ULONG source_unicode_length,
+                                  CHAR *destination_short_name)
+{
+
+UINT status, i;
+
+
+    /* Check for a NULL media or name pointers.  */
+    if ((media_ptr == FX_NULL) || (source_unicode_name == FX_NULL) || (source_unicode_length == 0) || (destination_short_name == FX_NULL))
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Check unicode zero in source_unicode_name */
+    for (i = 0; i < (source_unicode_length << 1); i += 2)
+    {
+        if ((source_unicode_name[i] == 0) && (source_unicode_name[i + 1] == 0))
+        {
+            return(FX_INVALID_NAME);
+        }
+    }
+
+    /* Call actual Unicode short name get service.  */
+    status =  _fx_unicode_short_name_get(media_ptr, source_unicode_name, source_unicode_length, destination_short_name);
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_unicode_short_name_get_extended.c
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_unicode_short_name_get_extended.c	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/common/src/fxe_unicode_short_name_get_extended.c	(revision 30)
@@ -0,0 +1,116 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Unicode                                                             */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_unicode.h"
+
+
+FX_CALLER_CHECKING_EXTERNS
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_unicode_short_name_get_extended                PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the Unicode short name get       */
+/*    service.                                                            */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Pointer to media              */
+/*    source_unicode_name                   Pointer to unicode name       */
+/*    source_unicode_length                 Length of unicode name        */
+/*    destination_short_name                Pointer to destination name   */
+/*    short_name_buffer_length              Buffer length of short name   */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    Completion Status                                                   */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_unicode_short_name_get_extended   Actual unicode short name get */
+/*                                            service                     */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_unicode_short_name_get_extended(FX_MEDIA *media_ptr, UCHAR *source_unicode_name, ULONG source_unicode_length,
+                                  CHAR *destination_short_name, ULONG short_name_buffer_length)
+{
+
+UINT status, i;
+
+
+    /* Check for a NULL media or name pointers.  */
+    if ((media_ptr == FX_NULL) || (source_unicode_name == FX_NULL) || (source_unicode_length == 0) || (destination_short_name == FX_NULL))
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for zero length buffer.  */
+    if (short_name_buffer_length == 0)
+    {
+        return(FX_BUFFER_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Check unicode zero in source_unicode_name */
+    for (i = 0; i < (source_unicode_length << 1); i += 2)
+    {
+        if ((source_unicode_name[i] == 0) && (source_unicode_name[i + 1] == 0))
+        {
+            return(FX_INVALID_NAME);
+        }
+    }
+
+    /* Call actual Unicode short name get service.  */
+    status =  _fx_unicode_short_name_get_extended(media_ptr, source_unicode_name, source_unicode_length, destination_short_name, short_name_buffer_length);
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: trunk/firmware/App/CubeMX/Middlewares/ST/filex/ports/generic/inc/fx_port.h
===================================================================
--- trunk/firmware/App/CubeMX/Middlewares/ST/filex/ports/generic/inc/fx_port.h	(revision 30)
+++ trunk/firmware/App/CubeMX/Middlewares/ST/filex/ports/generic/inc/fx_port.h	(revision 30)
@@ -0,0 +1,227 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */ 
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Port Specific                                                       */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/ 
+/*                                                                        */ 
+/*  PORT SPECIFIC C INFORMATION                            RELEASE        */ 
+/*                                                                        */ 
+/*    fx_port.h                                            Generic        */ 
+/*                                                           6.3.0        */
+/*                                                                        */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */ 
+/*                                                                        */ 
+/*    This file contains data type definitions that make the FileX FAT    */ 
+/*    compatible file system function identically on a variety of         */ 
+/*    different processor architectures.  For example, the byte offset of */ 
+/*    various entries in the boot record, and directory entries are       */ 
+/*    defined in this file.                                               */ 
+/*                                                                        */ 
+/*  RELEASE HISTORY                                                       */ 
+/*                                                                        */ 
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  11-09-2020     William E. Lamie         Initial Version 6.1.2         */
+/*  03-02-2021     William E. Lamie         Modified comment(s), and      */
+/*                                            added standalone support,   */
+/*                                            resulting in version 6.1.5  */
+/*  10-31-2023     Xiuwen Cai               Modified comment(s),          */
+/*                                            added basic types guards,   */
+/*                                            resulting in version 6.3.0  */
+/*                                                                        */
+/**************************************************************************/
+
+#ifndef FX_PORT_H
+#define FX_PORT_H
+
+
+/* Determine if the optional FileX user define file should be used.  */
+
+#ifdef FX_INCLUDE_USER_DEFINE_FILE
+
+
+/* Yes, include the user defines in fx_user.h. The defines in this file may 
+   alternately be defined on the command line.  */
+
+#include "fx_user.h"
+#endif
+
+
+/* Include the ThreadX api file.  */
+
+#ifndef FX_STANDALONE_ENABLE
+#include "tx_api.h"
+
+
+/* Define ULONG64 typedef, if not already defined.  */
+
+#ifndef ULONG64_DEFINED
+#define ULONG64_DEFINED
+typedef unsigned long long  ULONG64;
+#endif
+
+#else
+
+/* Define compiler library include files.  */
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#ifndef VOID
+#define VOID                                    void
+typedef char                                    CHAR;
+typedef char                                    BOOL;
+typedef unsigned char                           UCHAR;
+typedef int                                     INT;
+typedef unsigned int                            UINT;
+typedef long                                    LONG;
+typedef unsigned long                           ULONG;
+typedef short                                   SHORT;
+typedef unsigned short                          USHORT;
+#endif
+
+#ifndef ULONG64_DEFINED
+#define ULONG64_DEFINED
+typedef unsigned long long                      ULONG64;
+#endif
+
+/* Define basic alignment type used in block and byte pool operations. This data type must
+   be at least 32-bits in size and also be large enough to hold a pointer type.  */
+
+#ifndef ALIGN_TYPE_DEFINED
+#define ALIGN_TYPE_DEFINED
+#define ALIGN_TYPE                              ULONG
+#endif
+
+#endif
+
+/* Define FileX internal protection macros.  If FX_SINGLE_THREAD is defined,
+   these protection macros are effectively disabled.  However, for multi-thread
+   uses, the macros are setup to utilize a ThreadX mutex for multiple thread 
+   access control into an open media.  */
+
+#if defined(FX_SINGLE_THREAD) || defined(FX_STANDALONE_ENABLE)
+#define FX_PROTECT                   
+#define FX_UNPROTECT
+#else
+#define FX_PROTECT                      if (media_ptr -> fx_media_id != FX_MEDIA_ID) return(FX_MEDIA_NOT_OPEN); \
+                                        else if (tx_mutex_get(&(media_ptr -> fx_media_protect), TX_WAIT_FOREVER) != TX_SUCCESS) return(FX_MEDIA_NOT_OPEN);
+#define FX_UNPROTECT                    tx_mutex_put(&(media_ptr -> fx_media_protect));
+#endif
+
+
+/* Define interrupt lockout constructs to protect the system date/time from being updated
+   while they are being read.  */
+#ifndef FX_STANDALONE_ENABLE
+#ifndef FX_INT_SAVE_AREA
+#define FX_INT_SAVE_AREA                unsigned int  old_interrupt_posture;
+#endif
+
+#ifndef FX_DISABLE_INTS
+#define FX_DISABLE_INTS                 old_interrupt_posture =  tx_interrupt_control(TX_INT_DISABLE);
+#endif
+
+#ifndef FX_RESTORE_INTS
+#define FX_RESTORE_INTS                 tx_interrupt_control(old_interrupt_posture);
+#endif
+#else
+/* Disable use of ThreadX protection in standalone mode for FileX */
+#ifndef FX_LEGACY_INTERRUPT_PROTECTION
+#define FX_LEGACY_INTERRUPT_PROTECTION
+#endif
+#define FX_INT_SAVE_AREA
+#define FX_DISABLE_INTS
+#define FX_RESTORE_INTS
+#endif
+
+/* Define the error checking logic to determine if there is a caller error in the FileX API.  
+   The default definitions assume ThreadX is being used.  This code can be completely turned 
+   off by just defining these macros to white space.  */
+
+#ifndef FX_STANDALONE_ENABLE
+#ifndef TX_TIMER_PROCESS_IN_ISR
+
+#define FX_CALLER_CHECKING_EXTERNS      extern  TX_THREAD      *_tx_thread_current_ptr; \
+                                        extern  TX_THREAD       _tx_timer_thread; \
+                                        extern  volatile ULONG  _tx_thread_system_state;
+
+#define FX_CALLER_CHECKING_CODE         if ((TX_THREAD_GET_SYSTEM_STATE()) || \
+                                            (_tx_thread_current_ptr == TX_NULL) || \
+                                            (_tx_thread_current_ptr == &_tx_timer_thread)) \
+                                            return(FX_CALLER_ERROR);
+
+#else
+#define FX_CALLER_CHECKING_EXTERNS      extern  TX_THREAD      *_tx_thread_current_ptr; \
+                                        extern  volatile ULONG  _tx_thread_system_state;
+
+#define FX_CALLER_CHECKING_CODE         if ((TX_THREAD_GET_SYSTEM_STATE()) || \
+                                            (_tx_thread_current_ptr == TX_NULL)) \
+                                            return(FX_CALLER_ERROR);
+#endif
+#else
+#define FX_CALLER_CHECKING_EXTERNS
+#define FX_CALLER_CHECKING_CODE
+#endif
+
+
+/* Define the update rate of the system timer.  These values may also be defined at the command
+   line when compiling the fx_system_initialize.c module in the FileX library build.  Alternatively, they can
+   be modified in this file or fx_user.h. Note: the update rate must be an even number of seconds greater
+   than or equal to 2, which is the minimal update rate for FAT time. */
+
+/* Define the number of seconds the timer parameters are updated in FileX.  The default
+   value is 10 seconds.  This value can be overwritten externally. */
+
+#ifndef FX_UPDATE_RATE_IN_SECONDS
+#define FX_UPDATE_RATE_IN_SECONDS 10
+#endif
+
+
+/* Defines the number of ThreadX timer ticks required to achieve the update rate specified by 
+   FX_UPDATE_RATE_IN_SECONDS defined previously. By default, the ThreadX timer tick is 10ms, 
+   so the default value for this constant is 1000.  If TX_TIMER_TICKS_PER_SECOND is defined,
+   this value is derived from TX_TIMER_TICKS_PER_SECOND.  */
+ 
+#ifndef FX_UPDATE_RATE_IN_TICKS
+#if (defined(TX_TIMER_TICKS_PER_SECOND) && (!defined(FX_STANDALONE_ENABLE)))
+#define FX_UPDATE_RATE_IN_TICKS         (TX_TIMER_TICKS_PER_SECOND * FX_UPDATE_RATE_IN_SECONDS)
+#else
+#define FX_UPDATE_RATE_IN_TICKS         1000 
+#endif
+#endif
+
+
+/* Define the version ID of FileX.  This may be utilized by the application.  */
+
+#ifdef FX_SYSTEM_INIT
+CHAR                            _fx_version_id[] = 
+                                    "Copyright (c) Microsoft Corporation. All rights reserved.  *  FileX Generic Version 6.4.0 *";
+#else
+extern  CHAR                    _fx_version_id[];
+#endif
+
+#endif
+
