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 #include <string.h>
00027
00028 #include "MemoryImpl.h"
00029
00030
00031 #include "smbios/message.h"
00032
00033 using namespace std;
00034 using namespace factory;
00035
00036 namespace memory
00037 {
00038 struct LinuxData
00039 {
00040 FILE *fd;
00041 void *lastMapping;
00042 unsigned long lastMappedOffset;
00043 unsigned long mappingSize;
00044 int reopenHint;
00045 string filename;
00046 };
00047
00048 static void condOpenFd(struct LinuxData *data)
00049 {
00050 if(!data->fd)
00051 {
00052 data->lastMapping = 0;
00053 data->lastMappedOffset = 0;
00054 data->fd = fopen( data->filename.c_str(), "rb" );
00055 if(!data->fd)
00056 {
00057 AccessErrorImpl accessError;
00058 accessError.setMessageString( _("Unable to open memory. File: %(file)s, OS Error: %(err)s") );
00059 accessError.setParameter( "file", data->filename );
00060 accessError.setParameter( "err", strerror(errno) );
00061 throw accessError;
00062 }
00063 }
00064 }
00065
00066 static void closeFd(struct LinuxData *data)
00067 {
00068 if(data->lastMapping)
00069 {
00070 munmap(data->lastMapping, data->mappingSize);
00071 data->lastMapping = 0;
00072 }
00073 if (data->fd)
00074 {
00075 fclose(data->fd);
00076 data->fd = 0;
00077 }
00078 data->lastMappedOffset = 0;
00079 }
00080
00081 MemoryFactoryImpl::MemoryFactoryImpl()
00082 {
00083 setParameter("memFile", "/dev/mem");
00084 }
00085
00086 MemoryOsSpecific::MemoryOsSpecific( const string filename )
00087 : IMemory()
00088 {
00089 LinuxData *data = new LinuxData();
00090 data->fd = 0;
00091 data->filename = filename;
00092 data->mappingSize = getpagesize() * 16;
00093 data->reopenHint = 1;
00094 condOpenFd(data);
00095 closeFd(data);
00096 osData = static_cast<void *>(data);
00097 }
00098
00099 MemoryOsSpecific::~MemoryOsSpecific()
00100 {
00101 LinuxData *data = static_cast<LinuxData *>(osData);
00102 closeFd(data);
00103 delete data;
00104 osData = 0;
00105 }
00106
00107 int MemoryOsSpecific::incReopenHint()
00108 {
00109 LinuxData *data = static_cast<LinuxData *>(osData);
00110 return ++(data->reopenHint);
00111 }
00112 int MemoryOsSpecific::decReopenHint()
00113 {
00114 LinuxData *data = static_cast<LinuxData *>(osData);
00115 return --(data->reopenHint);
00116 }
00117
00118 void MemoryOsSpecific::fillBuffer( u8 *buffer, u64 offset, unsigned int length) const
00119 {
00120 LinuxData *data = static_cast<LinuxData *>(osData);
00121 unsigned int bytesCopied = 0;
00122
00123 condOpenFd(data);
00124
00125 while( bytesCopied < length )
00126 {
00127 off_t mmoff = offset % data->mappingSize;
00128
00129 if ((offset-mmoff) != data->lastMappedOffset)
00130 {
00131 data->lastMappedOffset = offset-mmoff;
00132 if (data->lastMapping)
00133 munmap(data->lastMapping, data->mappingSize);
00134 data->lastMapping = mmap( 0, data->mappingSize, PROT_READ, MAP_PRIVATE, fileno(data->fd), offset-mmoff);
00135 if ((data->lastMapping) == reinterpret_cast<void *>(-1))
00136 throw AccessErrorImpl(_("mmap failed."));
00137 }
00138
00139 unsigned long toCopy = length - bytesCopied;
00140 if( toCopy + mmoff > (data->mappingSize) )
00141 toCopy = (data->mappingSize) - mmoff;
00142
00143 memcpy(buffer + bytesCopied, (reinterpret_cast<const u8 *>(data->lastMapping) + mmoff), toCopy);
00144 offset += toCopy;
00145 bytesCopied += toCopy;
00146 }
00147
00148 if(data->reopenHint)
00149 closeFd(data);
00150
00151 }
00152
00153 u8 MemoryOsSpecific::getByte( u64 offset ) const
00154 {
00155 u8 value=0;
00156 fillBuffer( &value, offset, 1 );
00157 return value;
00158 }
00159
00160 void MemoryOsSpecific::putByte( u64 offset, u8 value ) const
00161 {
00162 LinuxData *data = static_cast<LinuxData *>(osData);
00163 condOpenFd(data);
00164 int ret = fseek( data->fd, offset, 0 );
00165 if( 0 != ret )
00166 {
00167 OutOfBoundsImpl outOfBounds;
00168 outOfBounds.setMessageString(_("Seek error trying to seek to memory location. OS Error: %(err)s"));
00169 outOfBounds.setParameter("err", strerror(errno) );
00170 closeFd(data);
00171 throw outOfBounds;
00172 }
00173 ret = fwrite( &value, 1, 1, data->fd );
00174 if( 1 != ret )
00175 {
00176 AccessErrorImpl accessError;
00177 accessError.setMessageString(_("Error trying to write memory. OS Error: %(err)s"));
00178 accessError.setParameter("err", strerror(errno) );
00179 closeFd(data);
00180 throw accessError;
00181 }
00182 if(data->reopenHint)
00183 closeFd(data);
00184 }
00185
00186 }