aboutsummaryrefslogtreecommitdiffstats
path: root/Drivers/Block/ramdisk/ramdisk.c
diff options
context:
space:
mode:
Diffstat (limited to 'Drivers/Block/ramdisk/ramdisk.c')
-rw-r--r--Drivers/Block/ramdisk/ramdisk.c526
1 files changed, 526 insertions, 0 deletions
diff --git a/Drivers/Block/ramdisk/ramdisk.c b/Drivers/Block/ramdisk/ramdisk.c
new file mode 100644
index 0000000..21e090b
--- /dev/null
+++ b/Drivers/Block/ramdisk/ramdisk.c
@@ -0,0 +1,526 @@
+
+/*
+ * Copyright (c) 1999, 2000
+ * Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this software must
+ * display the following acknowledgement:
+ *
+ * This product includes software developed by Intel Corporation and its
+ * contributors.
+ *
+ * 4. Neither the name of Intel Corporation or its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#include <Uefi.h>
+
+#include <Protocol/BlockIo.h>
+#include <Protocol/LoadedImage.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PcdLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DevicePathLib.h>
+
+#include <Guid/RamDiskGuid.h>
+#include "ramdisk.h"
+
+
+UINT32 GetDiskSize( EFI_HANDLE ImageHandle );
+
+/* Embedded version string for VERS utility */
+//static char v[] = "version_number=1.00 ";
+
+/* EFI device path definition */
+static RAM_DISK_DEVICE_PATH RamDiskDevicePath =
+{
+ {MESSAGING_DEVICE_PATH,
+ MSG_VENDOR_DP,
+ {sizeof(RAM_DISK_DEVICE_PATH) - END_DEVICE_PATH_LENGTH,
+ 0}},
+ RAM_DISK_GUID,
+ {0,0,0,0,0,0,0,0}, // ID assigned below
+ {END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {END_DEVICE_PATH_LENGTH}}
+};
+
+/* Lookup table of total sectors vs. cluster size.
+ * Ramdisk sizes between 0x20D0 (4.1MB) and 0x100000 (512MB) sectors are valid FAT16 drive sizes.
+ */
+#define MIN_DISK_SIZE 1
+#define MAX_DISK_SIZE 512
+static FAT16TABLE fat16tbl[] =
+{
+ {0x00000800, 1}, /* 800 sectors * 1 sec/cluster * 512 bytes = 1 M */
+ {0x00001000, 1}, /* 1000 sectors * 1 sec/cluster * 512 bytes = 2 M */
+ {0x00001800, 1}, /* 1800 sectors * 1 sec/cluster * 512 bytes = 3 M */
+ {0x00007FA8, 2},
+ {0x00040000, 4},
+ {0x00080000, 8},
+ {0x00100000,16},
+ {0xFFFFFFFF, 0}
+};
+
+VOID CopyBOOTSEC(VOID* Start,BOOTSEC* bsc)
+{
+UINT32 index=0;
+UINT8* pStart=(UINT8*)Start;
+
+CopyMem(&(pStart[index]), &(bsc->BS_jmpBoot[0]), sizeof(bsc->BS_jmpBoot));
+index+=sizeof(bsc->BS_jmpBoot);
+
+CopyMem(&(pStart[index]), &(bsc->BS_OEMName[0]), sizeof(bsc->BS_OEMName));
+index+=sizeof(bsc->BS_OEMName);
+
+CopyMem(&(pStart[index]), &(bsc->BPB_BytsPerSec), sizeof(bsc->BPB_BytsPerSec));
+index+=sizeof(bsc->BPB_BytsPerSec);
+
+CopyMem(&(pStart[index]), &(bsc->BPB_SecPerClus), sizeof(bsc->BPB_SecPerClus));
+index+=sizeof(bsc->BPB_SecPerClus);
+
+CopyMem(&(pStart[index]), &(bsc->BPB_RsvdSecCnt), sizeof(bsc->BPB_RsvdSecCnt));
+index+=sizeof(bsc->BPB_RsvdSecCnt);
+
+CopyMem(&(pStart[index]), &(bsc->BPB_NumFATs), sizeof(bsc->BPB_NumFATs));
+index+=sizeof(bsc->BPB_NumFATs);
+
+CopyMem(&(pStart[index]), &(bsc->BPB_NumFATs), sizeof(bsc->BPB_NumFATs));
+index+=sizeof(bsc->BPB_NumFATs);
+
+CopyMem(&(pStart[index]), &(bsc->BPB_RootEntCnt), sizeof(bsc->BPB_RootEntCnt));
+index+=sizeof(bsc->BPB_RootEntCnt);
+
+CopyMem(&(pStart[index]), &(bsc->BPB_TotSec16), sizeof(bsc->BPB_TotSec16));
+index+=sizeof(bsc->BPB_TotSec16);
+
+CopyMem(&(pStart[index]), &(bsc->BPB_Media), sizeof(bsc->BPB_Media));
+index+=sizeof(bsc->BPB_Media);
+
+CopyMem(&(pStart[index]), &(bsc->BPB_FATSz16), sizeof(bsc->BPB_FATSz16));
+index+=sizeof(bsc->BPB_FATSz16);
+
+CopyMem(&(pStart[index]), &(bsc->BPB_SecPerTrk), sizeof(bsc->BPB_SecPerTrk));
+index+=sizeof(bsc->BPB_SecPerTrk);
+
+CopyMem(&(pStart[index]), &(bsc->BPB_NumHeads), sizeof(bsc->BPB_NumHeads));
+index+=sizeof(bsc->BPB_NumHeads);
+
+CopyMem(&(pStart[index]), &(bsc->BPB_HiddSec), sizeof(bsc->BPB_HiddSec));
+index+=sizeof(bsc->BPB_HiddSec);
+
+CopyMem(&(pStart[index]), &(bsc->BPB_TotSec32), sizeof(bsc->BPB_TotSec32));
+index+=sizeof(bsc->BPB_TotSec32);
+
+CopyMem(&(pStart[index]), &(bsc->BS_DrvNum), sizeof(bsc->BS_DrvNum));
+index+=sizeof(bsc->BS_DrvNum);
+
+CopyMem(&(pStart[index]), &(bsc->BS_Reserved1), sizeof(bsc->BS_Reserved1));
+index+=sizeof(bsc->BS_Reserved1);
+
+CopyMem(&(pStart[index]), &(bsc->BS_BootSig), sizeof(bsc->BS_BootSig));
+index+=sizeof(bsc->BS_BootSig);
+
+CopyMem(&(pStart[index]), &(bsc->BS_VolID), sizeof(bsc->BS_VolID));
+index+=sizeof(bsc->BS_VolID);
+
+CopyMem(&(pStart[index]), &(bsc->BS_VolLab[0]), sizeof(bsc->BS_VolLab));
+index+=sizeof(bsc->BS_VolLab);
+
+CopyMem(&(pStart[index]), &(bsc->BS_FilSysType[0]), sizeof(bsc->BS_FilSysType));
+index+=sizeof(bsc->BS_FilSysType);
+
+CopyMem(&(pStart[index]), &(bsc->BS_Code[0]), sizeof(bsc->BS_Code));
+index+=sizeof(bsc->BS_Code);
+
+CopyMem(&(pStart[index]), &(bsc->BS_Sig), sizeof(bsc->BS_Sig));
+
+}
+
+
+
+/* Helper function to compute cluster size
+ * vs. total sectors on drive.
+ */
+STATIC UINT8 size2spc(UINT32 ts)
+{
+ int i = 0;
+
+ while(fat16tbl[i].size != 0xFFFFFFFF)
+ {
+ if(ts <= fat16tbl[i].size)
+ return fat16tbl[i].spc;
+ ++i;
+ }
+
+ return 0;
+}
+
+UINT8 TestSize(UINT32 ts)
+{
+ int i = 0;
+
+ while(fat16tbl[i].size != 0xFFFFFFFF)
+ {
+ if(ts <= fat16tbl[i].size)
+ return fat16tbl[i].spc;
+ ++i;
+ }
+
+ return 0;
+}
+
+EFI_SYSTEM_TABLE BackupSystemTable;
+
+/*
+ * Entry point for RamDisk driver.
+ */
+
+EFI_STATUS InitializeRamDiskDriver(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable)
+{
+ EFI_STATUS Status;
+ RAM_DISK_DEV *RamDiskDev;
+ UINT32 RamDiskSize;
+ UINT32 NumPages;
+ UINT32 BlockSize;
+ UINT64 DiskId;
+
+ /*
+ * Make a copy of the system table to workaround load command bug
+ */
+ CopyMem(&BackupSystemTable,SystemTable,sizeof(BackupSystemTable));
+
+ /*
+ * Initialize EFI library
+ */
+ //InitializeLib(ImageHandle,&BackupSystemTable);
+
+ /* IA64 compiler is removing version string (unused?) so I use it */
+ //v[0] = 'v';
+
+ /*
+ * Set the disk size
+ */
+ RamDiskSize = GetDiskSize(ImageHandle);
+ BlockSize = 512;
+
+ /* Allocate storage for ramdisk device info on the heap.
+ */
+ RamDiskDev = AllocateZeroPool(sizeof(RAM_DISK_DEV));
+ if(RamDiskDev == NULL)
+ return EFI_OUT_OF_RESOURCES;
+
+ /*
+ * Compute the number of 4KB pages needed by the ramdisk and allocate the memory.
+ */
+ NumPages = RamDiskSize / EFI_PAGE_SIZE;
+ if(NumPages % RamDiskSize)
+ NumPages++;
+
+ Status = gBS->AllocatePages(AllocateAnyPages,EfiBootServicesData,NumPages,&RamDiskDev->Start);
+ if(EFI_ERROR(Status)) {
+ FreePool(RamDiskDev);
+ return Status;
+ }
+
+ /*
+ * Initialize the ramdisk's device info.
+ */
+ (void)gBS->GetNextMonotonicCount(&DiskId);
+ CopyMem(&RamDiskDevicePath.DiskId, &DiskId, sizeof(DiskId));
+
+ RamDiskDev->Signature = PBLOCK_DEVICE_SIGNATURE;
+ RamDiskDev->BlkIo.Revision = EFI_BLOCK_IO_INTERFACE_REVISION;
+ RamDiskDev->BlkIo.Media = &RamDiskDev->Media;
+ RamDiskDev->Media.RemovableMedia = FALSE;
+ RamDiskDev->Media.MediaPresent = TRUE;
+
+ RamDiskDev->Media.LastBlock = RamDiskSize/BlockSize - 1;
+ RamDiskDev->Media.BlockSize = BlockSize;
+ RamDiskDev->Media.LogicalPartition = TRUE;
+ RamDiskDev->Media.ReadOnly = FALSE;
+ RamDiskDev->Media.WriteCaching = TRUE;
+
+ RamDiskDev->BlkIo.ReadBlocks = RamDiskReadBlocks;
+ RamDiskDev->BlkIo.WriteBlocks = RamDiskWriteBlocks;
+ RamDiskDev->BlkIo.FlushBlocks = RamDiskFlushBlocks;
+
+ RamDiskDev->DevicePath = DuplicateDevicePath((EFI_DEVICE_PATH*)&RamDiskDevicePath);
+
+ /*
+ * Build a FAT16 file system on the ramdisk.
+ */
+ FormatRamdisk((VOID*)(UINTN)RamDiskDev->Start,RamDiskSize);
+
+ /*
+ * Install the device.
+ */
+
+ Status = gBS->InstallMultipleProtocolInterfaces(
+ &ImageHandle,
+ &gEfiBlockIoProtocolGuid,
+ &RamDiskDev->BlkIo,
+ &gEfiDevicePathProtocolGuid,
+ RamDiskDev->DevicePath,
+ NULL);
+
+DEBUG((EFI_D_ERROR,"ramdisk:blckio install. Status=%r\n",Status));
+ return Status;
+}
+
+UINT32
+GetDiskSize( EFI_HANDLE ImageHandle )
+{
+ EFI_STATUS Status;
+ EFI_LOADED_IMAGE *Image;
+ UINT32 DiskSize = PcdGet32(PcdRamDiskMaxSize);
+
+ /*
+ * Check load options to see if they want to specify disk size in MBs
+ */
+ Status = gBS->HandleProtocol(ImageHandle, &gEfiLoadedImageProtocolGuid, (void**)&Image);
+ if (!EFI_ERROR(Status)) {
+ if (Image->LoadOptions && Image->LoadOptionsSize) {
+#define MAX_ARG_SIZE 32
+ CHAR16 Size[ MAX_ARG_SIZE ];
+ CHAR16 *CmdLine = Image->LoadOptions;
+ INT32 CmdLen = (INT32)Image->LoadOptionsSize;
+
+ /*
+ * Get past program name
+ */
+ while( CmdLen > 0 && *CmdLine != L' ' ) {
+ CmdLen -= sizeof(CHAR16);
+ CmdLine++;
+ }
+
+ if ( CmdLen > 0 ) {
+ /*
+ * Make sure we're null terminated
+ */
+ CopyMem( Size, CmdLine, MIN(CmdLen, (INT32)sizeof(Size)));
+ Size[MAX_ARG_SIZE - 1] = 0;
+
+ /*
+ * Atoi() will skip any leading white space
+ */
+ DiskSize = (UINT32)StrDecimalToUintn(Size);
+ if (DiskSize == 0)
+ DiskSize = PcdGet32(PcdRamDiskMaxSize);
+ DiskSize = MAX(DiskSize, MIN_DISK_SIZE);
+ DiskSize = MIN(DiskSize, MAX_DISK_SIZE);
+ }
+ }
+ }
+
+ return (DiskSize * 1024 * 1024);
+}
+
+/* Given a block of memory representing a ramdisk, build a pseudo-boot sector
+ * and initialize the drive.
+ *
+ * Assumes the global boot sector structure g_bs has been filled out with the
+ * static information the boot sector requires. Also assumes the ramdisk size
+ * is between 4.1MB and 512MB as appropriate for FAT16 file system.
+ */
+STATIC VOID FormatRamdisk(
+ IN VOID* pStart,
+ IN UINT32 Size)
+{
+ UINT32 TotalSectors,RootDirSectors,FatSz,tmp1,tmp2;
+ UINT8 *Fat1,*Fat2;
+ BOOTSEC g_bs;
+
+ g_bs.BS_jmpBoot[0] = 0xeb;
+ g_bs.BS_jmpBoot[1] = 0x0;
+ g_bs.BS_jmpBoot[2] = 0x90;
+ g_bs.BS_OEMName[0] = 'E';
+ g_bs.BS_OEMName[1] = 'F';
+ g_bs.BS_OEMName[2] = 'I';
+ g_bs.BS_OEMName[3] = 'R';
+ g_bs.BS_OEMName[4] = 'D';
+ g_bs.BS_OEMName[5] = 'I';
+ g_bs.BS_OEMName[6] = 'S';
+ g_bs.BS_OEMName[7] = 'K';
+ g_bs.BPB_BytsPerSec = 512;
+ g_bs.BPB_SecPerClus = 0;
+ g_bs.BPB_RsvdSecCnt = 1;
+ g_bs.BPB_NumFATs = 2;
+ g_bs.BPB_RootEntCnt = 512;
+ g_bs.BPB_TotSec16 = 0;
+ g_bs.BPB_Media = 0xF8;
+ g_bs.BPB_FATSz16 = 0;
+ g_bs.BPB_SecPerTrk = 0;
+ g_bs.BPB_NumHeads = 0;
+ g_bs.BPB_HiddSec = 0;
+ g_bs.BPB_TotSec32 = 0;
+ g_bs.BS_DrvNum = 0;
+ g_bs.BS_Reserved1 = 0;
+ g_bs.BS_BootSig = 0x29;
+ g_bs.BS_VolID = 0;
+ g_bs.BS_VolLab[0] = 'N';
+ g_bs.BS_VolLab[1] = 'O';
+ g_bs.BS_VolLab[2] = ' ';
+ g_bs.BS_VolLab[3] = 'N';
+ g_bs.BS_VolLab[4] = 'A';
+ g_bs.BS_VolLab[5] = 'M';
+ g_bs.BS_VolLab[6] = 'E';
+ g_bs.BS_VolLab[7] = ' ';
+ g_bs.BS_VolLab[8] = ' ';
+ g_bs.BS_FilSysType[0] = 'F';
+ g_bs.BS_FilSysType[1] = 'A';
+ g_bs.BS_FilSysType[2] = 'T';
+ g_bs.BS_FilSysType[3] = '1';
+ g_bs.BS_FilSysType[4] = '6';
+ g_bs.BS_FilSysType[5] = ' ';
+ g_bs.BS_FilSysType[6] = ' ';
+ g_bs.BS_FilSysType[7] = ' ';
+ /* The boot signature needs to be filled out */
+ g_bs.BS_Sig = 0xAA55;
+
+ /* Compute the total sectors and appropriate cluster size */
+ TotalSectors = Size / g_bs.BPB_BytsPerSec;
+ g_bs.BPB_SecPerClus = size2spc(TotalSectors);
+ ASSERT(g_bs.BPB_SecPerClus != 0);
+
+ /* Compute how many root directory sectors are needed */
+ RootDirSectors = (g_bs.BPB_RootEntCnt * 32 + g_bs.BPB_BytsPerSec - 1) / g_bs.BPB_BytsPerSec;
+
+ /* Compute how many sectors are required per FAT */
+ tmp1 = TotalSectors - (g_bs.BPB_RsvdSecCnt + RootDirSectors);
+ tmp2 = 256 * g_bs.BPB_SecPerClus + g_bs.BPB_NumFATs;
+ FatSz = (tmp1 + tmp2 - 1) / tmp2;
+ ASSERT(FatSz <= 0xFFFF);
+
+ /* Store the total sectors and fat size values */
+ if(TotalSectors > 0xFFFF)
+ g_bs.BPB_TotSec32 = TotalSectors;
+ else
+ g_bs.BPB_TotSec16 = (UINT16)TotalSectors;
+
+ g_bs.BPB_FATSz16 = (UINT16)FatSz;
+
+ /* The FAT table and root directory need to be all zeroes.
+ * We'll zero the whole drive.
+ */
+ ZeroMem(pStart,Size);
+
+ /* Write the completed boot sector to the ramdisk */
+ CopyMem(pStart,&g_bs,512);
+
+ /* Compute the starting offsets of the two FATs */
+ Fat1 = (UINT8*)pStart + g_bs.BPB_RsvdSecCnt * 512;
+ Fat2 = (UINT8*)pStart + (UINTN)(g_bs.BPB_RsvdSecCnt + FatSz) * 512;
+
+ /* Initialize FAT1 */
+ Fat1[0] = g_bs.BPB_Media;
+ Fat1[1] = 0xFF;
+ Fat1[2] = 0xFF;
+ Fat1[3] = 0xFF;
+
+ /* Initialize FAT2 */
+ Fat2[0] = g_bs.BPB_Media;
+ Fat2[1] = 0xFF;
+ Fat2[2] = 0xFF;
+ Fat2[3] = 0xFF;
+}
+
+/* Implementation of block I/O read */
+STATIC EFI_STATUS RamDiskReadBlocks(
+ IN EFI_BLOCK_IO *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer)
+{
+ EFI_BLOCK_IO_MEDIA *Media;
+ RAM_DISK_DEV *RamDiskDev;
+ EFI_PHYSICAL_ADDRESS RamDiskLBA;
+
+ Media = This->Media;
+
+ if(BufferSize % Media->BlockSize != 0)
+ return EFI_BAD_BUFFER_SIZE;
+
+ if(LBA > Media->LastBlock)
+ return EFI_DEVICE_ERROR;
+
+ if(LBA + BufferSize / Media->BlockSize - 1 > Media->LastBlock)
+ return EFI_DEVICE_ERROR;
+
+ RamDiskDev = RAM_DISK_FROM_THIS(This);
+ RamDiskLBA = RamDiskDev->Start + MultU64x32(LBA,Media->BlockSize);
+ CopyMem(Buffer,(VOID*)(UINTN)RamDiskLBA,BufferSize);
+
+ return EFI_SUCCESS;
+}
+
+
+/* Implementation of block I/O write */
+STATIC EFI_STATUS RamDiskWriteBlocks(
+ IN EFI_BLOCK_IO *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ IN VOID *Buffer)
+{
+ EFI_BLOCK_IO_MEDIA *Media;
+ RAM_DISK_DEV *RamDiskDev;
+ EFI_PHYSICAL_ADDRESS RamDiskLBA;
+
+ Media = This->Media;
+ if(Media->ReadOnly)
+ return EFI_WRITE_PROTECTED;
+
+ if(BufferSize % Media->BlockSize != 0)
+ return EFI_BAD_BUFFER_SIZE;
+
+ if(LBA > Media->LastBlock)
+ return EFI_DEVICE_ERROR;
+
+ if(LBA + BufferSize / Media->BlockSize - 1 > Media->LastBlock)
+ return EFI_DEVICE_ERROR;
+
+ RamDiskDev = RAM_DISK_FROM_THIS(This);
+ RamDiskLBA = RamDiskDev->Start + MultU64x32(LBA,Media->BlockSize);
+ CopyMem((VOID*)(UINTN)RamDiskLBA,Buffer,BufferSize);
+
+ return EFI_SUCCESS;
+}
+
+/* Implementation of block I/O flush */
+STATIC EFI_STATUS RamDiskFlushBlocks(
+ IN EFI_BLOCK_IO *This)
+{
+ return EFI_SUCCESS;
+}