www.pudn.com > efs.rar > fs_hotplug_sd_cprm.c


/***********************************************************************
 * fs_hotplug_sd_cprm.c
 *
 * Support for CPRM partition on SD Cards
 * Copyright (C) 2006 QUALCOMM, Inc.
 *
 * All Secure Digital media cards contain a protected partition that
 * is accessible only through the use of CPRM.  This partition appears
 * as a unique hotplug device.
 *
 ***********************************************************************/
/*===========================================================================

                        EDIT HISTORY FOR MODULE

  This section contains comments describing changes made to the module.
  Notice that changes are listed in reverse chronological order.

  $Header: //depot/asic/MSMSHARED/services/efs/MSM_EFS.01.02/fs_hotplug_sd_cprm.c#2 $ $DateTime: 2006/11/13 23:27:09 $ $Author: davidb $

when         who   what, where, why
----------   ---   ---------------------------------------------------------
2006-11-13   s h   Be careful not to include absent CPRM header files.
2006-11-12   s h   Cleanup
2006-09-28   sep   Created.

===========================================================================*/

#include "fs_hotplug.h"
#include "fs_hotplug_i.h"

#ifdef FS_HOTPLUG_SD_CPRM

#include "fs_hotplug_sd_cprm.h"
#include "fs_hotplug_sd_lock.h"
#include "sdcc_cprm.h"
#include "CprmInterface.h"
#include "CprmProtectedFileSystem.h"

/* All blocks are 512 bytes, always */
#define SDCC_PROTECTED_BLOCK_SIZE 512

/* Maximum number of blocks to read or write in a single transaction.
   Because the data is being passed over RPC, we need a limit on how
   many blocks are passed in one call. */
#define MAX_READ_BLOCKS  1
#define MAX_WRITE_BLOCKS 1

typedef enum
{
  HOTPLUG_SD_CPRM_MODE_READ_ANY_MKB  = 0,
  HOTPLUG_SD_CPRM_MODE_READ_SAME_MKB = 1
} HOTPLUG_SD_CPRM_MODE;

/* These macros lock and unlock the SD card in use.  Note that they
 * make some assumptions about a local hdev variable being present. */
#define LOCK     hotplug_sd_lock(hdev)
#define UNLOCK   hotplug_sd_unlock(hdev)

/*======================================================================
 * FUNCTION     hotplug_sd_cprm_open_device
 *
 * DESCRIPTION  Open the SD-card protected area.  Do nothing if it
 *    is already open.
 *
 * DEPENDENCIES     None
 *
 * PARAMETERS       hdev - Hotplug device object
 *
 * RETURN VALUE     0  - Successful, or device was already open
 *                  -1 - Failed
 *
 * SIDE EFFECTS     Device is opened, and reads and writes will now work
 *
 *======================================================================*/
int
hotplug_sd_cprm_open_device (struct hotplug_device *hdev)
{
  if (! hdev->sd_is_open)
  {
    /* The drive is not open.  Attempt to open it. */
    LOCK;

    /* Check if there is an SD card in the drive */
    if (sdcc_cprm_does_sd_card_exist (hdev->driveno))
    {
      /* Attempt to open this card */
      hdev->sd_is_open =
        (CprmInterfaceIsEnabled (hdev->driveno) ==
         CPRMINTERFACE_SUCCESS) ? 1 : 0;
    }

    UNLOCK;
  }

  return hdev->sd_is_open ? 0 : -1;
}

/*======================================================================
 * FUNCTION     hotplug_sd_cprm_close_device
 *
 * DESCRIPTION  Close the SD-card protected area.  Do nothing if it
 *    is already closed.
 *
 * DEPENDENCIES     None
 *
 * PARAMETERS       hdev - Hotplug device object
 *
 * RETURN VALUE     0  - Successful, or device was already closed
 *                  -1 - Failed
 *
 * SIDE EFFECTS     Device is closed, and reads or writes to it will no
 *                  longer work
 *
 *======================================================================*/
