Previous commit was a blunder. This commit setups up Malloc proper and includes a working string concat.
This commit is contained in:
@@ -0,0 +1,9 @@
|
|||||||
|
#ifndef BUILD_NUMBER
|
||||||
|
#define BUILD_NUMBER "48"
|
||||||
|
#endif
|
||||||
|
#ifndef VERSION_STR
|
||||||
|
#define VERSION_STR "0.0.2.48 - Sun Jan 6 21:40:38 CST 2019"
|
||||||
|
#endif
|
||||||
|
#ifndef VERSION_STR_SHORT
|
||||||
|
#define VERSION_STR_SHORT "0.0.2.48"
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
#ifndef __MEMORYMANAGER_H
|
||||||
|
#define __MEMORYMANAGER_H
|
||||||
|
|
||||||
|
#include "system.h"
|
||||||
|
|
||||||
|
typedef struct MemoryChunk
|
||||||
|
{
|
||||||
|
struct MemoryChunk* Prev;
|
||||||
|
struct MemoryChunk* Next;
|
||||||
|
size_t Size;
|
||||||
|
bool Allocated;
|
||||||
|
};
|
||||||
|
|
||||||
|
void MemoryManager(size_t start, size_t size);
|
||||||
|
|
||||||
|
void* Malloc(size_t size);
|
||||||
|
|
||||||
|
void Free(void* ptr);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
#ifndef __PCI_H
|
||||||
|
#define __PCI_H
|
||||||
|
|
||||||
|
#include "system.h"
|
||||||
|
|
||||||
|
typedef struct DeviceDescriptor
|
||||||
|
{
|
||||||
|
uint32_t PortBase;
|
||||||
|
uint32_t Interrupt;
|
||||||
|
uint16_t Bus;
|
||||||
|
uint16_t Device;
|
||||||
|
uint16_t Function;
|
||||||
|
|
||||||
|
uint16_t VendorId;
|
||||||
|
uint16_t DeviceId;
|
||||||
|
|
||||||
|
uint8_t ClassId;
|
||||||
|
uint8_t SubClassId;
|
||||||
|
uint8_t InterfaceId;
|
||||||
|
|
||||||
|
uint8_t Revision;
|
||||||
|
};
|
||||||
|
|
||||||
|
uint32_t Read(uint16_t busNumber, uint16_t deviceNumber, uint16_t functionNumber, uint32_t registerOffset);
|
||||||
|
|
||||||
|
void Write(uint16_t busNumber, uint16_t deviceNumber, uint16_t functionNumber, uint32_t registerOffset, uint32_t value);
|
||||||
|
|
||||||
|
bool DeviceHasFunctions(uint16_t bus, uint16_t device);
|
||||||
|
|
||||||
|
void EnumPCISubsystem(void);
|
||||||
|
|
||||||
|
struct DeviceDescriptor GetDeviceDescriptor(uint16_t busNumber, uint16_t deviceNumber, uint16_t functionNumber);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
#ifndef __PORT_H
|
||||||
|
#define __PORT_H
|
||||||
|
|
||||||
|
#include "system.h"
|
||||||
|
|
||||||
|
uint8_t Read8Bit(uint16_t portNumber);
|
||||||
|
void Write8Bit(uint16_t portNumber, uint8_t data);
|
||||||
|
|
||||||
|
uint16_t Read16Bit(uint16_t portNumber);
|
||||||
|
void Write16Bit(uint16_t portNumber, uint16_t data);
|
||||||
|
|
||||||
|
uint32_t Read32Bit(uint16_t portNumber);
|
||||||
|
void Write32Bit(uint16_t portNumber, uint32_t data);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
#!sh
|
||||||
|
# FILE: make_buildnum.sh
|
||||||
|
#version="`sed 's/^ *//' major_version`"
|
||||||
|
version="0.0.2."
|
||||||
|
old="`sed 's/^ *//' build.number`"
|
||||||
|
old=$(($old + 1))
|
||||||
|
echo $old > build.number
|
||||||
|
#echo $old | bc > build.number.temp
|
||||||
|
#mv build.number.temp build.number
|
||||||
|
#versión..
|
||||||
|
#echo "$version`sed 's/^ *//' build.number` - `date`" > version.number
|
||||||
|
#header
|
||||||
|
echo "#ifndef BUILD_NUMBER" > include/buildnumber.h
|
||||||
|
echo "#define BUILD_NUMBER \"`sed 's/^ *//' build.number`\"" >> include/buildnumber.h
|
||||||
|
echo "#endif" >> include/buildnumber.h
|
||||||
|
|
||||||
|
echo "#ifndef VERSION_STR" >> include/buildnumber.h
|
||||||
|
echo "#define VERSION_STR \"$version`sed 's/^ *//' build.number` - `date`\"" >> include/buildnumber.h
|
||||||
|
echo "#endif" >> include/buildnumber.h
|
||||||
|
|
||||||
|
echo "#ifndef VERSION_STR_SHORT" >> include/buildnumber.h
|
||||||
|
echo "#define VERSION_STR_SHORT \"$version`sed 's/^ *//' build.number`\"" >> include/buildnumber.h
|
||||||
|
echo "#endif" >> include/buildnumber.h
|
||||||
|
|
||||||
|
#echo "#ifndef COMPILE_DATE" >> include/buildnumber.h
|
||||||
|
#echo "#define COMPILE_DATE \"`sed 's/^ *//' date`\"" >> include/buildnumber.h
|
||||||
|
#echo "#endif" >> include/buildnumber.h
|
||||||
+185
@@ -0,0 +1,185 @@
|
|||||||
|
#include "../include/system.h"
|
||||||
|
#include "../include/gdt.h"
|
||||||
|
#include "../include/idt.h"
|
||||||
|
#include "../include/scrn.h"
|
||||||
|
#include "../include/shell.h"
|
||||||
|
#include "../include/port.h"
|
||||||
|
#include "../include/buildnumber.h"
|
||||||
|
#include "../include/pci.h"
|
||||||
|
#include "../include/memorymanager.h"
|
||||||
|
|
||||||
|
unsigned char *memcpy(unsigned char *dest, const unsigned char *src, int count)
|
||||||
|
{
|
||||||
|
/* Add code here to copy 'count' bytes of data from 'src' to
|
||||||
|
* 'dest', finally return 'dest' */
|
||||||
|
const char *sp = (const char *)src;
|
||||||
|
char *dp = (char *)dest;
|
||||||
|
for(; count != 0; count--) *dp++ = *sp++;
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char *memset(unsigned char *dest, unsigned char val, int count)
|
||||||
|
{
|
||||||
|
/* Add code here to set 'count' bytes in 'dest' to 'val'.
|
||||||
|
* Again, return 'dest' */
|
||||||
|
char *temp = (char *)dest;
|
||||||
|
for( ; count != 0; count--) *temp++ = val;
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned short *memsetw(unsigned short *dest, unsigned short val, int count)
|
||||||
|
{
|
||||||
|
/* Same as above, but this time, we're working with a 16-bit
|
||||||
|
* 'val' and dest pointer. Your code can be an exact copy of
|
||||||
|
* the above, provided that your local variables if any, are
|
||||||
|
* unsigned short */
|
||||||
|
unsigned short *temp = (unsigned short *)dest;
|
||||||
|
for( ; count != 0; count--) *temp++ = val;
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
int strlen(const char *str)
|
||||||
|
{
|
||||||
|
/* This loops through character array 'str', returning how
|
||||||
|
* many characters it needs to check before it finds a 0.
|
||||||
|
* In simple words, it returns the length in bytes of a string */
|
||||||
|
//size_t retval;
|
||||||
|
unsigned int retval;
|
||||||
|
for(retval = 0; *str != '\0'; str++) retval++;
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool strcmp(char* str1, char* str2)
|
||||||
|
{
|
||||||
|
int len1 = strlen(str1);
|
||||||
|
int len2 = strlen(str2);
|
||||||
|
|
||||||
|
if(len1 != len2) return false;
|
||||||
|
|
||||||
|
for(int i = len1; i >= 0; i--) if(str1[i] != str2[i]) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//Code reference:
|
||||||
|
//http://www.strudel.org.uk/itoa/
|
||||||
|
char* int_to_string(int value, int base)
|
||||||
|
{
|
||||||
|
static char buf[32] = {0};
|
||||||
|
|
||||||
|
if(value == 0)
|
||||||
|
{
|
||||||
|
buf[0] = '0';
|
||||||
|
return &buf[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
int i = 30;
|
||||||
|
|
||||||
|
for(; value && i; --i, value /= base)
|
||||||
|
{
|
||||||
|
buf[i] = "0123456789ABCDEF"[value % base];
|
||||||
|
}
|
||||||
|
|
||||||
|
return &buf[i+1];
|
||||||
|
}
|
||||||
|
|
||||||
|
//Not working
|
||||||
|
unsigned char strconcat(unsigned char *dest, unsigned char* src)
|
||||||
|
{
|
||||||
|
int dest_length = strlen(dest);
|
||||||
|
int src_length = strlen(src);
|
||||||
|
unsigned char* buffer = (unsigned char*)Malloc(dest_length + src_length + 1);
|
||||||
|
|
||||||
|
for(uint32_t i = 0; i < dest_length; i++)
|
||||||
|
{
|
||||||
|
*buffer++ = dest[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
for(uint32_t j = 0; j < src_length; j++)
|
||||||
|
{
|
||||||
|
*buffer++ = src[j];
|
||||||
|
}
|
||||||
|
*buffer++ = '\0';
|
||||||
|
|
||||||
|
return *buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We will use this later on for reading from the I/O ports to get data
|
||||||
|
* from devices such as the keyboard. We are using what is called
|
||||||
|
* 'inline assembly' in these routines to actually do the work */
|
||||||
|
unsigned char inportb (unsigned short _port)
|
||||||
|
{
|
||||||
|
unsigned char rv;
|
||||||
|
__asm__ __volatile__ ("inb %1, %0" : "=a" (rv) : "dN" (_port));
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We will use this to write to I/O ports to send bytes to devices. This
|
||||||
|
* will be used in the next tutorial for changing the textmode cursor
|
||||||
|
* position. Again, we use some inline assembly for the stuff that simply
|
||||||
|
* cannot be done in C */
|
||||||
|
void outportb (unsigned short _port, unsigned char _data)
|
||||||
|
{
|
||||||
|
__asm__ __volatile__ ("outb %1, %0" : : "dN" (_port), "a" (_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is a very simple main() function. All it does is sit in an
|
||||||
|
* infinite loop. This will be like our 'idle' loop */
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
/* You would add commands after here */
|
||||||
|
init_video();
|
||||||
|
puts("Video initialized.\n");
|
||||||
|
gdt_install();
|
||||||
|
puts("Global Descriptor Table initialized.\n");
|
||||||
|
|
||||||
|
size_t heap = 10 * 1024 * 1024;
|
||||||
|
MemoryManager(heap, heap * 30 * 1024);
|
||||||
|
puts("heap: 0x");
|
||||||
|
puts(int_to_string(heap, 16));
|
||||||
|
|
||||||
|
void* allocated = Malloc(2048);
|
||||||
|
puts("\nAllocated: 0x");
|
||||||
|
puts(int_to_string(allocated, 16));
|
||||||
|
puts("\n");
|
||||||
|
|
||||||
|
void* al = Malloc(3096);
|
||||||
|
puts("\nAllocated: 0x");
|
||||||
|
puts(int_to_string(al, 16));
|
||||||
|
puts("\n");
|
||||||
|
|
||||||
|
idt_install();
|
||||||
|
puts("Interrupt Descriptor Table initialized.\n");
|
||||||
|
isrs_install();
|
||||||
|
puts("Interrupt Service Routines installed.\n");
|
||||||
|
irq_install();
|
||||||
|
__asm__ __volatile__ ("sti");
|
||||||
|
puts("Interrupt Requests now allowed.\n");
|
||||||
|
//puts("Probing PCI subsystem for devices.\n");
|
||||||
|
//EnumPCISubsystem();
|
||||||
|
//puts("Finished probing PCI subsystem.\n");
|
||||||
|
//timer_install();
|
||||||
|
//puts("Installed Timer.\n");
|
||||||
|
kb_install();
|
||||||
|
puts("Keyboard installed.\n");
|
||||||
|
puts("SDOS Version ");
|
||||||
|
puts(VERSION_STR_SHORT);
|
||||||
|
puts(" Initialized.\n");
|
||||||
|
puts("Compile Date ");
|
||||||
|
puts(__DATE__);
|
||||||
|
puts("\n");
|
||||||
|
puts(strconcat("Hello ", "World!\n"));
|
||||||
|
//puts(__DATE__);
|
||||||
|
//puts("\n");
|
||||||
|
//puts(__TIME__);
|
||||||
|
//puts("\n");
|
||||||
|
run_shell();
|
||||||
|
//puts(&__BUILD_DATE);
|
||||||
|
//puts(&__BUILD_NUMBER);
|
||||||
|
//puts("Divide by zero check:\n");
|
||||||
|
//puts(5 / 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void idle()
|
||||||
|
{
|
||||||
|
__asm__ __volatile__ ("hlt");
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
#include "../include/memorymanager.h"
|
||||||
|
#include "../include/system.h"
|
||||||
|
|
||||||
|
static struct MemoryChunk* First;
|
||||||
|
|
||||||
|
struct MemoryManager* ActiveMemoryManager = {0};
|
||||||
|
|
||||||
|
void MemoryManager(size_t start, size_t size)
|
||||||
|
{
|
||||||
|
if(size < sizeof(struct MemoryChunk))
|
||||||
|
{
|
||||||
|
First = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
First = (struct MemoryChunk*) start;
|
||||||
|
|
||||||
|
First->Allocated = false;
|
||||||
|
First->Prev = 0;
|
||||||
|
First->Next = 0;
|
||||||
|
First->Size = size - sizeof(struct MemoryChunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* Malloc(size_t size)
|
||||||
|
{
|
||||||
|
struct MemoryChunk *freeChunk = 0;
|
||||||
|
|
||||||
|
for(struct MemoryChunk* chunk = First; chunk != 0 && freeChunk == 0; chunk = chunk->Next)
|
||||||
|
{
|
||||||
|
if(chunk->Size > size && !chunk->Allocated)
|
||||||
|
freeChunk = chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(freeChunk == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if(freeChunk->Size >= size + sizeof(struct MemoryChunk))
|
||||||
|
{
|
||||||
|
struct MemoryChunk* temp = (struct MemoryChunk*)((size_t)freeChunk + sizeof(struct MemoryChunk) + size);
|
||||||
|
|
||||||
|
temp->Allocated = false;
|
||||||
|
temp->Size = freeChunk->Size - size - sizeof(struct MemoryChunk);
|
||||||
|
temp->Prev = freeChunk;
|
||||||
|
temp->Next = freeChunk->Next;
|
||||||
|
|
||||||
|
if(temp->Next != 0)
|
||||||
|
temp->Next->Prev = temp;
|
||||||
|
|
||||||
|
freeChunk->Size = size;
|
||||||
|
freeChunk->Next = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
freeChunk->Allocated = true;
|
||||||
|
|
||||||
|
return (void*)(((size_t) freeChunk) + sizeof(struct MemoryChunk));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Free(void* ptr)
|
||||||
|
{
|
||||||
|
struct MemoryChunk* chunk = (struct MemoryChunk*)((size_t) ptr - sizeof(struct MemoryChunk));
|
||||||
|
|
||||||
|
chunk->Allocated = false;
|
||||||
|
|
||||||
|
if(chunk->Prev != 0 && !chunk->Prev->Allocated)
|
||||||
|
{
|
||||||
|
chunk->Prev->Next = chunk->Next;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
#include "../include/pci.h"
|
||||||
|
#include "../include/system.h"
|
||||||
|
#include "../include/port.h"
|
||||||
|
#include "../include/scrn.h"
|
||||||
|
|
||||||
|
uint32_t Read(uint16_t busNumber, uint16_t deviceNumber, uint16_t functionNumber, uint32_t registerOffset)
|
||||||
|
{
|
||||||
|
puts("Read ");
|
||||||
|
puts(int_to_string(functionNumber, 10));
|
||||||
|
puts("\n");
|
||||||
|
uint32_t id =
|
||||||
|
0x1 << 31
|
||||||
|
| ((busNumber & 0xFF) << 16)
|
||||||
|
| ((deviceNumber & 0x1F) << 11)
|
||||||
|
| ((functionNumber & 0x07) << 8)
|
||||||
|
| (registerOffset & 0xFC);
|
||||||
|
Write32Bit(0xCF8, id);
|
||||||
|
uint32_t result = Read32Bit(0xCFC);
|
||||||
|
return result >> (8 * (registerOffset %4));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Write(uint16_t busNumber, uint16_t deviceNumber, uint16_t functionNumber, uint32_t registerOffset, uint32_t value)
|
||||||
|
{
|
||||||
|
uint32_t id =
|
||||||
|
0x1 << 31
|
||||||
|
| ((busNumber & 0xFF) << 16)
|
||||||
|
| ((deviceNumber & 0x1F) << 11)
|
||||||
|
| ((functionNumber & 0x07) << 8)
|
||||||
|
| (registerOffset & 0xFC);
|
||||||
|
Write32Bit(0xCF8, id);
|
||||||
|
Write32Bit(0xCFC, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DeviceHasFunctions(uint16_t bus, uint16_t device)
|
||||||
|
{
|
||||||
|
//Checks the 7th bit to determine if the device has a function.
|
||||||
|
return Read(bus, device, 0, 0x0E) & (1 << 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnumPCISubsystem()
|
||||||
|
{
|
||||||
|
for(int bus = 0; bus < 8; bus++)
|
||||||
|
{
|
||||||
|
for(int device = 0; device < 32; device++)
|
||||||
|
{
|
||||||
|
int functionCount = DeviceHasFunctions(bus, device) ? 8 : 1;//8 or 1
|
||||||
|
|
||||||
|
for(int function = 0; function < functionCount; function++)
|
||||||
|
{
|
||||||
|
//puts(", Function ");
|
||||||
|
//puts(int_to_string(function, 16));
|
||||||
|
struct DeviceDescriptor dev = {0};
|
||||||
|
dev = GetDeviceDescriptor(bus, device, function);
|
||||||
|
|
||||||
|
if(dev.VendorId == 0x0000 || dev.VendorId == 0xFFFF)
|
||||||
|
break;//Break loop, no more funcitons.
|
||||||
|
//puts("PCI BUS ");
|
||||||
|
//puts(int_to_string(bus, 16));
|
||||||
|
//puts("Device ");
|
||||||
|
//puts(int_to_string(device, 16));
|
||||||
|
//puts(" = Vendor ");
|
||||||
|
//puts(int_to_string(dev.VendorId, 16));
|
||||||
|
//puts(", Device ");
|
||||||
|
//puts(int_to_string(dev.DeviceId, 16));
|
||||||
|
//puts(" Class ");
|
||||||
|
//puts(int_to_string(dev.ClassId, 16));
|
||||||
|
//puts("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DeviceDescriptor GetDeviceDescriptor(uint16_t busNumber, uint16_t deviceNumber, uint16_t functionNumber)
|
||||||
|
{
|
||||||
|
struct DeviceDescriptor result;
|
||||||
|
|
||||||
|
result.Bus = busNumber;
|
||||||
|
result.Device = deviceNumber;
|
||||||
|
result.Function = functionNumber;
|
||||||
|
|
||||||
|
result.VendorId = Read(busNumber, deviceNumber, functionNumber, 0x00);
|
||||||
|
result.DeviceId = Read(busNumber, deviceNumber, functionNumber, 0x02);
|
||||||
|
|
||||||
|
result.ClassId = Read(busNumber, deviceNumber, functionNumber, 0x0B);
|
||||||
|
result.SubClassId = Read(busNumber, deviceNumber, functionNumber, 0x0A);
|
||||||
|
result.InterfaceId = Read(busNumber, deviceNumber, functionNumber, 0x09);
|
||||||
|
|
||||||
|
result.Revision = Read(busNumber, deviceNumber, functionNumber, 0x08);
|
||||||
|
result.Interrupt = Read(busNumber, deviceNumber, functionNumber, 0x3C);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
+35
@@ -0,0 +1,35 @@
|
|||||||
|
#include "../include/port.h"
|
||||||
|
#include "../include/system.h"
|
||||||
|
|
||||||
|
uint8_t Read8Bit(uint16_t portNumber)
|
||||||
|
{
|
||||||
|
uint8_t result;
|
||||||
|
__asm__ volatile("inb %1, %0" : "=a" (result) : "Nd" (portNumber));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
void Write8Bit(uint16_t portNumber, uint8_t data)
|
||||||
|
{
|
||||||
|
__asm__ volatile("outb %0, %1" : : "a" (data), "Nd" (portNumber));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t Read16Bit(uint16_t portNumber)
|
||||||
|
{
|
||||||
|
uint16_t result;
|
||||||
|
__asm__ volatile("inw %1, %0" : "=a" (result) : "Nd" (portNumber));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
void Write16Bit(uint16_t portNumber, uint16_t data)
|
||||||
|
{
|
||||||
|
__asm__ volatile("outb %0, %1" : : "a" (data), "Nd" (portNumber));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t Read32Bit(uint16_t portNumber)
|
||||||
|
{
|
||||||
|
uint32_t result;
|
||||||
|
__asm__ volatile("inl %1, %0" : "=a" (result) : "Nd" (portNumber));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
void Write32Bit(uint16_t portNumber, uint32_t data)
|
||||||
|
{
|
||||||
|
__asm__ volatile("outb %0, %1" : : "a" (data), "Nd" (portNumber));
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user