Home > database >  Reading from memory and getting in char array.. What if a char in that contains 1 byte that suppose
Reading from memory and getting in char array.. What if a char in that contains 1 byte that suppose

Time:03-12

So I am reading memory that suppose to be bios info in C. And with usual read I get bunch of characters that.. The idea is those characters are making fields like Anchor "String" and 1 byte checksum and 1 Byte Length. But in C number is int or long. INT is 4 bytes. But I have char representing checksum and length is just taking 1 byte (1 character == 0x00 1 byte how to read it as int)

I am doing it like this . unsigned char checksum=mem[0]; first 1 byte character represent checksum. But check sum suppose to be a number which should be unsigned int checksum = mem[0].. The printing it prints 0

Then moving on this is how I get 1 byte length from my char array mem at index 1.

length = mem[1];
//int x=mem[2]; 

And suppose If I have two byte number (Word length data) representing max size I am doing it like this at index 4 in my character array..

    char x1[3];
    memcpy(x1,&mem[4],2);
    x1[2]='\0';
    long v=strtol(x1,'\0',16);
    

Above is obviously printing wrong result for my max size. printing 0. And it does not seems all right either. long is 8 bytes But I have two byte that should represent my max size field in bios.

May be above is just wrong thinking that if I believe its correct or wrong. the fact is I really dont know how to handle this sort of conversion. Can any one please let me is above is wrong or correct. Or makes sense for what I like to achieve

This is 2.1 table info from bios I am trying to extract. My anchor strings are printing correct but number fields not printing correct I am gett 0 for max size. 31 for length

https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.0.0.pdf

This is the code

void get_it(char *arr)
{

    char *mem = (unsigned char *) &arr[0];
    int length, i;
    unsigned char checksum=mem[0];
    printf("checksum %d\n",checksum);
    
    length = mem[1];
    int x=mem[2];
    int y=0;
    y=mem[3];
    
    
    
    printf("\nlength = %d version = %x\n minor version = %d",length,x,mem[3]);
    char x1[3];
    memcpy(x1,&mem[4],2);
    x1[2]='\0';
    long v=strtol(x1,'\0',16);
    
    printf("max size %lx\n",v);
    printf("entry point revision = %d\n",mem[6]);
    printf("~~ %c %c %c %c %c\n",mem[12],mem[13],mem[14],mem[15],mem[16]);  
    /*checksum = 0;
    for(i = 0; i < length; i  ) 
    {
       checksum  = mem[i];
    }
    
    if(checksum == 0) break;
    
    mem  = 16;
    */

    mem=mem length;
    char type=*mem;
    printf("first type = %d",*mem);
    printf("length = %d",*(mem 1));
    
    int j=0;
    
    
    


}



int main()
{

    int fd=open("/dev/mychardev-0",O_RDWR);
    if(fd<=0)
    {   
        printf("fd %d\n",fd);
        exit(0);

    }

    size_t length=1048576;
    size_t x=0;
    char *buffer=malloc(sizeof(char )*length);
    while(x<length)
    {
        int valread=read(fd,buffer,length);
        printf("here\n");
        if(valread==0)
        {
            printf("zero bytes read\n");
            
            break;
        }
    
        if(valread<0)
        {
            printf("read return negative %d %d\n",valread,errno);

            break;
        }
        x=x valread;
        
    }
    if(x>0)
    {
        size_t y=0;
        while(y<x)
        {

            if(*(buffer y)=='_' && *(buffer y 1)=='S' && *(buffer y 2)=='M' && *(buffer y 3)=='_')
            {
                                                
                
                printf("%c\n",buffer[y]);
                printf("%c\n",buffer[y 1]);
                printf("%c\n",buffer[y 2]);
                buffer=buffer 4;
                get_it(buffer);

            }
            y  ;

        }
        printf("%x\n",buffer);
    }
    else
    {
        printf("ops no read\n");
    }
    return 0;
}