int
hotplug_sd_cprm_close_device (struct hotplug_device *hdev)
{
  /* Do nothing, just close */
  hdev->sd_is_open = 0;

  return 0;
}

/*======================================================================
 * FUNCTION     hotplug_sd_cprm_is_present
 *
 * DESCRIPTION  This will return that the protected area of the SD-card
 *  is present only if it has been successfully enabled for CPRM, at
 *  which point, CprmProtectedFileSystemIsEnabled will return TRUE.
 *
 * DEPENDENCIES     None
 *
 * PARAMETERS       hdev - Hotplug device object
 *
 * RETURN VALUE     1 if the SD card exists
 *
 * SIDE EFFECTS     None
 *
 *======================================================================*/
int
hotplug_sd_cprm_is_present (struct hotplug_device *hdev)
{
  int cprm_enabled = CprmProtectedFileSystemIsEnabled (hdev->driveno);

  /* If CPRM is enabled, also make sure that there is an SD card in the slot
     before reporting that the SD card is present. */
  if (cprm_enabled && !sdcc_cprm_does_sd_card_exist (hdev->driveno))
  {
    /* If there was no SD card, disable CPRM so we don't keep checking */
    CprmProtectedFileSystemDisable (hdev->driveno);
    cprm_enabled = 0;
  }

  /* If the card is present, and is not open, attempt to open it now.
     HFAT will make read calls to the card without calling open otherwise */
  if (cprm_enabled && !hdev->sd_is_open)
  {
    if (hotplug_sd_cprm_open_device (hdev) != 0)
    {
      /* Something failed in the open call. */
      cprm_enabled = 0;
    }
  }

  return cprm_enabled ? 1 : 0;
}

/*======================================================================
 * FUNCTION     hotplug_sd_cprm_read
 *
 * DESCRIPTION  Read some data from the protected area of the SD-card
 *
 * DEPENDENCIES     The device must have been opened with hotplug_sd_cprm_open
 *
 * PARAMETERS       hdev - Hotplug device object
 *
 *                  sector_number - Number of the block to read.  The
 *                     first block number is 0.
 *
 *                  p_buffer - Buffer to read the data into
 *
 *                  sector_count - Number of blocks to read.
 *
 * RETURN VALUE     0  - Successful
 *                  -1 - Failed
 *
 * SIDE EFFECTS     p_buffer receives the data read from the SD card
 *
 *======================================================================*/
int
hotplug_sd_cprm_read (struct hotplug_device *hdev,
                      uint32 sector_number,
                      uint8 * p_buffer, uint16 sector_count)
{
  int result = -1;
  uint32 block_offset = 0;

  if (hdev->sd_is_open)
  {
    while (sector_count)
    {
      uint32 blocks_to_read = sector_count;

      /* Since this is going over RPC, we don't want to transfer a lot
         of blocks at once.  So limit it to MAX_BLOCKS_TO_WRITE per
         call. */
      if (blocks_to_read > MAX_READ_BLOCKS)
        blocks_to_read = MAX_READ_BLOCKS;

      LOCK;
      // Address apparantly requires a block number
      result = CprmInterfaceProtectedRead
        (hdev->driveno, // drive number
         sector_number + block_offset, // address
         p_buffer + block_offset * SDCC_PROTECTED_BLOCK_SIZE, // p_data
         blocks_to_read) ? 0 : -1;    // blockCount
      UNLOCK;

      /* Exit early if any read failed */
      if (result == -1)
        break;

      sector_count -= blocks_to_read;
      block_offset += blocks_to_read;
    }

  }

  return result;
}

