• Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

Memory_Linux.cpp

Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
00002  * vim:expandtab:autoindent:tabstop=4:shiftwidth=4:filetype=c:cindent:textwidth=0:
00003  *
00004  * Copyright (C) 2005 Dell Inc.
00005  *  by Michael Brown <Michael_E_Brown@dell.com>
00006  * Licensed under the Open Software License version 2.1
00007  *
00008  * Alternatively, you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published
00010  * by the Free Software Foundation; either version 2 of the License,
00011  * or (at your option) any later version.
00012 
00013  * This program is distributed in the hope that it will be useful, but
00014  * WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00016  * See the GNU General Public License for more details.
00017  */
00018 
00019 // compat header should always be first header if including system headers
00020 #define LIBSMBIOS_SOURCE
00021 #include "smbios/compat.h"
00022 
00023 #include <errno.h>
00024 #include <sys/mman.h>   /* mmap */
00025 #include <stdio.h>
00026 #include <unistd.h>     /* getpagesize */
00027 #include <string.h>     /* memcpy etc. */
00028 
00029 #include "MemoryImpl.h"
00030 
00031 // include this last
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 }

Generated on Sun Aug 22 2010 14:38:30 for SMBIOS Library by  doxygen 1.7.1