OpenWrt Forum Archive

Topic: map nvram variiables in /proc

The content of this topic has been archived on 5 Apr 2018. There are no obvious gaps in this topic, but there may still be some posts missing at the end.

hello,

is it possible to map nvram variable in /proc ?

I need this to avoid forking (or exec) in web server interface writen in php. Fork consume mush time,
reading a file may be very very lighter. Also we could create php interface to nvram. But with
/proc, reading could be possible with php, perl and any scripting languages.

An other way to do this should be to read raw nvram memory if it available. In Web interface
we make many read, and only free write (updates). So we could make read read, and update
securely with standard nvram command.

Here is what we could se for nvram in /proc :

cd /proc/nvram ; ls
-> should display all nvram variables,

cat /proc/nvram/boot_wait
-> display boot_wait status

echo 1 > /proc/nvram/boot_wait
-> set boot_wait to 1

rm /proc/nram/boot_wait
-> unset boot_wait value (not a good idea ...)

echo 1 > /proc/nvram/commit
-> commit nvram values. (may be an other way ?)

Hi _marc_,

I'm not sure I understood what you want, but it seems to me that all your examples (ls, echo, cat) will require a fork anyway.

Do you mean using native read / write functions in PHP / Perl / Whatever ?
If so, writing native bindings to libnvram for PHP / Perl / Whatever would be more efficient I suppose.

Get variable using nvram:

root@OpenWrt:/tmp# nvram show | grep lan_ipaddr
size: 1441 bytes (31327 left)
lan_ipaddr=192.168.1.1

Get variable from nvram using strings /dev/nvram:

root@OpenWrt:/tmp# strings /dev/nvram | grep lan_ipaddr
lan_ipaddr=192.168.1.1
root@OpenWrt:/tmp#

Write variable to nvram:

root@OpenWrt:/tmp# echo "foobar=123" > /dev/nvram

(Last edited by olli_04 on 17 Jun 2005, 10:30)

yes, strings /dev/nvram works fine. So now I am trying to read /dev/nvram with php fopen, fread, fgetc but have not been success now. I will give solution here if I found.

Nico wrote:

I'm not sure I understood what you want, but it seems to me that all your examples (ls, echo, cat) will require a fork anyway.
If so, writing native bindings to libnvram for PHP / Perl / Whatever would be more efficient I suppose.

forks are very expensive in my environment. (very is about 0.1 second), probably because httpd+php is a large process. So I am trying to avoid fork wait exec functions. Each exec give a fork. The other mean to read nvram variables is by reading /dev/nvram. And fopen+fread is very very much lighter.

A native nvram API for php would be very nice. But also time expensive.

again a nice way to talk with /dev/nvram :

root@ap51:/tmp# echo "vv1=abc          
> vv2=def
> vv3=zxy 
> " > /dev/nvram
root@ap51:/tmp# nvram show | grep vv
size: 2351 bytes (30417 left)
vv1=abc
vv2=def
vv3=zxy

can't read /dev/nvram with php. But I can read /proc/uptime for example.

Here is a sample code, with many checkings :

<pre>
<?php

error_reporting(E_ALL);

$nvram_dev = '/dev/nvram';
# $nvram_dev = '/proc/uptime';  # ok for this pseudo file

$fd = fopen($nvram_dev, 'r');

if(false === $fd){
    echo "error fopen\n";
    exit(1);
}

$i=0;
while ($i< 100){
    $status = fseek($fd, $i,SEEK_SET);
    if($status === false){
        echo "error fseek($i)\n";
        exit(1);
    }
       $char = fgetc($fd);
    if($char === false){
        # should close $fd and exit()
        $pos = ftell($fd);
        echo "error ($i) - $pos\n";
    }
    else {
        $pos = ftell($fd);
      echo "char = $char - " . ord($char) . "($i) - $pos\n";
    }
    $i++;
}

# ok - it works, so /dev/nvram can be read by httpd user.
# $nvram = system('strings /dev/nvram');

echo "system info : \n";
echo "pid : " . getmypid() . "\n";
echo "id : " .  getmyuid() . "\n";
echo "gid : " .  getmygid() . "\n";
echo "user : " .  get_current_user() . "\n";

?>

id, gid are O/O, (root/root) so it should be ok. I have made a chmod ugo+r /dev/vnram. It does not work to.

any idea ?

You can't seek in /dev/nvram; it's a one shot read -- You must read the entire thing in one call

If you want to set a value, you write to /dev/nvram using an =; ie write the string "boot_wait=on".

For reads, if you attempt to read the device without writing anything, you'll get all the nvram vars; if you write a variable name then read, it will spit back the value of that var.

mbm wrote:

You must read the entire thing in one call

yes ! thanks It was my problem.

here is a working script but it can work only one time. After that, there is no data read, but not error detected.
I need to restart thttpd (with embeded php) to enable again for one shot.

* I think /dev/nvram is not closed correctly.
* it is same pid for each requests so ressources are not closed automaticaly by kernel.

<pre>
<?php

$fp = fopen('/dev/nvram', 'rb');

if(false === $fp)
    trigger_error("Can't open /dev/nvram for reading");

$data = fread($fp, 1024*10);
fclose($fp);

if(false === $data)
    trigger_error("error reading /dev/nvram");
    
# preg_split is not available in this php distrib (thttpd)
# $data = preg_split('/\0/', $data, -1, PREG_SPLIT_NO_EMPTY);

# split with \0
$str = '';
$i=0; $last = 0;
$list = array();

while(1){
 if(ord($data[$i]) !== 0){
     $str .= $data[$i];
    }
 else{

         # echo "data = 0 ($i) - str = $str\n";
        # print_r($list); flush();

        # 2 \0 -> terminate loop
        if($last+1 == $i)
            break;
        list($key, $val) = split('=', $str);
                $list[$key] = $val;
        $str = '';

        $last = $i;
 }
 $i++;
}

$delay =  microtime_float() - $start;
echo "time = $delay\n";
print_r($list);

?>
_marc_ wrote:

here is a working script but it can work only one time. After that, there is no data read, but not error detected.
I need to restart thttpd (with embeded php) to enable again for one shot.

have you or anyone else found a fix for this yet?
my code is working but i have the exact same problem

Getaway007 wrote:

have you or anyone else found a fix for this yet?
my code is working but i have the exact same problem

I don't know, I'm not working any more on php under openwrt now.

_marc_, what you are trying to do is read that file as a random access file. It is not a normal file on a filesystem. Even using 1024*10 to try to read all the file in one pass without needing to fseek on it later is not the best way to do it.

The only thing you should do with /proc files is read them sequentially. Do not use fopen, fread, etc. Just open it and read it all in an array. My PHP is very rusty, but if I remember correctly there's a command to read an entire file to an array, in one shot, and close it. Then you scan the array to locate variables.

something like @array = readfile("/path/to/file");

Also, /proc files can be read only one time. You *must* open, read it all, close. If you want to read it again, you must open it again.

token

The discussion might have continued from here.