/*======================================================================
 * FUNCTION     hotplug_sd_cprm_write_with_mode
 *
 * DESCRIPTION  Write some data from the protected area of the SD-card
 *    This function allows specifying whether to allow reading what
 *    was written with any MKB that can get to the protected area,
 *    or only allowing the same MKB used to write it to read the data
 *    that is being written.
 *
 * DEPENDENCIES     hotplug_sd_cprm_open should have been called already
 *
 * PARAMETERS       hdev - Hotplug device object
 *
 *                  sector_number - Number of the block to write.  The
 *                     first block number is 0.
 *
 *                  p_buffer - Buffer containing the data to write
 *
 *                  sector_count - Number of blocks to write.
 *
 * RETURN VALUE     0  - Successful
 *                  -1 - Failed
 *
 * SIDE EFFECTS     Data is written to the disk
 *
 *======================================================================*/
int
hotplug_sd_cprm_write_with_mode (struct hotplug_device *hdev,
                                 uint32 sector_number,
                                 uint8 * p_buffer,
                                 uint16 sectors_to_write,
                                 HOTPLUG_SD_CPRM_MODE mode)
{
  int result = -1;
  uint32 block_offset = 0;

  if (hdev->sd_is_open)
  {
    while (sectors_to_write)
    {
      uint32 blocks_to_write = sectors_to_write;

      /* Since this is going over RPC, we don't want to transfer a lot
         of blocks at once.  So limit it to MAX_BLOCKS_TO_WRITE per
         call. */
      if (blocks_to_write > MAX_WRITE_BLOCKS)
        blocks_to_write = MAX_WRITE_BLOCKS;

      LOCK;
      result = CprmInterfaceProtectedWrite
        (hdev->driveno,         //drive number
         sector_number + block_offset, //address
         p_buffer + block_offset * SDCC_PROTECTED_BLOCK_SIZE, //p_data
         blocks_to_write,       //blockCount
         mode) ? 0 : -1;        //mode
      UNLOCK;

      /*Exit early if any write failed */
      if (result == -1)
        break;

      sectors_to_write -= blocks_to_write;
      block_offset += blocks_to_write;
    }
  }

  return result;
}


/*======================================================================
 * FUNCTION     hotplug_sd_cprm_write
 *
 * DESCRIPTION  Write some data from the protected area of the SD-card
 *   This defaults to allowing any MKB to read the data that was written.
 *   This is the correct setting for file system data or directory data,
 *   but writes of data to files should use hotplug_sd_cprm_write_with_mode
 *   and specify READ_SAME_MKB as the mode.
 *
 * DEPENDENCIES     hotplug_sd_cprm_open should have been called already
 *
 * PARAMETERS       hdev - Hotplug device object
 *
 *                  sector_number - Number of the block to write.  The
 *                     first block number is 0.
 *
 *                  p_buffer - Buffer containing the data to write
 *
 *                  sector_count - Number of blocks to write.
 *
 * RETURN VALUE     0  - Successful
 *                  -1 - Failed
 *
 * SIDE EFFECTS     Data is written to the disk
 *
 *======================================================================*/
int
hotplug_sd_cprm_write (struct hotplug_device *hdev,
                       uint32 sector_number,
                       uint8 * p_buffer, uint16 sectors_to_write)
{
  // By default, do writes that allow read back with any MKB
  return hotplug_sd_cprm_write_with_mode (hdev,
                                          sector_number,
                                          p_buffer,
                                          sectors_to_write,
                                          HOTPLUG_SD_CPRM_MODE_READ_ANY_MKB);
}

/*======================================================================
 * FUNCTION     hotplug_sd_cprm_user_write
 *
 * DESCRIPTION  Write some data from the protected area of the SD-card
 *              This function writes data that can only be read with same MKB
 *
 * DEPENDENCIES     hotplug_sd_cprm_open should have been called already
 *
 * PARAMETERS       hdev - Hotplug device object
 *
 *                  sector_number - Number of the block to write.  The
 *                     first block number is 0.
 *
 *                  p_buffer - Buffer containing the data to write
 *
 *                  sector_count - Number of blocks to write.
 *
 * RETURN VALUE     0  - Successful
 *                  -1 - Failed
 *
 * SIDE EFFECTS     Data is written to the disk
 *
 *======================================================================*/
