init.c

来自「Next BIOS Source code : Extensible Firmw」· C语言 代码 · 共 818 行 · 第 1/2 页

C
818
字号
/*++

Copyright (c)  1999 - 2003 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.


Module Name:

  init.c
  
Abstract:

  Initialization routines
  
--*/

#include "fat.h"

EFI_STATUS
FatAllocateVolume (
  IN  EFI_HANDLE                Handle,
  IN  EFI_DISK_IO_PROTOCOL      *DiskIo,
  IN  EFI_BLOCK_IO_PROTOCOL     *BlockIo
  );

EFI_STATUS
FatAbandonVolume (
  IN FAT_VOLUME *Vol
  );

EFI_STATUS
FatOpenDevice (
  IN OUT FAT_VOLUME           *Vol
  );

EFI_STATUS
FatInitUnicodeCollationSupport (
  IN  EFI_DRIVER_BINDING_PROTOCOL    *This,
  IN  LC_ISO_639_2                   *LangCode,
  OUT EFI_UNICODE_COLLATION_PROTOCOL **UnicodeCollationInterface
  )
/*++

Routine Description:

  Initializes Unicode Collation support.
    
Arguments:

  LangCode                   - Language Code specified.
  UnicodeCollationInterface  - Unicode Collation protocol interface returned.

Returns:

  EFI_SUCCESS   - Successfully get the Unicode Collation protocol interface by 
                  specified LangCode.
  EFI_NOT_FOUND - Specified Unicode Collation protocol is not found.

--*/ 
{
  EFI_STATUS                      Status;
  LC_ISO_639_2                    *Languages;
  UINTN                           Index, Position, Length;
  UINTN                           NoHandles;
  EFI_HANDLE                      *Handles;
  BOOLEAN                         Found;
  EFI_UNICODE_COLLATION_PROTOCOL  *Uci;
  
  Found = FALSE;
  *UnicodeCollationInterface = NULL;
  
  if (!LangCode) {
    return EFI_NOT_FOUND;
  }
  
  //
  // Locate all Unicode Collation drivers.
  //
  Status = gBS->LocateHandleBuffer (
                      ByProtocol, 
                      &gEfiUnicodeCollationProtocolGuid, 
                      NULL, 
                      &NoHandles, 
                      &Handles
                    );
  
  if (EFI_ERROR(Status) || !NoHandles) {
    return EFI_NOT_FOUND;
  }

  //
  // Check all Unicode Collation drivers for a matching language code.
  //
  for (Index = 0; Index < NoHandles; Index++) {
    //
    // Open Unicode Collation Protocol
    //
    Status = gBS->OpenProtocol (
                  Handles[Index],   
                  &gEfiUnicodeCollationProtocolGuid,  
                  (VOID **)&Uci,
                  This->DriverBindingHandle,     
                  NULL,   
                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
                  );
  
    if (EFI_ERROR(Status)) {
      continue;
    }

    Found = FALSE;
  
    //
    // Check for a matching language code.
    //
    Languages = Uci->SupportedLanguages;
    Length = EfiAsciiStrLen (Languages);
    
    for (Position = 0; Position < Length; Position += LC_ISO_639_2_ENTRY_SIZE) {

      //
      // If this code matches, use this driver
      //
      if (EfiCompareMem (Languages + Position, LangCode, LC_ISO_639_2_ENTRY_SIZE) == 0) {
        Found = TRUE;
        *UnicodeCollationInterface = Uci;
        goto Done;
      }
    }
  }

Done:
  //
  // Cleanup
  //
  if (Handles) {
    gBS->FreePool (Handles);
  }
  
  if (Found) {
    return EFI_SUCCESS;
  }
  
  return EFI_NOT_FOUND;
}


EFI_STATUS
FatAllocateVolume (
  IN  EFI_HANDLE                Handle,
  IN  EFI_DISK_IO_PROTOCOL      *DiskIo,
  IN  EFI_BLOCK_IO_PROTOCOL     *BlockIo
  )
