how to write to cmos memory

Hi all,
Can i write to cmos memory?
I am trying to write at particular offset in cmos memory but after reading value from that offset i am getting the previous value not the new value that i am writing.
I am using port 70 and 71 for the same.
It’s just a learning assignment.

Can someone please elaborate on this?

Thanks in anticipation!!

Hi all,

Can someone please guide me for above mentioned problem?

xxxxx@yahoo.com wrote:

Can i write to cmos memory?
I am trying to write at particular offset in cmos memory but after reading value from that offset i am getting the previous value not the new value that i am writing.
I am using port 70 and 71 for the same.
It’s just a learning assignment.

Can someone please elaborate on this?

From a kernel driver, yes, you can. From user-mode code, no, you can’t.

Hi all,

Can someone please guide me for above mentioned problem?

Geez, it was only an hour and a half! This is not a real-time support
chat line where people are standing by to take your call. This is a
mailing list,. Members are in different time zones around the world,
and most of us are trying to earn a living. Be patient.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

> It’s just a learning assignment.

You’ve got interesting “learning assignments” - modifying MBR and CMOS memory. I just wonder if your “learning assignments” involves modifying flash BIOS as well…

Anton Bassov

Thanks Tim!!

I am trying to modify byte in cmos memory from kernel mode driver.
I am using port 0x70 and 0x71 for the same.
When I read from cmos memory, then write new value to cmos memory at same offset and again read back from same offset i am not getting new value that i have written.
I have also added sufficient delay.
Is there anything special that i have to do apart from in and out instructions on ports?

Writes are not reflecting over cmos memory.
Thanks in anticipation!!

xxxxx@yahoo.com wrote:

Thanks Tim!!

I am trying to modify byte in cmos memory from kernel mode driver.
I am using port 0x70 and 0x71 for the same.
When I read from cmos memory, then write new value to cmos memory at same offset and again read back from same offset i am not getting new value that i have written.
I have also added sufficient delay.
Is there anything special that i have to do apart from in and out instructions on ports?

No, so you must have done something wrong. Post the code and we’ll
check it.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Well, ports 0x70 and 0x71 are what’s called an “index/data register
pair.” You write to one to say which offset in the internal device
space the other manipulates.

You can’t access an index/data pair without a lock, or you get
undefined results. Say you want to write to byte 67 in CMOS space.
You write a 67 to port 0x70 and then you write the data to port 0x71.
But, if some other code runs between your two accesses (either on
another processor or because your thread got swapped) then port 0x70
may not contain 67 when you write to port 0x71.

This is where this discussion gets interesting. Both the OS and the
BIOS use the RTC, which contains the CMOS device. The OS has a
spinlock to make sure that it doesn’t collide. And the BIOS doesn’t
write to port 0x70 until it has corralled all the processors in System
Management Mode, and then it restores any previous contents of the
port when it exits.

Your code probably isn’t guaranteeing atomic access to CMOS. (It
probably has other issues, too, but we don’t know about those yet.)

You can guarantee atomic access to CMOS using HalSetBusData.

  • Jake Oshins
    Windows Kernel Team
    (Author of at least part of the CMOS access code in Windows)

wrote in message news:xxxxx@ntdev…
> Thanks Tim!!
>
> I am trying to modify byte in cmos memory from kernel mode driver.
> I am using port 0x70 and 0x71 for the same.
> When I read from cmos memory, then write new value to cmos memory at
> same offset and again read back from same offset i am not getting
> new value that i have written.
> I have also added sufficient delay.
> Is there anything special that i have to do apart from in and out
> instructions on ports?
>
> Writes are not reflecting over cmos memory.
> Thanks in anticipation!!
>

Thanks Tim and Jake!!!
Sorry for late reply.

This is a piece of code with which i am trying to write to cmos memory.

unsigned char index = 16;
unsigned char buff=0,PrevBuff=0;
KeAcquireSpinLock(pspin_lock,&cIrq);

//Read
_asm {
xor ax,ax /* Clear Accumulator*/
cli /* Clear interrupts*/
mov al,index /* move index address*/
out 0x70,al /* copy address to CMOS register*/
nop
nop
nop /* Wait a bit for response*/
in al,0x7 1 /* Fetch 1 byte to al*/
sti /* Enable interrupts*/
mov buff,al
}
PrevBuff = buff;
buff=0x3F;

//Write
_asm {
xor ax,ax /* zero register*/
cli
mov al,index /* move index address*/
mov ah,buff /* copy value to ah*/
out 0x70,al /* copy address to CMOS register*/
nop
nop
nop
mov al,ah /* move value to al*/
out 0x71,al /* write 1 byte to CMOS*/
sti /* Enable interrupts*/
}
KeReleaseSpinLock(pspin_lock,cIrq);