CodePudding user response:

But in C number is int or long.

char is an integral type which can be used to represent numbers, the same as short, int or long.

It has a maximum value of CHAR_MAX.

One problem is that the signedness of char is implementation-defined. When in doubt, be explicit with signed char (SCHAR_MAX) or unsigned char (UCHAR_MAX).

Alternatively, use fixed width integer types to make it easier to reason about the byte width of the data you are working with.

The fields in the EPS table are denoted as being of size BYTE, WORD, and DWORD. These can be represented by uint8_t, uint16_t, and uint32_t respectively, as you almost certainly want unsigned integers.


This code

char x1[3];
memcpy(x1,&mem[4],2);
x1[2]='\0';
long v=strtol(x1,'\0',16);

printf("max size %lx\n",v);

that attempts to parse the Maximum Structure Size as if it were a number represented by two characters is incorrect. The Maximum Structure Size is a 16-bit integer.

mem=mem length; does not make much sense, as this would place you in memory beyond the table. I am not sure what the two printf calls that follow are trying to print.

Additionally, your example includes some errant code (unused variables: i, y, j).

Everything else is more-or-less correct, if messy.


Below is a simple example that seemingly works on my machine, using the smbios_entry_point table file. You should be able to use it as reference to adjust your program accordingly.

$ uname -rmo
5.14.21-210.current x86_64 GNU/Linux
#include <fcntl.h>
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#define EPS_SIZE 31
#define TARGET_FILE "/sys/firmware/dmi/tables/smbios_entry_point"

void print_buffer(uint8_t *eps) {
    printf("Anchor string: %c%c%c%c\n", eps[0], eps[1], eps[2], eps[3]);
    printf("Checksum: Xh\n", eps[4]);
    printf("Entry point length: Xh\n", eps[5]);
    printf("Major version: Xh\n", eps[6]);
    printf("Minor version: Xh\n", eps[7]);

    uint16_t mss;
    memcpy(&mss, eps   8, sizeof mss);
    printf("Maximum structure size: %" PRIu16 " bytes\n", mss);

    printf("Entry point revision: Xh\n", eps[10]);
    printf("Formatted area: Xh Xh Xh Xh Xh\n",
            eps[11], eps[12], eps[13], eps[14], eps[15]);
    printf("Intermediate anchor string: %c%c%c%c%c\n",
            eps[16], eps[17], eps[18], eps[19], eps[20]);
    printf("Intermediate checksum: Xh\n", eps[21]);

    uint16_t stl;
    memcpy(&stl, eps   22, sizeof stl);
    printf("Structure table length: %" PRIu16 " bytes \n", stl);

    uint32_t sta;
    memcpy(&sta, eps   24, sizeof sta);
    printf("Structure table address: 0xx\n", sta);

    uint16_t nsmbs;
    memcpy(&nsmbs, eps   28, sizeof nsmbs);
    printf("Number of SMBIOS structures: %" PRIu16 "\n", nsmbs);

    printf("SMBIOS BCD revision: Xh Xh\n",
            eps[30] >> 4, eps[30] & 0x0f);
}

int main(void) {
    uint8_t buf[EPS_SIZE];
    int fd = open(TARGET_FILE, O_RDONLY);

    read(fd, buf, sizeof buf);
    close(fd);

    print_buffer(buf);
}

stdout:

Anchor string: _SM_
Checksum: C2h
Entry point length: 1Fh
Major version: 02h
Minor version: 07h
Maximum structure size: 184 bytes
Entry point revision: 00h
Formatted area: 00h 00h 00h 00h 00h
Intermediate anchor string: _DMI_
Intermediate checksum: DCh
Structure table length: 2229 bytes
Structure table address: 0x000ed490
Number of SMBIOS structures: 54
SMBIOS BCD revision: 02h 07h

You may also be interested in dmidecode and its source code.

  • Related