1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
|
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim:expandtab:autoindent:tabstop=4:shiftwidth=4:filetype=c:cindent:textwidth=0:
*
* Copyright (C) 2005 Dell Inc.
* by Michael Brown <Michael_E_Brown@dell.com>
* Licensed under the Open Software License version 2.1
*
* Alternatively, you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License,
* or (at your option) any later version.
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*/
// compat header should always be first header if including system headers
#define LIBSMBIOS_SOURCE
#include "smbios/compat.h"
#include <errno.h>
#include <string.h>
#include "CmosRWImpl.h"
using namespace std;
namespace cmos
{
//
// NON-MEMBER FUNCTIONS
//
void readByteArray ( const ICmosRW &cmos, u32 indexPort, u32 dataPort, u32 offset, u8 * target, u32 count)
{
for (u32 i = 0; i < count; ++i)
{
target[i] = cmos.readByte (indexPort, dataPort, offset + i);
}
}
void writeByteArray ( const ICmosRW &cmos, u32 indexPort, u32 dataPort, u32 offset, const u8 * source, u32 count)
{
const Suppressable *s = dynamic_cast<const Suppressable *>(&cmos);
if(s)
s->suppressNotification();
for (u32 i = 0; i < count; ++i)
{
cmos.writeByte (indexPort, dataPort, offset + i, source[i]);
}
if(s)
s->resumeNotification();
}
//
// Suppressable
//
// This class is used to supress ->notify() calls inside an Observable
// class. This lets us do many operations that may cause spurious
// notifications. This would also probably let us do some simple
// transaction-like operations.
//
Suppressable::Suppressable()
: suppressNotify(false)
{}
Suppressable::~Suppressable()
{}
void Suppressable::suppressNotification(bool sup) const
{
suppressNotify = sup;
}
void Suppressable::resumeNotification(bool doNotify) const
{
const observer::IObservable *o = dynamic_cast<const observer::IObservable *>(this);
if(o && doNotify)
o->notify();
suppressNotify = false;
}
bool Suppressable::isNotifySuppressed() const
{
return suppressNotify;
}
//
// ICmosRW functions
//
ICmosRW::ICmosRW()
{}
ICmosRW::~ICmosRW()
{}
//
// CmosRWFile functions
//
// REGULAR CONSTRUCTOR
CmosRWFile::CmosRWFile ( const string &File )
:ICmosRW(), Suppressable(), fileName (File)
{}
// DESTRUCTOR
CmosRWFile::~CmosRWFile()
{}
CmosRWIo::~CmosRWIo()
{}
// TODO: need to throw exception on problem with file
//
u8 CmosRWFile::readByte (u32 indexPort, u32 dataPort, u32 offset) const
{
u8 retval = 0xFF;
u32 realOffset = indexPort * 256 + offset;
(void) dataPort; // unused
string errMessage("Could not open CMOS file(" + fileName + ") for reading: ");
FILE *fh = fopen (fileName.c_str (), "rb");
if( !fh )
throw smbios::InternalErrorImpl(errMessage + strerror(errno));
fseek (fh, static_cast<long>(realOffset), SEEK_SET);
size_t numBytes = fread (&retval, 1, sizeof (retval), fh); // only used in unit tests, so isnt critical
fclose (fh);
if (numBytes != sizeof(retval))
throw std::exception(); // short read. there isnt really a good exception to throw here.
return retval;
}
// TODO: need to throw exception on problem with file
//
void CmosRWFile::writeByte (u32 indexPort, u32 dataPort, u32 offset, u8 byte) const
{
//cout << "w(" << offset << ")";
u32 realOffset = indexPort * 256 + offset;
(void) dataPort; // unused
string errMessage("Could not open CMOS file(" + fileName + ") for writing: ");
FILE *fh = fopen (fileName.c_str (), "r+b");
if( !fh )
throw smbios::InternalErrorImpl(errMessage + strerror(errno));
fseek (fh, static_cast<long>(realOffset), SEEK_SET);
fwrite (&byte, 1, sizeof (byte), fh);
fclose (fh);
fflush(NULL);
if(! isNotifySuppressed() )
{
// writers are responsible for only writing changed values
// otherwise we get to see how fast our OS can do an
// infinite loop. :-)
notify();
}
return;
}
}
|