When i write to cmos memory at offset 16 and again when i read back from same offset i am not getting new value.
I have added sufficient delay and lock for the same.

I have also try to add delay upto 3 seconds using KeDelayExecutionThread ,but it won’t work.
Let me know if i am missing anything.

Thanks in anticipation!!!

Too many years since I did anything like this to quickly spot
anything wrong, but why aren’t you using the native functions which
are portable ?

READ_PORT_UCHAR()
WRITE_PORT_UCHAR()
etc

Using the above will get rid of any assembler mistakes you might have made.

Mark.

At 07:29 AM 3/7/2008, xxxxx@yahoo.com wrote:

Thanks Tim and Jake!!!
Sorry for late reply.

This is a piece of code with which i am trying to write to cmos memory.

unsigned char index = 16;
unsigned char buff=0,PrevBuff=0;
KeAcquireSpinLock(pspin_lock,&cIrq);

//Read
_asm {
xor ax,ax /* Clear Accumulator*/
cli /* Clear interrupts*/
mov al,index /* move index address*/
out 0x70,al /* copy address to CMOS register*/
nop
nop
nop /* Wait a bit for response*/
in al,0x7 1 /* Fetch 1 byte to al*/
sti /* Enable interrupts*/
mov buff,al
}
PrevBuff = buff;
buff=0x3F;

//Write
_asm {
xor ax,ax /* zero register*/
cli
mov al,index /* move index address*/
mov ah,buff /* copy value to ah*/
out 0x70,al /* copy address to CMOS register*/
nop
nop
nop
mov al,ah /* move value to al*/
out 0x71,al /* write 1 byte to CMOS*/
sti /* Enable interrupts*/
}
KeReleaseSpinLock(pspin_lock,cIrq);

When i write to cmos memory at offset 16 and again when i read back
from same offset i am not getting new value.
I have added sufficient delay and lock for the same.

I have also try to add delay upto 3 seconds using
KeDelayExecutionThread ,but it won’t work.
Let me know if i am missing anything.

Thanks in anticipation!!!


HalGet/SetBusData with BusTypeInternal is the way.


Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com

wrote in message news:xxxxx@ntdev…
> Hi all,
> Can i write to cmos memory?
> I am trying to write at particular offset in cmos memory but after reading
value from that offset i am getting the previous value not the new value that i
am writing.
> I am using port 70 and 71 for the same.
> It’s just a learning assignment.
>
> Can someone please elaborate on this?
>
> Thanks in anticipation!!
>

I replaced my assembly code with READ_PORT_UCHAR & WRITE_PORT_UCHAR, but it behaves the same way i.e.
i am not getting the value that i wrote previously.
Is there anything that i am missing?

Also as suggested by maxim to use HalGetBusData, What value i should specify for parameter such as

BusNumber,SlotNumber,Buffer,Length? Where should i specify port no.?

Also is cmos memory is locked ? if it is how can i unlock it?

Thanks in anticipation!!

I don’t see how this could really be the issue in and of themselves, but
your problem made me think of these, which I read a while ago:

http://support.microsoft.com/kb/283649

http://www.microsoft.com/whdc/archive/BIOSAML.mspx

Basically, what they say is that access to 0x70 & 0x71 from ACPI AML
code are blocked on XP and forward, and an attempt to access these ports
from AML would result in an entry in the system event log, along the
lines of:

“Source: ACPI Category: None Type: Error Event ID: 5 User: N/A Computer:
Machine_Name Description: AMLI: ACPI BIOS is attempting to write to an
illegal IO port address (0xnnnn), which lies in the 0xXXXX - 0xYYYY
protected address range. This could lead to system instability. Please
contact your system vendor for technical assistance.”

As you’re not using AML, this isn’t your problem, but given that it is
possible for a chipset to cause I/O to a port to result in an SMI, I
thought I would mention this, mostly to see if anyone has any thoughts
on the subject. At least for the Intel chipsets with which I am
reasonably familiar, buried somewhere in the usually 800 or so pages
that document whatever ICH a platform happens to use, there’s a way to
redirect most anything to an SMI. Perhaps there’s something ACPI
related going on here. I’m not suggesting that there is; I really have
no idea. As there is really not much to the code involved, I am kind of
wondering what’s going on here. Historically, the RTC has been a source
of instability and exploit, and SMM has been used by firmware vendors
for things like power management, error correction, hardware emulation,
and in the implementation of other really, really nasty hacks, so,
barring any better ideas, which I think probably are, I don’t think it
unreasonable to wonder if there’s something like this going on. That
being said, I would definitely explore this as a possibility only if no
better ideas surface, because I don’t see it as particularly likely, but
also because, reasonably speaking, there’s no way to investigate this
one without a JTAG emulator or some other expensive form of hardware
assisted debugging.

