I'm Trying to understand the PE Format & the source code of "hook_finder" in here
"https://github.com/Mr-Un1k0d3r/EDRs/blob/main/hook_finder64.c"
in this snippet I now it's trying to calculate Export_Table offset:
VOID DumpListOfExport(VOID *lib, BOOL bNt) {
DWORD dwIter = 0;
CHAR* base = (CHAR*)lib;
CHAR* PE = base + (unsigned char)*(base + 0x3c);
DWORD ExportDirectoryOffset = *((DWORD*)PE + (0x8a / 4));
CHAR* ExportDirectory = base + ExportDirectoryOffset;
DWORD dwFunctionsCount = *((DWORD*)ExportDirectory + (0x14 / 4));
DWORD OffsetNamesTableOffset = *((DWORD*)ExportDirectory + (0x20 / 4));
CHAR* OffsetNamesTable = base + OffsetNamesTableOffset;
printf("------------------------------------------\nBASE\t\t\t0x%p\t%s\nPE\t\t\t0x%p\t%s\nExportTableOffset\t0x%p\nOffsetNameTable\t\t0x%p\nFunctions Count\t\t0x%x (%d)\n------------------------------------------\n",
base, base, PE, PE, ExportDirectory, OffsetNamesTable, dwFunctionsCount, dwFunctionsCount);
for(dwIter; dwIter < dwFunctionsCount - 1; dwIter++) {
DWORD64 offset = *((DWORD*)OffsetNamesTable + dwIter);
CHAR* current = base + offset;
GetBytesByName((HANDLE)lib, current, bNt);
}
}
ox3c is e_lfnew offset. However, can't understand what's other hex values and why it's divided by 4 byte?
Further,
VOID GetBytesByName(HANDLE hDll, CHAR *name, BOOL bNt) {
FARPROC ptr = GetProcAddress((HMODULE)hDll, name);
DWORD* opcode = (DWORD*)*ptr;
if(bNt) {
if(name[0] != 'N' && name[1] != 't') {
return;
}
}
if((*opcode << 24) >> 24 == 0xe9) {
if(!IsFalsePositive(name)) {
printf("%s is hooked\n", name);
}
}
}
what's been exactly left & right shifting and Why 24 specifically?
From my understanding of EDRs, it adds a JMP instruction at the very beginning of the function and that's why the condition is trying to check if it's (0xe9), but how does it follow and be certain about the function flow?
and is this applicable only for ntdll.dll?
Sorry I'm starting to study the PE behavior and trying to make things very clear.
Thank you in advance
The function DumpListOfExport assumes that NtHeaders start at the offset 0x3c from the base but, this is not always the case depending on the size of the DOS stub. Probably, this code makes that assumption for ntdll.dll.
And in the function GetBytesByName, if first byte of the procedure starts with a JMP(in that case, it is near, relative jmp whose opcode starts with "E9") instruction and the procedure name is not in the false positives list, then the function makes decision that the function is hooked.
Let be the value of the 4-bytes pointed to by opcode 0xca0e4be9, left shifting it by 24 will result in 0xe9000000, and then right shifting by 24 the result will be 0x000000e9 which is the value of the first byte at ptr.
That procedure can be simplified as follows.
VOID GetBytesByName(HANDLE hDll, CHAR *name, BOOL bNt) {
FARPROC ptr = GetProcAddress((HMODULE)hDll, name);
BYTE* opcode = (BYTE*)ptr;
if(bNt) {
if(name[0] != 'N' && name[1] != 't') {
return;
}
}
if(!IsFalsePositive(name) && *opcode == 0xe9) {
printf("%s is hooked\n", name);
}
}
As a note : I can say that the code isn't written well, and doesn't follow any good coding style.
Related
I was making an os, or atleast trying to, but I stumbled upon a problem. While trying to iterate over a string to convert to char to print to screen, the returned char seemed to be empty!(I am actually new to os development); Here is the code snippet:
int offset = 0;
void clear_screen() {
unsigned char * video = 0xB8000;
for(int i = 0; i < 2000; i+=2){
video[i] = ' ';
}
}
void printc(char c) {
unsigned char * video = 0xB8000;
video[offset] = c;
video[offset+1] = 0x03;
offset += 2;
}
void print(unsigned char *string) {
char * sus = '\0';
uint32 i = 0;
printc('|');
sus[0] = 'a';
printc(sus[0]); //this prints "a" correctly
string[i] = 'c';
while (string[i] != '\0') {
printc(string[i]); //this while loop is only called once
i++; //it prints " " only once and exits
}
printc('|');
}
int bootup(void)
{
clear_screen();
// printc('h');
// printc('e');
// printc('l'); /* These work */
// printc('l');
// printc('o');
print("hello"); //this doesn't
return 1;
}
Output that it prints:
|a |
Thanks in advance!!
edit
New print function
void print(unsigned char *string) {
uint32 i = 0;
printc('|');
while (string[i] != '\0') {
printc('i'); //not printed
printc(string[i]);
i++;
}
printc('|');
}
still does not work
edit 2
updated the code as per #lundin's advice
int offset = 0;
void clear_screen() {
unsigned char * video = (unsigned char *)0xB8000;
for(int i = 0; i < 2000; i+=2){
video[i] = ' ';
}
}
void printc(char c) {
unsigned char * video = (unsigned char *)0xB8000;
video[offset] = c;
video[offset+1] = 0x03;
offset += 2;
}
void print(const char *string) {
int i = 0;
printc('|');
while (string[i] != '\0') {
printc('i');
printc(string[i]);
i++;
}
printc('|');
}
int bootup(void)
{
clear_screen();
// printc('h');
// printc('e');
// printc('l');
// printc('l');
// printc('o');
print("hello");
return 1;
}
stack:
init_lm:
mov ax, 0x10
mov fs, ax ;other segments are ignored
mov gs, ax
mov rbp, 0x90000 ;set up stack
mov rsp, rbp
;Load kernel from disk
xor ebx, ebx ;upper 2 bytes above bh in ebx is for cylinder = 0x0
mov bl, 0x2 ;read from 2nd sectors
mov bh, 0x0 ;head
mov ch, 1 ;read 1 sector
mov rdi, KERNEL_ADDRESS
call ata_chs_read
jmp KERNEL_ADDRESS
jmp $
Before proceeding I would recommend reading the OSDev wiki's page on text-based UIs.
While this may go beyond the scope of the question somewhat, I would strongly recommend that, rather than working with the character/attribute values as unsigned char manually, you might want to declare a struct type for those pairs:
struct TextCell {
volatile unsigned char ch;
volatile uint8_t attribute;
};
(You could actually be even more refined about it, by using a bitfield for the individual foreground, background, and decoration components of the attributes, but that's probably getting ahead of things.)
From there you can define the text buffer as a constant pointer:
const struct TextCell* text_buffer = (TextCell *)0xB8000;
You could further define
const uint16_t MAXH = 80, MAXV = 25;
uint16_t currv = 0, currh = 0;
struct TextCell* text_cursor = text_buffer;
void advance_cursor() {
text_cursor++;
if (currh < MAXH) {
currh++;
}
else {
currh = 0;
if (currv < MAXV) {
currv++;
}
else {
/* handle scrolling */
}
}
}
void gotoxy(uint16_t x, uint16_t y) {
uint16_t new_pos = x * y;
if (new_pos > (MAXV * MAXH)) {
text_cursor = text_buffer + (MAXV * MAXH);
currh = MAXH;
currv = MAXV;
}
else {
text_cursor += new_pos;
currh = x;
currv = y;
}
Which would lead to the following modifications of your code:
void kprintc(char c, uint8_t attrib) {
text_cursor->ch = c;
text_cursor->attribute = attrib;
advance_cursor();
}
void kprint(const char *string, uint8_t attribs) {
int i;
for (i = 0; string[i] != '\0'; i++) {
kprintc(string[i], attribs);
}
}
void clear_screen() {
for(int i = 0; i < (MAXH * MAXV); i++) {
kprintc(' ', 0);
}
}
int bootup(void) {
clear_screen();
// kprintc('h', 0x03);
// kprintc('e', 0x03);
// kprintc('l', 0x03);
// kprintc('l', 0x03);
// kprintc('o', 0x03);
kprint("hello", 0x03);
return 1;
}
So, why am I suggesting all of this extra stuff? Because it is a lot easier to debug this way, mainly - it divides the concerns up better, and structures the data (or in this case, the video text buffer) more effectively. Also, you'll eventually need to do something like this at some point in the project, so if it helps now, you might as well do it now.
If I am out of line in this, please let me know.
Your program has undefined behavior since it contains multiple lines that aren't valid C. You will have gotten compiler messages about those lines.
unsigned char * video = 0xB8000; etc is not valid C, you need an explicit cast. "Pointer from integer/integer from pointer without a cast" issues
Similarly, char * sus = '\0'; is also not valid C. You are trying to assign a pointer to a single character, which doesn't make sense. String handling beginner FAQ here: Common string handling pitfalls in C programming. It also addresses memory allocation basics.
sus[0] = 'a'; etc here you have wildly undefined behavior since sus isn't pointing at valid memory.
In case you are actually trying to access physical memory addresses, this isn't the correct way to do so. You need volatile qualified pointers. See How to access a hardware register from firmware? (In your case it probably isn't a register but everything from that link still applies - how to use hex constants etc.)
EDIT: void print(unsigned char *string) ... string[i] = 'c'; is also wrong. First of all you are passing a char* which is not necessarily compatible with unsigned char*. Then you shouldn't modify the passed string from inside a function called print, that doesn't make sense. This should have been const char* string to prevent such bugs. As it stands you are passing a string literal to this function and then try to modify it - that is undefined behavior since string literals are read-only.
Assuming gcc or clang, if you wish to block the compiler from generating an executable out of invalid C code, check out What compiler options are recommended for beginners learning C? In your case you also likely need the -ffreestanding option mentioned there.
char * sus = '\0';
Have not checked more... but this assigns a null pointer to sus, and most probably is not what you want to do.
I have an array that is declared inside a public struct like this:
uint16_t *registers;
In a function I'm retrieving a char string (stored in buffer, see code below) that contains numerical values separated by a comma (e.g., "1,12,0,136,5,76,1243"). My goal is to get each individual numerical value and store it in the array, one after another.
i = 0;
const char delimiter[] = ",";
char *end;
tmp.vals = strtok(buffer, delimiter);
while (tmp.vals != NULL) {
tmp.registers[i] = strtol(tmp.vals, &end, 10);
tmp.vals = strtok(NULL, delimiter);
i++;
}
The problem is that the line containing strtol is producing a Segmentation fault (core dumped) error. I'm pretty sure it's caused by trying to fit unsigned long values into uint16_t array slots but no matter what I try I can't get it fixed.
Changing the code as follows seems to have solved the problem:
unsigned long num = 0;
size_t size = 0;
i = 0;
size = 1;
tmp.vals = (char *)calloc(strlen(buffer) + 1, sizeof(char));
tmp.registers = (uint16_t *)calloc(size, sizeof(uint16_t));
tmp.vals = strtok(buffer, delimiter);
while (tmp.vals != NULL) {
num = strtoul(tmp.vals, &end, 10);
if (0 <= num && num < 65536) {
tmp.registers = (uint16_t *)realloc(tmp.registers, size + i);
tmp.registers[i] = (uint16_t)num;
} else {
fprintf(stderr, "==> %lu is too large to fit in register[%d]\n", num, i);
}
tmp.vals = strtok(NULL, delimiter);
i++;
}
A long integer is at least 32 bits, so yes, you're going to lose information trying to shove a signed 32 bit integer into an unsigned 16 bit integer. If you have compiler warnings on (I use -Wall -Wshadow -Wwrite-strings -Wextra -Wconversion -std=c99 -pedantic) it should tell you that.
test.c:20:28: warning: implicit conversion loses integer precision: 'long' to 'uint16_t'
(aka 'unsigned short') [-Wconversion]
tmp.registers[i] = strtol(tmp.vals, &end, 10);
~ ^~~~~~~~~~~~~~~~~~~~~~~~~~
However, this isn't going to cause a segfault. You'll lose 16 bits and the change in sign will do funny things.
#include <stdio.h>
#include <inttypes.h>
int main() {
long big = 1234567;
uint16_t small = big;
printf("big = %ld, small = %" PRIu16 "\n", big, small);
}
If you know what you're reading will fit into 16 bits, you can make things a little safer first by using strtoul to read an unsigned long, verify that it's small enough to fit, and explicitly cast it.
unsigned long num = strtoul(tmp.vals, &end, 10);
if( 0 <= num && num < 65536 ) {
tmp.registers[i] = (uint16_t)num;
}
else {
fprintf(stderr, "%lu is too large to fit in the register\n", num);
}
More likely tmp.registers (and possibly buffer) weren't properly initialized and allocated points to garbage. If you simply declared the tmp on the stack like so:
Registers tmp;
This only allocates memory for tmp, not the things it points to. And it will contain garbage. tmp.registers will point to some random spot in memory. When you try to write to it it will segfault... eventually.
The register array needs to be allocated.
size_t how_many = 10;
uint16_t *registers = malloc( sizeof(uint16_t) * how_many );
Thing tmp = {
.registers = registers,
.vals = NULL
};
This is fine so long as your loop only ever runs how_many times. But you can't be sure of that when reading input. Your loop is potentially reading an infinite number of registers. If it goes over the 10 we've allocated it will again start writing into someone else's memory and segfault.
Dynamic memory is too big a topic for here, but we can at least limit the loop to the size of the array by tracking the maximum size of registers and how far in it is. We could do it in the loop, but it really belongs in the struct.
typedef struct {
uint16_t *registers;
char *vals;
size_t max;
size_t size;
} Registers;
While we're at it, put initialization into a function so we're sure it's done reliably each time.
void Registers_init( Registers *registers, size_t size ) {
registers->registers = malloc( sizeof(uint16_t) * size );
registers->max = size;
registers->size = 0;
}
And same with our bounds check.
void Registers_push( Registers *registers, uint16_t num ) {
if( registers->size == registers->max ) {
fprintf(stderr, "Register has reached its limit of %zu\n", registers->max);
exit(1);
}
registers->registers[ registers->size ] = (uint16_t)num;
registers->size++;
}
Now we can add registers safely. Or at least it will error nicely.
Registers registers;
Registers_init( ®isters, 10 );
tmp.vals = strtok(buffer, delimiter);
while (tmp.vals != NULL) {
unsigned long num = strtoul(tmp.vals, &end, 10);
if( 0 <= num && num < 65536 ) {
Registers_push( &tmp, (uint16_t)num );
}
else {
fprintf(stderr, "%lu is too large to fit in the register\n", num);
}
tmp.vals = strtok(NULL, delimiter);
i++;
}
At this point we're re-implementing a size-bound array. It's a good exercise, but for production code use an existing library such as GLib which provides self-growing arrays and a lot more features.
I have run into a strange bug and I cannot for the life of me get it figured out. I have a function that decodes a byte array into a string based on another encoding function. The function that decodes looks roughly like this:
char *decode_string( uint8_t *encoded_string, uint32_t length,
uint8_t encoding_bits ) {
char *sequence_string;
uint32_t idx = 0;
uint32_t posn_in_buffer;
uint32_t posn_in_cell;
uint32_t encoded_nucleotide;
uint32_t bit_mask;
// Useful Constants
const uint8_t CELL_SIZE = 8;
const uint8_t NUCL_PER_CELL = CELL_SIZE / encoding_bits;
sequence_string = malloc( sizeof(char) * (length + 1) );
if ( !sequence_string ) {
ERR_PRINT("could not allocate enough space to decode the string\n");
return NULL;
}
// Iterate over the buffer, converting one nucleotide at a time.
while ( idx < length ) {
posn_in_buffer = idx / NUCL_PER_CELL;
posn_in_cell = idx % NUCL_PER_CELL;
encoded_nucleotide = encoded_string[posn_in_buffer];
encoded_nucleotide >>= (CELL_SIZE - encoding_bits*(posn_in_cell+1));
bit_mask = (1 << encoding_bits) - 1;
encoded_nucleotide &= bit_mask;
sequence_string[idx] = decode_nucleotide( encoded_nucleotide );
// decode_nucleotide returns a char on integer input.
idx++;
}
sequence_string[idx] = '\0';
printf("%s", sequence_string); // prints the correct string
return sequence_string;
}
The bug is that the return pointer, if I try to print it, causes a segmentation fault. But calling printf("%s\n", sequence_string) inside of the function will print everything just fine. If I call the function like this:
const char *seq = "AA";
uint8_t *encoded_seq;
encode_string( &encoded_seq, seq, 2, 2);
char *decoded_seq = decode_string( encoded_seq, 2, 2);
if ( decoded_seq ) {
printf("%s\n",decoded_seq); // this crashes
if ( !strcmp(decoded_seq, seq) ) {
printf("Success!");
}
then it will crash on the print.
A few notes, the other functions seem to all work, I've tested them fairly thoroughly (i.e. decode_nucleotide, encode_string). The string also prints correctly inside the function. It is only after the function returns that it stops working.
My question is, what might cause this memory to become invalid just by returning the pointer from a function? Thanks in advance!
First (and not that important, but) in the statement:
sequence_string = malloc( sizeof(char) * (length + 1) );
sizeof(char) by definition is always == 1. so the statement becomes:
sequence_string = malloc(length + 1);
In this section of your post:
char *decoded_seq = decode_string( encoded_seq, 2, 2);
...since I cannot see your implementation of decode_string, I can only make assumptions about how you are verifying its output before returning it. I do however understand that you are expecting the return value to contain values that would be legal contents for a C string. I can also assume that because you are working with coding and decoding, that the output type is likely unsigned char. If I am correct, then a legal range of characters for an output type of unsigned char is 0-255.
You are not checking the output before sending the value to the printf statement. If the value at the memory address of decoded_seq happens to be 0, (in the range of unsigned char) your program would crash. String functions do not work well with null pointers.
You should verify the return of _decode_string_ sending it to printf
char *decoded_seq = decode_string( encoded_seq, 2, 2);
if(decoded_seq != NULL)
{
...
I'm trying to short the cpu id of my microcontroller (STM32F1).
The cpu id is composed by 3 word ( 3 x 4 bytes). This is the id string built from the 3 word: 980416578761680031125348904
I found a very useful library that do this.
The library is Hashids and there is a C code.
I try to build a test code on PC with "Code Blocks IDE" and the code works.
But when I move the code into the embedded side (Keil v5 IDE), I get an error on strdup() function: "strdup implicit declaration of function".
The problem is related to the strdup function isn't a standard library function and ins't included into string.h.
I will avoid to replace the strdup function with a custom function (that mimic the behaviour of strdup) to avoid memory leak because strdup copy strings using malloc.
Is there a different approach to compress long numbers?
Thanks for the help!
<---Appendix--->
This is the function that uses the strdup.
/* common init */
struct hashids_t *
hashids_init3(const char *salt, size_t min_hash_length, const char *alphabet)
{
struct hashids_t *result;
unsigned int i, j;
size_t len;
char ch, *p;
hashids_errno = HASHIDS_ERROR_OK;
/* allocate the structure */
result = _hashids_alloc(sizeof(struct hashids_t));
if (HASHIDS_UNLIKELY(!result)) {
hashids_errno = HASHIDS_ERROR_ALLOC;
return NULL;
}
/* allocate enough space for the alphabet and its copies */
len = strlen(alphabet) + 1;
result->alphabet = _hashids_alloc(len);
result->alphabet_copy_1 = _hashids_alloc(len);
result->alphabet_copy_2 = _hashids_alloc(len);
if (HASHIDS_UNLIKELY(!result->alphabet || !result->alphabet_copy_1
|| !result->alphabet_copy_2)) {
hashids_free(result);
hashids_errno = HASHIDS_ERROR_ALLOC;
return NULL;
}
/* extract only the unique characters */
result->alphabet[0] = '\0';
for (i = 0, j = 0; i < len; ++i) {
ch = alphabet[i];
if (!strchr(result->alphabet, ch)) {
result->alphabet[j++] = ch;
}
}
result->alphabet[j] = '\0';
/* store alphabet length */
result->alphabet_length = j;
/* check length and whitespace */
if (result->alphabet_length < HASHIDS_MIN_ALPHABET_LENGTH) {
hashids_free(result);
hashids_errno = HASHIDS_ERROR_ALPHABET_LENGTH;
return NULL;
}
if (strchr(result->alphabet, ' ')) {
hashids_free(result);
hashids_errno = HASHIDS_ERROR_ALPHABET_SPACE;
return NULL;
}
/* copy salt */
result->salt = strdup(salt ? salt : HASHIDS_DEFAULT_SALT);
result->salt_length = (unsigned int) strlen(result->salt);
/* allocate enough space for separators */
result->separators = _hashids_alloc((size_t)
(ceil((float)result->alphabet_length / HASHIDS_SEPARATOR_DIVISOR) + 1));
if (HASHIDS_UNLIKELY(!result->separators)) {
hashids_free(result);
hashids_errno = HASHIDS_ERROR_ALLOC;
return NULL;
}
/* non-alphabet characters cannot be separators */
for (i = 0, j = 0; i < strlen(HASHIDS_DEFAULT_SEPARATORS); ++i) {
ch = HASHIDS_DEFAULT_SEPARATORS[i];
if ((p = strchr(result->alphabet, ch))) {
result->separators[j++] = ch;
/* also remove separators from alphabet */
memmove(p, p + 1,
strlen(result->alphabet) - (p - result->alphabet));
}
}
/* store separators length */
result->separators_count = j;
/* subtract separators count from alphabet length */
result->alphabet_length -= result->separators_count;
/* shuffle the separators */
hashids_shuffle(result->separators, result->separators_count,
result->salt, result->salt_length);
/* check if we have any/enough separators */
if (!result->separators_count
|| (((float)result->alphabet_length / (float)result->separators_count)
> HASHIDS_SEPARATOR_DIVISOR)) {
unsigned int separators_count = (unsigned int)ceil(
(float)result->alphabet_length / HASHIDS_SEPARATOR_DIVISOR);
if (separators_count == 1) {
separators_count = 2;
}
if (separators_count > result->separators_count) {
/* we need more separators - get some from alphabet */
int diff = separators_count - result->separators_count;
strncat(result->separators, result->alphabet, diff);
memmove(result->alphabet, result->alphabet + diff,
result->alphabet_length - diff + 1);
result->separators_count += diff;
result->alphabet_length -= diff;
} else {
/* we have more than enough - truncate */
result->separators[separators_count] = '\0';
result->separators_count = separators_count;
}
}
/* shuffle alphabet */
hashids_shuffle(result->alphabet, result->alphabet_length,
result->salt, result->salt_length);
/* allocate guards */
result->guards_count = (unsigned int) ceil((float)result->alphabet_length
/ HASHIDS_GUARD_DIVISOR);
result->guards = _hashids_alloc(result->guards_count + 1);
if (HASHIDS_UNLIKELY(!result->guards)) {
hashids_free(result);
hashids_errno = HASHIDS_ERROR_ALLOC;
return NULL;
}
if (HASHIDS_UNLIKELY(result->alphabet_length < 3)) {
/* take some from separators */
strncpy(result->guards, result->separators, result->guards_count);
memmove(result->separators, result->separators + result->guards_count,
result->separators_count - result->guards_count + 1);
result->separators_count -= result->guards_count;
} else {
/* take them from alphabet */
strncpy(result->guards, result->alphabet, result->guards_count);
memmove(result->alphabet, result->alphabet + result->guards_count,
result->alphabet_length - result->guards_count + 1);
result->alphabet_length -= result->guards_count;
}
/* set min hash length */
result->min_hash_length = min_hash_length;
/* return result happily */
return result;
}
The true question seems to be
Is there a different approach to compress long numbers?
There are many. They differ in several respects, including which bits of the input contribute to the output, how many inputs map to the same output, and what manner of transformations of the input leave the output unchanged.
As a trivial examples, you can compress the input to a single bit by any of these approaches:
Choose the lowest-order bit of the input
Choose the highest-order bit of the input
The output is always 1
etc
Or you can compress to 7 bits by using using the number of 1 bits in the input as the output.
None of those particular options is likely to be of interest to you, of course.
Perhaps you would be more interested in producing 32-bit outputs for your 96-bit inputs. Do note that in that case on average there will be at least 264 possible inputs that map to each possible output. That depends only on the sizes of input and output, not on any details of the conversion.
For example, suppose that you have
uint32_t *cpuid = ...;
pointing to the hardware CPU ID. You can produce a 32-bit value from it that depends on all the bits of the input simply by doing this:
uint32_t cpuid32 = cpuid[0] ^ cpuid[1] ^ cpuid[2];
Whether that would suit your purpose depends on how you intend to use it.
You can easily implement strdup yourself like this:
char* strdup (const char* str)
{
size_t size = strlen(str);
char* result = malloc(size);
if(result != NULL)
{
memcpy(result, str, size+1);
}
return result;
}
That being said, using malloc or strdup on an embedded system is most likely just nonsense practice, see this. Nor would you use float numbers. Overall, that library seems to have been written by a desktop-minded person.
If you are implementing something like for example a chained hash table on an embedded system, you would use a statically allocated memory pool and not malloc. I'd probably go with a non-chained one for that reason (upon duplicates, pick next free spot in the buffer).
Unique device ID register (96 bits) is located under address 0x1FFFF7E8. It is factory programmed and is read-only. You can read it directly without using any other external library. For example:
unsigned int b = *(0x1FFFF7E8);
should give you the first 32 bits (31:0) of the unique device ID. If you want to retrieve a string as in case of the library mentioned, the following should work:
sprintf(id, "%08X%08X%08X", *(0x1FFFF7E8), *(0x1FFFF7E8 + 4), *(0x1FFFF7E8 + 8);
Some additional casting may be required, but generally that's what the library did. Please refer to STM32F1xx Reference Manual (RM0008), section 30.2 for more details. The exact memory location to read from is different in case of Cortex-M4 family of the MCUs.
I am making a C kernel from scratch, and I literally just copied this code off of a website because my code wasn't working so I was confused.
void kmain(void)
{
const char *str = "my first kernel";
char *vidptr = (char*)0xb8000; //video mem begins here.
unsigned int i = 0;
unsigned int j = 0;
/* this loops clears the screen
* there are 25 lines each of 80 columns; each element takes 2 bytes */
while(j < 80 * 25 * 2) {
/* blank character */
vidptr[j] = ' ';
/* attribute-byte - light grey on black screen */
vidptr[j+1] = 0x07;
j = j + 2;
}
j = 0;
/* this loop writes the string to video memory */
while(str[j] != '\0') {
/* the character's ascii */
vidptr[i] = str[j];
/* attribute-byte: give character black bg and light grey fg */
vidptr[i+1] = 0x07;
++j;
i = i + 2;
}
return;
}
When I run my kernel, it prints an S to the screen and nothing else. I know my kernel is booting, because if I do
vidptr[0] = 'h';
vidptr[2] = 'e';
vidptr[4] = 'l';
vidptr[6] = 'l';
vidptr[8] = 'o';
it works as expected. What is happening?
EDIT: It might be something with my code that loads the kernel (might not have set up some of the registers) so I will just look into grub and other things.
Try using the volatile keyword with the variable
Ref page: http://wiki.osdev.org/Printing_To_Screen
// note this example will always write to the top
// line of the screen
void write_string( int colour, const char *string )
{
volatile char *video = (volatile char*)0xB8000;
while( *string != 0 )
{
*video++ = *string++;
*video++ = colour;
}
}
For some reason, if I use char str[] = "blabla"; instead of char *str = "blabla"; it works.
First, have you set the SP before jumping Kernel or before running the function? If you have not, please set them appropriately. In your starting function you should set the stack pointer DS, SS; you can use inline assembly at the beginning of the program. Also instead char * p = "Something" you should use char var [] = "Something", or
char var[10];
var[1] = 'S';
var[2] = 'o';
or
char var[] = { 'S', 'o', 'm', 'e', ..., '\0' } ;
My bootloader establishes the GDT and makes the switcthing to 32 bit mode and jumps (jmp 0x8:0x8000) Here 0x8 is my Code segment address in GDT, 0x10 for the DS, SS; so it jumps to kernel. Before I hadn't set the SS, SP, DS and I could not get it printed so I have written this small code:
[bits 32]
MOV AX, 0x10 ; 0x10 points at the new data selector
MOV DS, eax
MOV ES, AX
MOV FS, AX
MOV GS, AX
MOV SS, AX
MOV eax, 0x200000
MOV esp, eax
and compiled it with nasm and added to beginning of the kernel program manually by using a HEX editor program.