You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
296 lines
7.7 KiB
296 lines
7.7 KiB
// This file was extracted from the TCG Published |
|
// Trusted Platform Module Library |
|
// Part 4: Supporting Routines |
|
// Family "2.0" |
|
// Level 00 Revision 01.16 |
|
// October 30, 2014 |
|
|
|
#include <memory.h> |
|
#include <stdio.h> |
|
#include <string.h> |
|
|
|
#include "PlatformData.h" |
|
#include "TpmError.h" |
|
#include "assert.h" |
|
|
|
#ifndef EMBEDDED_MODE |
|
#define FILE_BACKED_NV |
|
#endif |
|
|
|
#if defined FILE_BACKED_NV |
|
static FILE* s_NVFile; |
|
#endif |
|
static unsigned char s_NV[NV_MEMORY_SIZE]; |
|
static BOOL s_NvIsAvailable; |
|
static BOOL s_NV_unrecoverable; |
|
static BOOL s_NV_recoverable; |
|
// |
|
// |
|
// Functions |
|
// |
|
// _plat__NvErrors() |
|
// |
|
// This function is used by the simulator to set the error flags in the NV subsystem to simulate an error in the |
|
// NV loading process |
|
// |
|
LIB_EXPORT void |
|
_plat__NvErrors( |
|
BOOL recoverable, |
|
BOOL unrecoverable |
|
) |
|
{ |
|
s_NV_unrecoverable = unrecoverable; |
|
s_NV_recoverable = recoverable; |
|
} |
|
// |
|
// |
|
// _plat__NVEnable() |
|
// |
|
// Enable NV memory. |
|
// This version just pulls in data from a file. In a real TPM, with NV on chip, this function would verify the |
|
// integrity of the saved context. If the NV memory was not on chip but was in something like RPMB, the NV |
|
// state would be read in, decrypted and integrity checked. |
|
// The recovery from an integrity failure depends on where the error occurred. It it was in the state that is |
|
// discarded by TPM Reset, then the error is recoverable if the TPM is reset. Otherwise, the TPM must go |
|
// into failure mode. |
|
// |
|
// Return Value Meaning |
|
// |
|
// 0 if success |
|
// >0 if receive recoverable error |
|
// <0 if unrecoverable error |
|
// |
|
LIB_EXPORT int |
|
_plat__NVEnable( |
|
void *platParameter // IN: platform specific parameter |
|
) |
|
{ |
|
// Start assuming everything is OK |
|
s_NV_unrecoverable = FALSE; |
|
s_NV_recoverable = FALSE; |
|
#ifdef FILE_BACKED_NV |
|
if(s_NVFile != NULL) return 0; |
|
// Try to open an exist NVChip file for read/write |
|
s_NVFile = fopen("NVChip", "r+b"); |
|
if(NULL != s_NVFile) |
|
{ |
|
// See if the NVChip file is empty |
|
fseek(s_NVFile, 0, SEEK_END); |
|
if(0 == ftell(s_NVFile)) |
|
s_NVFile = NULL; |
|
} |
|
if(s_NVFile == NULL) |
|
{ |
|
// Initialize all the byte in the new file to 0 |
|
memset(s_NV, 0, NV_MEMORY_SIZE); |
|
// If NVChip file does not exist, try to create it for read/write |
|
s_NVFile = fopen("NVChip", "w+b"); |
|
// Start initialize at the end of new file |
|
fseek(s_NVFile, 0, SEEK_END); |
|
// Write 0s to NVChip file |
|
fwrite(s_NV, 1, NV_MEMORY_SIZE, s_NVFile); |
|
} |
|
else |
|
{ |
|
// If NVChip file exist, assume the size is correct |
|
fseek(s_NVFile, 0, SEEK_END); |
|
assert(ftell(s_NVFile) == NV_MEMORY_SIZE); |
|
// read NV file data to memory |
|
fseek(s_NVFile, 0, SEEK_SET); |
|
assert(1 == fread(s_NV, NV_MEMORY_SIZE, 1, s_NVFile)); |
|
} |
|
#endif |
|
// NV contents have been read and the error checks have been performed. For |
|
// simulation purposes, use the signaling interface to indicate if an error is |
|
// to be simulated and the type of the error. |
|
if(s_NV_unrecoverable) |
|
return -1; |
|
return s_NV_recoverable; |
|
} |
|
// |
|
// |
|
// _plat__NVDisable() |
|
// |
|
// Disable NV memory |
|
// |
|
LIB_EXPORT void |
|
_plat__NVDisable( |
|
void |
|
) |
|
{ |
|
#ifdef FILE_BACKED_NV |
|
assert(s_NVFile != NULL); |
|
// Close NV file |
|
fclose(s_NVFile); |
|
// Set file handle to NULL |
|
// |
|
s_NVFile = NULL; |
|
#endif |
|
return; |
|
} |
|
// |
|
// |
|
// _plat__IsNvAvailable() |
|
// |
|
// Check if NV is available |
|
// |
|
// Return Value Meaning |
|
// |
|
// 0 NV is available |
|
// 1 NV is not available due to write failure |
|
// 2 NV is not available due to rate limit |
|
// |
|
LIB_EXPORT int |
|
_plat__IsNvAvailable( |
|
void |
|
) |
|
{ |
|
// NV is not available if the TPM is in failure mode |
|
if(!s_NvIsAvailable) |
|
return 1; |
|
#ifdef FILE_BACKED_NV |
|
if(s_NVFile == NULL) |
|
return 1; |
|
#endif |
|
return 0; |
|
} |
|
// |
|
// |
|
// _plat__NvMemoryRead() |
|
// |
|
// Function: Read a chunk of NV memory |
|
// |
|
LIB_EXPORT void |
|
_plat__NvMemoryRead( |
|
unsigned int startOffset, // IN: read start |
|
unsigned int size, // IN: size of bytes to read |
|
void *data // OUT: data buffer |
|
) |
|
{ |
|
assert(startOffset + size <= NV_MEMORY_SIZE); |
|
// Copy data from RAM |
|
memcpy(data, &s_NV[startOffset], size); |
|
return; |
|
} |
|
// |
|
// |
|
// _plat__NvIsDifferent() |
|
// |
|
// This function checks to see if the NV is different from the test value. This is so that NV will not be written if |
|
// it has not changed. |
|
// |
|
// |
|
// |
|
// |
|
// Return Value Meaning |
|
// |
|
// TRUE the NV location is different from the test value |
|
// FALSE the NV location is the same as the test value |
|
// |
|
LIB_EXPORT BOOL |
|
_plat__NvIsDifferent( |
|
unsigned int startOffset, // IN: read start |
|
unsigned int size, // IN: size of bytes to read |
|
void *data // IN: data buffer |
|
) |
|
{ |
|
return (memcmp(&s_NV[startOffset], data, size) != 0); |
|
} |
|
// |
|
// |
|
// _plat__NvMemoryWrite() |
|
// |
|
// This function is used to update NV memory. The write is to a memory copy of NV. At the end of the |
|
// current command, any changes are written to the actual NV memory. |
|
// |
|
LIB_EXPORT void |
|
_plat__NvMemoryWrite( |
|
unsigned int startOffset, // IN: write start |
|
unsigned int size, // IN: size of bytes to write |
|
void *data // OUT: data buffer |
|
) |
|
{ |
|
assert(startOffset + size <= NV_MEMORY_SIZE); |
|
// Copy the data to the NV image |
|
memcpy(&s_NV[startOffset], data, size); |
|
} |
|
// |
|
// |
|
// _plat__NvMemoryMove() |
|
// |
|
// Function: Move a chunk of NV memory from source to destination This function should ensure that if |
|
// there overlap, the original data is copied before it is written |
|
// |
|
LIB_EXPORT void |
|
_plat__NvMemoryMove( |
|
unsigned int sourceOffset, // IN: source offset |
|
unsigned int destOffset, // IN: destination offset |
|
unsigned int size // IN: size of data being moved |
|
) |
|
{ |
|
assert(sourceOffset + size <= NV_MEMORY_SIZE); |
|
assert(destOffset + size <= NV_MEMORY_SIZE); |
|
// Move data in RAM |
|
memmove(&s_NV[destOffset], &s_NV[sourceOffset], size); |
|
return; |
|
} |
|
// |
|
// |
|
// _plat__NvCommit() |
|
// |
|
// Update NV chip |
|
// |
|
// |
|
// |
|
// Return Value Meaning |
|
// |
|
// 0 NV write success |
|
// non-0 NV write fail |
|
// |
|
LIB_EXPORT int |
|
_plat__NvCommit( |
|
void |
|
) |
|
{ |
|
#ifdef FILE_BACKED_NV |
|
// If NV file is not available, return failure |
|
if(s_NVFile == NULL) |
|
return 1; |
|
// Write RAM data to NV |
|
fseek(s_NVFile, 0, SEEK_SET); |
|
fwrite(s_NV, 1, NV_MEMORY_SIZE, s_NVFile); |
|
return 0; |
|
#else |
|
return 0; |
|
#endif |
|
} |
|
// |
|
// |
|
// _plat__SetNvAvail() |
|
// |
|
// Set the current NV state to available. This function is for testing purpose only. It is not part of the |
|
// platform NV logic |
|
// |
|
LIB_EXPORT void |
|
_plat__SetNvAvail( |
|
void |
|
) |
|
{ |
|
s_NvIsAvailable = TRUE; |
|
return; |
|
} |
|
// |
|
// |
|
// _plat__ClearNvAvail() |
|
// |
|
// Set the current NV state to unavailable. This function is for testing purpose only. It is not part of the |
|
// platform NV logic |
|
// |
|
LIB_EXPORT void |
|
_plat__ClearNvAvail( |
|
void |
|
) |
|
{ |
|
s_NvIsAvailable = FALSE; |
|
return; |
|
}
|
|
|