Good luck,

mm

Mark S. Edwards wrote:

Too many years since I did anything like this to quickly spot anything
wrong, but why aren’t you using the native functions which are portable ?

READ_PORT_UCHAR()
WRITE_PORT_UCHAR()
etc

Using the above will get rid of any assembler mistakes you might have made.

Mark.

At 07:29 AM 3/7/2008, xxxxx@yahoo.com wrote:
> Thanks Tim and Jake!!!
> Sorry for late reply.
>
> This is a piece of code with which i am trying to write to cmos memory.
>
> unsigned char index = 16;
> unsigned char buff=0,PrevBuff=0;
> KeAcquireSpinLock(pspin_lock,&cIrq);
>
> //Read
> _asm {
> xor ax,ax /* Clear Accumulator*/
> cli /* Clear interrupts*/
> mov al,index /* move index address*/
> out 0x70,al /* copy address to CMOS register*/
> nop
> nop
> nop /* Wait a bit for response*/
> in al,0x7 1 /* Fetch 1 byte to al*/
> sti /* Enable interrupts*/
> mov buff,al
> }
> PrevBuff = buff;
> buff=0x3F;
>
> //Write
> _asm {
> xor ax,ax /* zero register*/
> cli
> mov al,index /* move index address*/
> mov ah,buff /* copy value to ah*/
> out 0x70,al /* copy address to CMOS register*/
> nop
> nop
> nop
> mov al,ah /* move value to al*/
> out 0x71,al /* write 1 byte to CMOS*/
> sti /* Enable interrupts*/
> }
> KeReleaseSpinLock(pspin_lock,cIrq);
>
> When i write to cmos memory at offset 16 and again when i read back
> from same offset i am not getting new value.
> I have added sufficient delay and lock for the same.
>
> I have also try to add delay upto 3 seconds using
> KeDelayExecutionThread ,but it won’t work.
> Let me know if i am missing anything.
>
> Thanks in anticipation!!!
>
> —

I don’t think that you understood my post. Please re-read it.

Your spinlock isn’t doing anything, as the system is using a different
spinlock for its own access to CMOS.

  • Jake

wrote in message news:xxxxx@ntdev…
> Thanks Tim and Jake!!!
> Sorry for late reply.
>
> This is a piece of code with which i am trying to write to cmos
> memory.
>
> unsigned char index = 16;
> unsigned char buff=0,PrevBuff=0;
> KeAcquireSpinLock(pspin_lock,&cIrq);
>
> //Read
> _asm {
> xor ax,ax /* Clear Accumulator*/
> cli /* Clear interrupts*/
> mov al,index /* move index address*/
> out 0x70,al /* copy address to CMOS register*/
> nop
> nop
> nop /* Wait a bit for response*/
> in al,0x7 1 /* Fetch 1 byte to al*/
> sti /* Enable interrupts*/
> mov buff,al
> }
> PrevBuff = buff;
> buff=0x3F;
>
> //Write
> _asm {
> xor ax,ax /* zero register*/
> cli
> mov al,index /* move index address*/
> mov ah,buff /* copy value to ah*/
> out 0x70,al /* copy address to CMOS register*/
> nop
> nop
> nop
> mov al,ah /* move value to al*/
> out 0x71,al /* write 1 byte to CMOS*/
> sti /* Enable interrupts*/
> }
> KeReleaseSpinLock(pspin_lock,cIrq);
>
> When i write to cmos memory at offset 16 and again when i read back
> from same offset i am not getting new value.
> I have added sufficient delay and lock for the same.
>
> I have also try to add delay upto 3 seconds using
> KeDelayExecutionThread ,but it won’t work.
> Let me know if i am missing anything.
>
> Thanks in anticipation!!!
>

xxxxx@yahoo.com wrote:

Is there anything that i am missing?

Yes. Persistence on your assignment. And an understanding how to look
for information, e.g. on Google and MSDN.

Also as suggested by maxim to use HalGetBusData, What value i should specify for parameter such as
BusNumber,SlotNumber,Buffer,Length? Where should i specify port no.?

This is evident from the description given in an MSDN CEDDK article
version about the functions Maxim kindly pointed you to.

If after reading the MSDN article you still don’t understand, why don’t
you try out the function call, and look into the program flow with the
free kernel debugger? You will learn a lot this way. Real, hard
experience, that is necessary later in life to solve real problems.

You told us you have an assignment. This is probably not to waste your
time but to make you explore strategies for learning and applying the
information needed to solve problems.
Probably you are actually supposed to experiment a bit.