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