int
hotplug_sd_cprm_user_write (struct hotplug_device *hdev,
                            uint32 sector_number,
                            uint8 * p_buffer, uint16 sectors_to_write)
{
  // Do writes that allow read back with same MKB
  return hotplug_sd_cprm_write_with_mode (hdev,
                                          sector_number,
                                          p_buffer,
                                          sectors_to_write,
                                          HOTPLUG_SD_CPRM_MODE_READ_SAME_MKB);
}

/*======================================================================
 * FUNCTION     hotplug_sd_cprm_get_size
 *
 * DESCRIPTION  Get the size of the SD-card's protected area.  The size
 *   is returned in the parameters p_blocks and p_bytes_per_block
 *
 * PARAMETERS       hdev - Hotplug device object
 *
 *                  p_blocks - Gets the number of blocks in the protected area
 *
 *                  p_bytes_per_block - Gets the block size in bytes
 *
 * RETURN VALUE     0  - Successful
 *                  -1 - Failed
 *
 *                  Fails if there is a problem reading the protected area
 *                  size, or if the size is not a multiple of the block size.
 *
 * SIDE EFFECTS     p_blocks and p_bytes_per_block recieve the size information
 *
 *======================================================================*/
int
hotplug_sd_cprm_get_size (struct hotplug_device *hdev,
                          uint32 * p_blocks, uint16 * p_bytes_per_block)
{
  int result;
  uint32 protected_area_size;   //in bytes

  /* Fail if either pointer is NULL */
  if (!p_blocks || !p_bytes_per_block)
    return -1;

  /* Fail if the SD card does not exist */
  if (!sdcc_cprm_does_sd_card_exist (hdev->driveno))
    return -1;

  /* Get the size of the protected area */
  LOCK;
  result = sdcc_cprm_get_protected_area_size (hdev->driveno,
                                              &protected_area_size);
  UNLOCK;

  /* Check that the result is valid and divisible by the block size */
  if (!result || ((protected_area_size % SDCC_PROTECTED_BLOCK_SIZE) != 0))
    return -1;

  /* Protected area blocks are always 512 bytes */
  *p_bytes_per_block = SDCC_PROTECTED_BLOCK_SIZE;

  /* The size was returned in bytes */
  *p_blocks = protected_area_size / SDCC_PROTECTED_BLOCK_SIZE;

  /* Successful */
  return 0;
}

/*======================================================================
 * FUNCTION     hotplug_sd_cprm_format
 *
 * DESCRIPTION  This callback checks rather or not it is ok to format
 *   the device.  It does not actually format it.  We will always
 *   return failure since we do not want the user to be able to
 *   format the device through this hotplug.
 *
 * PARAMETERS       hdev - Hotplug device object
 *
 * RETURN VALUE     0  - Ok to format
 *                  -1 - Not Ok to format
 *
 *======================================================================*/
int
hotplug_sd_cprm_format (struct hotplug_device *hdev)
{
  (void) hdev;
  /* Do not allow formatting the protected area of the SD card */
  return -1;
}

int
hotplug_sd_cprm_reset (struct hotplug_device *hdev)
{
  /* Ensure that the lock is initialized */
  hotplug_sd_lock_init (hdev);
  return 0;
}


/*======================================================================
  This table contains the functions we expose to the
  file system.
 *======================================================================*/

struct hotplug_dev_funcs hotplug_sd_cprm_functions = {
  hotplug_fat_mount,
  hotplug_sd_cprm_open_device,
  hotplug_sd_cprm_close_device,
  hotplug_sd_cprm_read,
  hotplug_sd_cprm_write,
  hotplug_sd_cprm_user_write,
  hotplug_no_erase,
  hotplug_sd_cprm_get_size,
  hotplug_sd_cprm_is_present,
  hotplug_sd_cprm_format,
  hotplug_sd_cprm_reset,        /* Reset */
};
#else
extern int __dont_complain_about_empty_file;
#endif