/*++

Routine Description:
  Allocates volume structure, detects FAT file system, installs protocol,
  and initialize cache.
  
Arguments:
  Handle    - the handle of parent device
  DiskIo    - the DiskIo of parent device
  BlockIo   - the BlockIo of parent device
  
Returns:
  Status Code

--*/
{
  EFI_STATUS    Status;
  FAT_VOLUME    *Vol;
  UINTN         Index;
  BOOLEAN       LockedByMe;
  UINTN         CachePageSizeInSector;
  CHAR16        VolumeName[80];

  LockedByMe = FALSE;

  //
  // Allocate a volume structure 
  //
  Vol = EfiLibAllocateZeroPool (sizeof(FAT_VOLUME));
  if (Vol == NULL) {
  return EFI_OUT_OF_RESOURCES;
  }
  
  //
  // Acquire the lock.
  // If caller has already acquired the lock, cannot lock it again.
  //
  if (!FatIsLocked()) {
    LockedByMe = TRUE;
    FatAcquireLock ();
  }

  //
  // Initialize the structure
  //
  Vol->Signature = FAT_VOLUME_SIGNATURE;
  Vol->Handle = Handle;
  Vol->DiskIo = DiskIo;
  Vol->BlkIo = BlockIo;
  Vol->MediaId = BlockIo->Media->MediaId;
  Vol->VolInterface.Revision = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION;
  Vol->VolInterface.OpenVolume = FatOpenVolume;
  InitializeListHead (&Vol->CheckRef);
  Vol->FreeInfoValid = FALSE;

  //
  // Check to see if there's a file system on the volume
  //
  Status = FatOpenDevice (Vol);
  if (EFI_ERROR(Status)) {
    
    //
    // Unlock if locked by myself.
    //
    if (LockedByMe) {
      FatReleaseLock ();
    }

    gBS->FreePool (Vol);
    return Status;
  }

  //
  // Install our protocol interfaces on the device's handle
  //
  Status = gBS->InstallMultipleProtocolInterfaces (
          &Vol->Handle,
          &gEfiSimpleFileSystemProtocolGuid,  &Vol->VolInterface,
          NULL
          );
  if (EFI_ERROR (Status)) {
    
    //
    // Unlock if locked by myself.
    //
    if (LockedByMe) {
      FatReleaseLock ();
    }

    gBS->FreePool (Vol);
    return Status;
  }
  
  //
  // Volume installed
  //
  DEBUG((EFI_D_INIT, "%HInstalled Fat filesystem on %x%N\n", Handle));
  Vol->Valid = TRUE;
  
  //
  // Initialize cache
  //

  //
  // Determine the proper cache page size
  //
  CachePageSizeInSector = Vol->SectorsPerCluster;

  while ((Vol->Sectors % CachePageSizeInSector != 0) ||
         (CachePageSizeInSector * Vol->SectorSize > FAT_CACHE_PAGE_MAX_SIZE)) {
    CachePageSizeInSector /= 2;
  }
  
  Vol->CachePageSize = CachePageSizeInSector * Vol->SectorSize;

  for (Index = 0; Index < FAT_CACHE_SIZE; Index++) {
    Vol->Cache[Index].Valid = FALSE;
    Vol->Cache[Index].Dirty = FALSE;
    Status = gBS->AllocatePool (
          EfiBootServicesData,
          Vol->CachePageSize,
          &Vol->Cache[Index].Data
          );
    if (EFI_ERROR (Status)) {
    
      //
      // Roll back allocated memories
      //
      if (Index > 0) {
        for (;(INTN)Index >= 0; Index --) {
          gBS->FreePool (&Vol->Cache[Index].Data);
        }
      }
      
      gBS->UninstallMultipleProtocolInterfaces (
          Vol->Handle,
          &gEfiSimpleFileSystemProtocolGuid,  &Vol->VolInterface,
          NULL
          );
      
      //
      // Unlock if locked by myself.
      //
      if (LockedByMe) {
        FatReleaseLock ();
      }
      
      gBS->FreePool (Vol);
      return Status;
    }
  }
  
  //
  // Unlock if locked by myself.
  //
  if (LockedByMe) {
    FatReleaseLock ();
  }

  //
  // Build name for this FAT volume
  //
  Vol->ControllerNameTable = NULL;
  EfiStrCpy (VolumeName, L"FAT File System [FAT");
  switch (Vol->FatType) {
  case FAT12 :
    EfiStrCat (VolumeName, L"12");
    break;
  case FAT16 :
    EfiStrCat (VolumeName, L"16");
    break;
  case FAT32 :
    EfiStrCat (VolumeName, L"32");
    break;
  default :
    EfiStrCat (VolumeName, L"xx");
    break;
  }
  EfiStrCat (VolumeName, L"] ");
  if (Vol->VolSize < 10000000) {
    EfiValueToString (&(VolumeName[EfiStrLen(VolumeName)]),
                       DriverLibRShiftU64(Vol->VolSize,10),
                       0,
                       0
                       );
    EfiStrCat (VolumeName, L" KB");
  } else if (Vol->VolSize < 10000000000) {
    EfiValueToString (&(VolumeName[EfiStrLen(VolumeName)]),
                       DriverLibRShiftU64(Vol->VolSize,20),
                       0,
                       0
                       );
    EfiStrCat (VolumeName, L" MB");
  } else {
    EfiValueToString (&(VolumeName[EfiStrLen(VolumeName)]),
                       DriverLibRShiftU64(Vol->VolSize,30),
                       0,
                       0
                       );
    EfiStrCat (VolumeName, L" GB");
  }

  EfiLibAddUnicodeString (
    "eng", 
    gFatComponentName.SupportedLanguages, 
    &Vol->ControllerNameTable, 
    VolumeName
    );

  return Status;
}


EFI_STATUS
FatAbandonVolume (
  IN FAT_VOLUME *Vol
  )
/*++
  
Routine Description:
  Called by FatDriverBindingStop(), Abandon the volume.
  
Arguments:
  Vol     - the volume to be abandoned
  
Returns:
  Status code.
  
--*/
{
  EFI_STATUS  Status;
  BOOLEAN     LockedByMe;
  
  //
  // Uninstall the protocol interface.
  //
  if (Vol->Handle) {
    Status = gBS->UninstallMultipleProtocolInterfaces (
                    Vol->Handle,
                    &gEfiSimpleFileSystemProtocolGuid,    &Vol->VolInterface,
                    NULL
                    );
    if (EFI_ERROR (Status)) {
      return Status;
    }
  }

  LockedByMe = FALSE;
  
  //

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?