00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #define LIBSMBIOS_SOURCE
00021 #include "smbios/compat.h"
00022
00023 #include <errno.h>
00024 #include <sys/mman.h>
00025 #include <unistd.h>
00026
00027 #include "MemoryImpl.h"
00028
00029
00030 #include "smbios/message.h"
00031
00032 using namespace std;
00033 using namespace factory;
00034
00035 namespace memory
00036 {
00037
00038 struct LinuxData
00039 {
00040 FILE *fd;
00041 void *lastMapping;
00042 unsigned long lastMappedOffset;
00043 unsigned long mappingSize;
00044 };
00045
00046 MemoryFactoryImpl::MemoryFactoryImpl()
00047 {
00048 setParameter("memFile", "/dev/mem");
00049 }
00050
00051 MemoryOsSpecific::MemoryOsSpecific( const string filename )
00052 : IMemory()
00053 {
00054 LinuxData *data = new LinuxData();
00055 data->lastMapping = 0;
00056 data->lastMappedOffset = 0;
00057 data->mappingSize = getpagesize() * 16;
00058 data->fd = fopen( filename.c_str(), "rb" );
00059 if(!data->fd)
00060 {
00061 AccessErrorImpl accessError;
00062 accessError.setMessageString( _("Unable to open memory. File: %(file)s, OS Error: %(err)s") );
00063 accessError.setParameter( "file", filename );
00064 accessError.setParameter( "err", strerror(errno) );
00065 throw accessError;
00066 }
00067 osData = static_cast<void *>(data);
00068 }
00069
00070 MemoryOsSpecific::~MemoryOsSpecific()
00071 {
00072 LinuxData *data = static_cast<LinuxData *>(osData);
00073 if(data->lastMapping)
00074 munmap(data->lastMapping, data->mappingSize);
00075 fclose(data->fd);
00076 delete data;
00077 osData = 0;
00078 }
00079
00080 void MemoryOsSpecific::fillBuffer( u8 *buffer, u64 offset, unsigned int length) const
00081 {
00082 LinuxData *data = static_cast<LinuxData *>(osData);
00083 unsigned int bytesCopied = 0;
00084
00085 while( bytesCopied < length )
00086 {
00087 off_t mmoff = offset % data->mappingSize;
00088
00089 if ((offset-mmoff) != data->lastMappedOffset)
00090 {
00091 data->lastMappedOffset = offset-mmoff;
00092 if (data->lastMapping)
00093 munmap(data->lastMapping, data->mappingSize);
00094 data->lastMapping = mmap( 0, data->mappingSize, PROT_READ, MAP_PRIVATE, fileno(data->fd), offset-mmoff);
00095 if ((data->lastMapping) == reinterpret_cast<void *>(-1))
00096 throw AccessErrorImpl(_("mmap failed."));
00097 }
00098
00099 unsigned long toCopy = length - bytesCopied;
00100 if( toCopy + mmoff > (data->mappingSize) )
00101 toCopy = (data->mappingSize) - mmoff;
00102
00103 memcpy(buffer + bytesCopied, (reinterpret_cast<const u8 *>(data->lastMapping) + mmoff), toCopy);
00104 offset += toCopy;
00105 bytesCopied += toCopy;
00106 }
00107 }
00108
00109 u8 MemoryOsSpecific::getByte( u64 offset ) const
00110 {
00111 u8 value=0;
00112 fillBuffer( &value, offset, 1 );
00113 return value;
00114 }
00115
00116 void MemoryOsSpecific::putByte( u64 offset, u8 value ) const
00117 {
00118 LinuxData *data = static_cast<LinuxData *>(osData);
00119 int ret = fseek( data->fd, offset, 0 );
00120 if( 0 != ret )
00121 {
00122 OutOfBoundsImpl outOfBounds;
00123 outOfBounds.setMessageString(_("Seek error trying to seek to memory location. OS Error: %(err)s"));
00124 outOfBounds.setParameter("err", strerror(errno) );
00125 throw outOfBounds;
00126 }
00127 ret = fwrite( &value, 1, 1, data->fd );
00128 if( 1 != ret )
00129 {
00130 AccessErrorImpl accessError;
00131 accessError.setMessageString(_("Error trying to write memory. OS Error: %(err)s"));
00132 accessError.setParameter("err", strerror(errno) );
00133 throw accessError;
00134 }
00135 }
00136
00137 }