Home | History | Annotate | Download | only in ramdisk
      1 
      2 /*
      3  * Copyright (c) 1999, 2000
      4  * Intel Corporation.
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without modification,
      8  * are permitted provided that the following conditions are met:
      9  *
     10  * 1. Redistributions of source code must retain the above copyright notice,
     11  *    this list of conditions and the following disclaimer.
     12  *
     13  * 2. Redistributions in binary form must reproduce the above copyright notice,
     14  *    this list of conditions and the following disclaimer in the documentation
     15  *    and/or other materials provided with the distribution.
     16  *
     17  * 3. All advertising materials mentioning features or use of this software must
     18  *    display the following acknowledgement:
     19  *
     20  *    This product includes software developed by Intel Corporation and its
     21  *    contributors.
     22  *
     23  * 4. Neither the name of Intel Corporation or its contributors may be used to
     24  *    endorse or promote products derived from this software without specific
     25  *    prior written permission.
     26  *
     27  * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION AND CONTRIBUTORS ``AS IS'' AND
     28  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     29  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     30  * DISCLAIMED.  IN NO EVENT SHALL INTEL CORPORATION OR CONTRIBUTORS BE LIABLE FOR
     31  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     32  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     33  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
     34  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     35  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     36  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     37  *
     38  */
     39 #include <Uefi.h>
     40 
     41 #include <Protocol/BlockIo.h>
     42 #include <Protocol/LoadedImage.h>
     43 #include <Library/DebugLib.h>
     44 #include <Library/BaseMemoryLib.h>
     45 #include <Library/UefiDriverEntryPoint.h>
     46 #include <Library/UefiBootServicesTableLib.h>
     47 #include <Library/UefiLib.h>
     48 #include <Library/BaseLib.h>
     49 #include <Library/PcdLib.h>
     50 #include <Library/MemoryAllocationLib.h>
     51 #include <Library/DevicePathLib.h>
     52 
     53 #include <Guid/RamDiskGuid.h>
     54 #include "ramdisk.h"
     55 
     56 
     57 UINT32    GetDiskSize( EFI_HANDLE ImageHandle );
     58 
     59 /* Embedded version string for VERS utility */
     60 //static char v[] = "version_number=1.00 ";
     61 
     62 /* EFI device path definition */
     63 static RAM_DISK_DEVICE_PATH RamDiskDevicePath =
     64 {
     65   {MESSAGING_DEVICE_PATH,
     66   MSG_VENDOR_DP,
     67   {sizeof(RAM_DISK_DEVICE_PATH) - END_DEVICE_PATH_LENGTH,
     68   0}},
     69   RAM_DISK_GUID,
     70   {0,0,0,0,0,0,0,0},  // ID assigned below
     71   {END_DEVICE_PATH_TYPE,
     72   END_ENTIRE_DEVICE_PATH_SUBTYPE,
     73   {END_DEVICE_PATH_LENGTH}}
     74 };
     75 
     76 /* Lookup table of total sectors vs. cluster size.
     77  * Ramdisk sizes between 0x20D0 (4.1MB) and 0x100000 (512MB) sectors are valid FAT16 drive sizes.
     78  */
     79 #define MIN_DISK_SIZE  1
     80 #define  MAX_DISK_SIZE  512
     81 static FAT16TABLE fat16tbl[] =
     82 {
     83   {0x00000800, 1},  /* 800 sectors * 1 sec/cluster * 512 bytes = 1 M */
     84   {0x00001000, 1},  /* 1000 sectors * 1 sec/cluster * 512 bytes = 2 M */
     85   {0x00001800, 1},  /* 1800 sectors * 1 sec/cluster * 512 bytes = 3 M */
     86   {0x00007FA8, 2},
     87   {0x00040000, 4},
     88   {0x00080000, 8},
     89   {0x00100000,16},
     90   {0xFFFFFFFF, 0}
     91 };
     92 
     93 VOID CopyBOOTSEC(VOID* Start,BOOTSEC* bsc)
     94 {
     95 UINT32 index=0;
     96 UINT8* pStart=(UINT8*)Start;
     97 
     98 CopyMem(&(pStart[index]), &(bsc->BS_jmpBoot[0]), sizeof(bsc->BS_jmpBoot));
     99 index+=sizeof(bsc->BS_jmpBoot);
    100 
    101 CopyMem(&(pStart[index]), &(bsc->BS_OEMName[0]), sizeof(bsc->BS_OEMName));
    102 index+=sizeof(bsc->BS_OEMName);
    103 
    104 CopyMem(&(pStart[index]), &(bsc->BPB_BytsPerSec), sizeof(bsc->BPB_BytsPerSec));
    105 index+=sizeof(bsc->BPB_BytsPerSec);
    106 
    107 CopyMem(&(pStart[index]), &(bsc->BPB_SecPerClus), sizeof(bsc->BPB_SecPerClus));
    108 index+=sizeof(bsc->BPB_SecPerClus);
    109 
    110 CopyMem(&(pStart[index]), &(bsc->BPB_RsvdSecCnt), sizeof(bsc->BPB_RsvdSecCnt));
    111 index+=sizeof(bsc->BPB_RsvdSecCnt);
    112 
    113 CopyMem(&(pStart[index]), &(bsc->BPB_NumFATs), sizeof(bsc->BPB_NumFATs));
    114 index+=sizeof(bsc->BPB_NumFATs);
    115 
    116 CopyMem(&(pStart[index]), &(bsc->BPB_NumFATs), sizeof(bsc->BPB_NumFATs));
    117 index+=sizeof(bsc->BPB_NumFATs);
    118 
    119 CopyMem(&(pStart[index]), &(bsc->BPB_RootEntCnt), sizeof(bsc->BPB_RootEntCnt));
    120 index+=sizeof(bsc->BPB_RootEntCnt);
    121 
    122 CopyMem(&(pStart[index]), &(bsc->BPB_TotSec16), sizeof(bsc->BPB_TotSec16));
    123 index+=sizeof(bsc->BPB_TotSec16);
    124 
    125 CopyMem(&(pStart[index]), &(bsc->BPB_Media), sizeof(bsc->BPB_Media));
    126 index+=sizeof(bsc->BPB_Media);
    127 
    128 CopyMem(&(pStart[index]), &(bsc->BPB_FATSz16), sizeof(bsc->BPB_FATSz16));
    129 index+=sizeof(bsc->BPB_FATSz16);
    130 
    131 CopyMem(&(pStart[index]), &(bsc->BPB_SecPerTrk), sizeof(bsc->BPB_SecPerTrk));
    132 index+=sizeof(bsc->BPB_SecPerTrk);
    133 
    134 CopyMem(&(pStart[index]), &(bsc->BPB_NumHeads), sizeof(bsc->BPB_NumHeads));
    135 index+=sizeof(bsc->BPB_NumHeads);
    136 
    137 CopyMem(&(pStart[index]), &(bsc->BPB_HiddSec), sizeof(bsc->BPB_HiddSec));
    138 index+=sizeof(bsc->BPB_HiddSec);
    139 
    140 CopyMem(&(pStart[index]), &(bsc->BPB_TotSec32), sizeof(bsc->BPB_TotSec32));
    141 index+=sizeof(bsc->BPB_TotSec32);
    142 
    143 CopyMem(&(pStart[index]), &(bsc->BS_DrvNum), sizeof(bsc->BS_DrvNum));
    144 index+=sizeof(bsc->BS_DrvNum);
    145 
    146 CopyMem(&(pStart[index]), &(bsc->BS_Reserved1), sizeof(bsc->BS_Reserved1));
    147 index+=sizeof(bsc->BS_Reserved1);
    148 
    149 CopyMem(&(pStart[index]), &(bsc->BS_BootSig), sizeof(bsc->BS_BootSig));
    150 index+=sizeof(bsc->BS_BootSig);
    151 
    152 CopyMem(&(pStart[index]), &(bsc->BS_VolID), sizeof(bsc->BS_VolID));
    153 index+=sizeof(bsc->BS_VolID);
    154 
    155 CopyMem(&(pStart[index]), &(bsc->BS_VolLab[0]), sizeof(bsc->BS_VolLab));
    156 index+=sizeof(bsc->BS_VolLab);
    157 
    158 CopyMem(&(pStart[index]), &(bsc->BS_FilSysType[0]), sizeof(bsc->BS_FilSysType));
    159 index+=sizeof(bsc->BS_FilSysType);
    160 
    161 CopyMem(&(pStart[index]), &(bsc->BS_Code[0]), sizeof(bsc->BS_Code));
    162 index+=sizeof(bsc->BS_Code);
    163 
    164 CopyMem(&(pStart[index]), &(bsc->BS_Sig), sizeof(bsc->BS_Sig));
    165 
    166 }
    167 
    168 
    169 
    170 /* Helper function to compute cluster size
    171  * vs. total sectors on drive.
    172  */
    173 STATIC UINT8 size2spc(UINT32 ts)
    174 {
    175   int i = 0;
    176 
    177   while(fat16tbl[i].size != 0xFFFFFFFF)
    178   {
    179     if(ts <= fat16tbl[i].size)
    180       return fat16tbl[i].spc;
    181     ++i;
    182   }
    183 
    184   return 0;
    185 }
    186 
    187 UINT8 TestSize(UINT32 ts)
    188 {
    189   int i = 0;
    190 
    191   while(fat16tbl[i].size != 0xFFFFFFFF)
    192   {
    193     if(ts <= fat16tbl[i].size)
    194       return fat16tbl[i].spc;
    195     ++i;
    196   }
    197 
    198   return 0;
    199 }
    200 
    201 EFI_SYSTEM_TABLE  BackupSystemTable;
    202 
    203 /*
    204  * Entry point for RamDisk driver.
    205  */
    206 
    207 EFI_STATUS InitializeRamDiskDriver(
    208   IN EFI_HANDLE       ImageHandle,
    209   IN EFI_SYSTEM_TABLE *SystemTable)
    210 {
    211   EFI_STATUS           Status;
    212   RAM_DISK_DEV         *RamDiskDev;
    213   UINT32               RamDiskSize;
    214   UINT32               NumPages;
    215   UINT32               BlockSize;
    216   UINT64               DiskId;
    217 
    218   /*
    219    * Make a copy of the system table to workaround load command bug
    220    */
    221   CopyMem(&BackupSystemTable,SystemTable,sizeof(BackupSystemTable));
    222 
    223   /*
    224    * Initialize EFI library
    225    */
    226   //InitializeLib(ImageHandle,&BackupSystemTable);
    227 
    228   /* IA64 compiler is removing version string (unused?) so I use it */
    229   //v[0] = 'v';
    230 
    231   /*
    232    *  Set the disk size
    233    */
    234   RamDiskSize = GetDiskSize(ImageHandle);
    235   BlockSize   = 512;
    236 
    237   /* Allocate storage for ramdisk device info on the heap.
    238    */
    239   RamDiskDev = AllocateZeroPool(sizeof(RAM_DISK_DEV));
    240   if(RamDiskDev == NULL)
    241     return EFI_OUT_OF_RESOURCES;
    242 
    243   /*
    244    * Compute the number of 4KB pages needed by the ramdisk and allocate the memory.
    245    */
    246   NumPages = RamDiskSize / EFI_PAGE_SIZE;
    247   if(NumPages % RamDiskSize)
    248     NumPages++;
    249 
    250   Status = gBS->AllocatePages(AllocateAnyPages,EfiBootServicesData,NumPages,&RamDiskDev->Start);
    251   if(EFI_ERROR(Status)) {
    252     FreePool(RamDiskDev);
    253     return Status;
    254   }
    255 
    256   /*
    257    * Initialize the ramdisk's device info.
    258    */
    259   (void)gBS->GetNextMonotonicCount(&DiskId);
    260   CopyMem(&RamDiskDevicePath.DiskId, &DiskId, sizeof(DiskId));
    261 
    262   RamDiskDev->Signature            = PBLOCK_DEVICE_SIGNATURE;
    263   RamDiskDev->BlkIo.Revision       = EFI_BLOCK_IO_INTERFACE_REVISION;
    264   RamDiskDev->BlkIo.Media          = &RamDiskDev->Media;
    265   RamDiskDev->Media.RemovableMedia = FALSE;
    266   RamDiskDev->Media.MediaPresent   = TRUE;
    267 
    268   RamDiskDev->Media.LastBlock        = RamDiskSize/BlockSize - 1;
    269   RamDiskDev->Media.BlockSize        = BlockSize;
    270   RamDiskDev->Media.LogicalPartition = TRUE;
    271   RamDiskDev->Media.ReadOnly         = FALSE;
    272   RamDiskDev->Media.WriteCaching     = TRUE;
    273 
    274   RamDiskDev->BlkIo.ReadBlocks  = RamDiskReadBlocks;
    275   RamDiskDev->BlkIo.WriteBlocks = RamDiskWriteBlocks;
    276   RamDiskDev->BlkIo.FlushBlocks = RamDiskFlushBlocks;
    277 
    278   RamDiskDev->DevicePath = DuplicateDevicePath((EFI_DEVICE_PATH*)&RamDiskDevicePath);
    279 
    280   /*
    281    * Build a FAT16 file system on the ramdisk.
    282    */
    283   FormatRamdisk((VOID*)(UINTN)RamDiskDev->Start,RamDiskSize);
    284 
    285   /*
    286    * Install the device.
    287    */
    288 
    289   Status = gBS->InstallMultipleProtocolInterfaces(
    290   &ImageHandle,
    291   &gEfiBlockIoProtocolGuid,
    292   &RamDiskDev->BlkIo,
    293   &gEfiDevicePathProtocolGuid,
    294   RamDiskDev->DevicePath,
    295   NULL);
    296 
    297 DEBUG((EFI_D_ERROR,"ramdisk:blckio install. Status=%r\n",Status));
    298   return Status;
    299 }
    300 
    301 UINT32
    302 GetDiskSize( EFI_HANDLE ImageHandle )
    303 {
    304   EFI_STATUS      Status;
    305   EFI_LOADED_IMAGE  *Image;
    306   UINT32        DiskSize = PcdGet32(PcdRamDiskMaxSize);
    307 
    308   /*
    309    * Check load options to see if they want to specify disk size in MBs
    310    */
    311   Status = gBS->HandleProtocol(ImageHandle, &gEfiLoadedImageProtocolGuid, (void**)&Image);
    312   if (!EFI_ERROR(Status)) {
    313     if (Image->LoadOptions && Image->LoadOptionsSize) {
    314 #define MAX_ARG_SIZE    32
    315       CHAR16  Size[ MAX_ARG_SIZE ];
    316       CHAR16  *CmdLine = Image->LoadOptions;
    317       INT32  CmdLen   = (INT32)Image->LoadOptionsSize;
    318 
    319       /*
    320        * Get past program name
    321        */
    322       while( CmdLen > 0 && *CmdLine != L' ' ) {
    323         CmdLen -= sizeof(CHAR16);
    324         CmdLine++;
    325       }
    326 
    327       if ( CmdLen > 0 ) {
    328         /*
    329          * Make sure we're null terminated
    330          */
    331         CopyMem( Size, CmdLine, MIN(CmdLen, (INT32)sizeof(Size)));
    332         Size[MAX_ARG_SIZE - 1] = 0;
    333 
    334         /*
    335          *  Atoi() will skip any leading white space
    336          */
    337         DiskSize = (UINT32)StrDecimalToUintn(Size);
    338         if (DiskSize == 0)
    339           DiskSize = PcdGet32(PcdRamDiskMaxSize);
    340         DiskSize = MAX(DiskSize, MIN_DISK_SIZE);
    341         DiskSize = MIN(DiskSize, MAX_DISK_SIZE);
    342       }
    343     }
    344   }
    345 
    346   return (DiskSize * 1024 * 1024);
    347 }
    348 
    349 /* Given a block of memory representing a ramdisk, build a pseudo-boot sector
    350  * and initialize the drive.
    351  *
    352  * Assumes the global boot sector structure g_bs has been filled out with the
    353  * static information the boot sector requires.  Also assumes the ramdisk size
    354  * is between 4.1MB and 512MB as appropriate for FAT16 file system.
    355  */
    356 STATIC VOID FormatRamdisk(
    357   IN VOID*  pStart,
    358   IN UINT32 Size)
    359 {
    360   UINT32 TotalSectors,RootDirSectors,FatSz,tmp1,tmp2;
    361   UINT8 *Fat1,*Fat2;
    362     BOOTSEC g_bs;
    363 
    364     g_bs.BS_jmpBoot[0] = 0xeb;
    365     g_bs.BS_jmpBoot[1] = 0x0;
    366     g_bs.BS_jmpBoot[2] = 0x90;
    367     g_bs.BS_OEMName[0] = 'E';
    368     g_bs.BS_OEMName[1] = 'F';
    369     g_bs.BS_OEMName[2] = 'I';
    370     g_bs.BS_OEMName[3] = 'R';
    371     g_bs.BS_OEMName[4] = 'D';
    372     g_bs.BS_OEMName[5] = 'I';
    373     g_bs.BS_OEMName[6] = 'S';
    374     g_bs.BS_OEMName[7] = 'K';
    375     g_bs.BPB_BytsPerSec = 512;
    376     g_bs.BPB_SecPerClus = 0;
    377     g_bs.BPB_RsvdSecCnt = 1;
    378     g_bs.BPB_NumFATs = 2;
    379     g_bs.BPB_RootEntCnt = 512;
    380     g_bs.BPB_TotSec16 = 0;
    381     g_bs.BPB_Media = 0xF8;
    382     g_bs.BPB_FATSz16 = 0;
    383     g_bs.BPB_SecPerTrk = 0;
    384     g_bs.BPB_NumHeads = 0;
    385     g_bs.BPB_HiddSec = 0;
    386     g_bs.BPB_TotSec32 = 0;
    387     g_bs.BS_DrvNum = 0;
    388     g_bs.BS_Reserved1 = 0;
    389     g_bs.BS_BootSig = 0x29;
    390     g_bs.BS_VolID = 0;
    391     g_bs.BS_VolLab[0] = 'N';
    392     g_bs.BS_VolLab[1] = 'O';
    393     g_bs.BS_VolLab[2] = ' ';
    394     g_bs.BS_VolLab[3] = 'N';
    395     g_bs.BS_VolLab[4] = 'A';
    396     g_bs.BS_VolLab[5] = 'M';
    397     g_bs.BS_VolLab[6] = 'E';
    398     g_bs.BS_VolLab[7] = ' ';
    399     g_bs.BS_VolLab[8] = ' ';
    400     g_bs.BS_FilSysType[0] = 'F';
    401     g_bs.BS_FilSysType[1] = 'A';
    402     g_bs.BS_FilSysType[2] = 'T';
    403     g_bs.BS_FilSysType[3] = '1';
    404     g_bs.BS_FilSysType[4] = '6';
    405     g_bs.BS_FilSysType[5] = ' ';
    406     g_bs.BS_FilSysType[6] = ' ';
    407     g_bs.BS_FilSysType[7] = ' ';
    408   /* The boot signature needs to be filled out */
    409   g_bs.BS_Sig = 0xAA55;
    410 
    411   /* Compute the total sectors and appropriate cluster size */
    412   TotalSectors = Size / g_bs.BPB_BytsPerSec;
    413   g_bs.BPB_SecPerClus = size2spc(TotalSectors);
    414   ASSERT(g_bs.BPB_SecPerClus != 0);
    415 
    416   /* Compute how many root directory sectors are needed */
    417   RootDirSectors = (g_bs.BPB_RootEntCnt * 32 + g_bs.BPB_BytsPerSec - 1) / g_bs.BPB_BytsPerSec;
    418 
    419   /* Compute how many sectors are required per FAT */
    420   tmp1 = TotalSectors - (g_bs.BPB_RsvdSecCnt + RootDirSectors);
    421   tmp2 = 256 * g_bs.BPB_SecPerClus + g_bs.BPB_NumFATs;
    422   FatSz = (tmp1 + tmp2 - 1) / tmp2;
    423   ASSERT(FatSz <= 0xFFFF);
    424 
    425   /* Store the total sectors and fat size values */
    426   if(TotalSectors > 0xFFFF)
    427     g_bs.BPB_TotSec32 = TotalSectors;
    428   else
    429     g_bs.BPB_TotSec16 = (UINT16)TotalSectors;
    430 
    431   g_bs.BPB_FATSz16 = (UINT16)FatSz;
    432 
    433   /* The FAT table and root directory need to be all zeroes.
    434    * We'll zero the whole drive.
    435    */
    436   ZeroMem(pStart,Size);
    437 
    438   /* Write the completed boot sector to the ramdisk */
    439   CopyMem(pStart,&g_bs,512);
    440 
    441   /* Compute the starting offsets of the two FATs */
    442   Fat1 = (UINT8*)pStart + g_bs.BPB_RsvdSecCnt * 512;
    443   Fat2 = (UINT8*)pStart + (UINTN)(g_bs.BPB_RsvdSecCnt + FatSz) * 512;
    444 
    445   /* Initialize FAT1 */
    446   Fat1[0] = g_bs.BPB_Media;
    447   Fat1[1] = 0xFF;
    448   Fat1[2] = 0xFF;
    449   Fat1[3] = 0xFF;
    450 
    451   /* Initialize FAT2 */
    452   Fat2[0] = g_bs.BPB_Media;
    453   Fat2[1] = 0xFF;
    454   Fat2[2] = 0xFF;
    455   Fat2[3] = 0xFF;
    456 }
    457 
    458 /* Implementation of block I/O read */
    459 STATIC EFI_STATUS RamDiskReadBlocks(
    460   IN EFI_BLOCK_IO *This,
    461   IN UINT32       MediaId,
    462   IN EFI_LBA      LBA,
    463   IN UINTN        BufferSize,
    464   OUT VOID        *Buffer)
    465 {
    466   EFI_BLOCK_IO_MEDIA   *Media;
    467   RAM_DISK_DEV         *RamDiskDev;
    468   EFI_PHYSICAL_ADDRESS RamDiskLBA;
    469 
    470   Media = This->Media;
    471 
    472   if(BufferSize % Media->BlockSize != 0)
    473     return EFI_BAD_BUFFER_SIZE;
    474 
    475   if(LBA > Media->LastBlock)
    476     return EFI_DEVICE_ERROR;
    477 
    478   if(LBA + BufferSize / Media->BlockSize - 1 > Media->LastBlock)
    479     return EFI_DEVICE_ERROR;
    480 
    481   RamDiskDev = RAM_DISK_FROM_THIS(This);
    482   RamDiskLBA = RamDiskDev->Start + MultU64x32(LBA,Media->BlockSize);
    483   CopyMem(Buffer,(VOID*)(UINTN)RamDiskLBA,BufferSize);
    484 
    485   return EFI_SUCCESS;
    486 }
    487 
    488 
    489 /* Implementation of block I/O write */
    490 STATIC EFI_STATUS RamDiskWriteBlocks(
    491   IN EFI_BLOCK_IO *This,
    492   IN UINT32       MediaId,
    493   IN EFI_LBA      LBA,
    494   IN UINTN        BufferSize,
    495   IN VOID         *Buffer)
    496 {
    497   EFI_BLOCK_IO_MEDIA   *Media;
    498   RAM_DISK_DEV         *RamDiskDev;
    499   EFI_PHYSICAL_ADDRESS RamDiskLBA;
    500 
    501   Media = This->Media;
    502   if(Media->ReadOnly)
    503     return EFI_WRITE_PROTECTED;
    504 
    505   if(BufferSize % Media->BlockSize != 0)
    506     return EFI_BAD_BUFFER_SIZE;
    507 
    508   if(LBA > Media->LastBlock)
    509     return EFI_DEVICE_ERROR;
    510 
    511   if(LBA + BufferSize / Media->BlockSize - 1 > Media->LastBlock)
    512     return EFI_DEVICE_ERROR;
    513 
    514   RamDiskDev = RAM_DISK_FROM_THIS(This);
    515   RamDiskLBA = RamDiskDev->Start + MultU64x32(LBA,Media->BlockSize);
    516   CopyMem((VOID*)(UINTN)RamDiskLBA,Buffer,BufferSize);
    517 
    518   return EFI_SUCCESS;
    519 }
    520 
    521 /* Implementation of block I/O flush */
    522 STATIC EFI_STATUS RamDiskFlushBlocks(
    523   IN EFI_BLOCK_IO *This)
    524 {
    525   return EFI_SUCCESS;
    526 }
    527