OS Development Series code question
Moderator:Moderators
-
- Posts:92
- Joined:Thu May 27, 2010 8:54 pm
- Location:Netherlands
I've been going through the code provided in the tutorials, not only to learn, but also to eliminate those pesky warnings (I like warnings as much as errors) and I can't help but wonder why functions like isascii() are defined twice, with a different body.
Re: OS Development Series code question
Hello,
It would seem a lot of those routines are defined in ctype.c. This was left over from legacy code. ctype.c is no longer needed and can be removed. (Its not being compiled anyways). isascii() has also been defined twice in ctype.h, this is an error and not intentional. Thank you for letting us know, it will be corrected.
It would seem a lot of those routines are defined in ctype.c. This was left over from legacy code. ctype.c is no longer needed and can be removed. (Its not being compiled anyways). isascii() has also been defined twice in ctype.h, this is an error and not intentional. Thank you for letting us know, it will be corrected.
-
- Posts:92
- Joined:Thu May 27, 2010 8:54 pm
- Location:Netherlands
Re: OS Development Series code question
In don't know if it's a common error, but trying to read a txt file from the floppy hangs my test system, while the tutorial works flawlessly in VPC. This is with chapter 22.
I thought; maybe I did something wrong, I.E. modified the wrong section of code, so I took an unmodified chapter 21 (yes, the previous one) and tried that out.
This results in an overview of sector 0, as I entered it, but the data returned is almost only 0x00. This ain't what's supposed to be in sector 0, right?
Seems to me like reading from the floppy drive on real hardware returns garbage, making the later chapter (22) hang, because it doesn't recieve anything it can convert to ASCII characters.
Weird thing is, in VPC it does exactly what it's supposed to do.
Also, placing the kernel anywhere else than the root directory means you can't boot.
And because the "Corrupt kernel" message thingy has its await keypress lines commented out, the system reboots instantly, leaving the user with no reason for failure.
My second stage has those lines uncommented, so I was warned about the fact it couldn't find my kernel (located in a directory called "boot"), but I still find it strange that the second stage bootloader can't find my kernel using the FindFile function.
I thought; maybe I did something wrong, I.E. modified the wrong section of code, so I took an unmodified chapter 21 (yes, the previous one) and tried that out.
This results in an overview of sector 0, as I entered it, but the data returned is almost only 0x00. This ain't what's supposed to be in sector 0, right?
Seems to me like reading from the floppy drive on real hardware returns garbage, making the later chapter (22) hang, because it doesn't recieve anything it can convert to ASCII characters.
Weird thing is, in VPC it does exactly what it's supposed to do.
Also, placing the kernel anywhere else than the root directory means you can't boot.
And because the "Corrupt kernel" message thingy has its await keypress lines commented out, the system reboots instantly, leaving the user with no reason for failure.
My second stage has those lines uncommented, so I was warned about the fact it couldn't find my kernel (located in a directory called "boot"), but I still find it strange that the second stage bootloader can't find my kernel using the FindFile function.
Re: OS Development Series code question
Hello,
The demo code provided in chapter 22 has some issues with the memory management software provided from earlier chapters. A new release of chapter 22's demo with the fixes are described in this thread. A direct link to the new demo is here (SysCore2.zip).
Please let us know if this updated version works on your test machine. The series is currently being updated to reflect these new changes and should be finished in about a week.
The demo code provided in chapter 22 has some issues with the memory management software provided from earlier chapters. A new release of chapter 22's demo with the fixes are described in this thread. A direct link to the new demo is here (SysCore2.zip).
Please let us know if this updated version works on your test machine. The series is currently being updated to reflect these new changes and should be finished in about a week.
Lead Programmer for BrokenThorn Entertainment, Co.
Website: http://www.brokenthorn.com
Email: webmaster@brokenthorn.com
Website: http://www.brokenthorn.com
Email: webmaster@brokenthorn.com
-
- Posts:92
- Joined:Thu May 27, 2010 8:54 pm
- Location:Netherlands
Re: OS Development Series code question
I tried it out, and it hangs, just like my own version.
It's like (I don't remember his name) said; "when reading a non-existing file, it loops indefinately." Though the file I'm attempting to read does exist.
My own OS already uses the suggested fix in the PMM and VMM init; it doesn't fix the error on real hardware.
I'm gonna try to implement a PIO read routine for the FFD and see if that works. If it doesn't... well, then I don't know what will.
If it does work, I'll need to take a good look at the DMA routine to see if I can help you locate the problem.
Also, I've noticed the FAT12 project uses absolute paths instead of relative ones, which produces errors.
The Additional Include Directories need to be
It's like (I don't remember his name) said; "when reading a non-existing file, it loops indefinately." Though the file I'm attempting to read does exist.
My own OS already uses the suggested fix in the PMM and VMM init; it doesn't fix the error on real hardware.

I'm gonna try to implement a PIO read routine for the FFD and see if that works. If it doesn't... well, then I don't know what will.
If it does work, I'll need to take a good look at the DMA routine to see if I can help you locate the problem.
Also, I've noticed the FAT12 project uses absolute paths instead of relative ones, which produces errors.
The Additional Include Directories need to be
Code: Select all
..\Kernel\;..\Include\
Re: OS Development Series code question
I had this problem when trying to read a file that existed inside a subdirectory. I can't remember all what I changed, but I did change this. It may have been the only thing, so it may help you.halofreak1990 wrote:I tried it out, and it hangs, just like my own version.
It's like (I don't remember his name) said; "when reading a non-existing file, it loops indefinately." Though the file I'm attempting to read does exist.
This is fsysFatOpenSubDir inside fat12.cpp:
Code: Select all
FILE fsysFatOpenSubDir(FILE kFile, const char* filename)
{
FILE file;
char DosFileName[11];
ToDosFileName(filename, DosFileName, 11);
DosFileName[11]=0;
while(!kFile.eof) // read directory
{
unsigned char buf[512];
fsysFatRead(&file, buf, 512);
PDIRECTORY pkDir = (PDIRECTORY) buf; // set directory
for(unsigned int i = 0; i < 16; i++)
{
if(pkDir->Filename[0] == 0xE5)
{
//File has been deleted.
}
if(pkDir->Filename[0] == 0x00)
{
//No entries past this point.
goto exitWhile;
}
char name[11];
memcpy(name, pkDir->Filename, 11);
name[11]=0;
if (strcmp(name, DosFileName) == 0)
{
file.id = 0;
file.currentCluster = pkDir->FirstCluster;
file.fileLength = pkDir->FileSize;
file.eof = 0;
file.fileLength = pkDir->FileSize;
if (pkDir->Attrib == 0x10)
{
file.flags = FS_DIRECTORY;
}
else
{
file.flags = FS_FILE;
}
return file;
}
pkDir++;
}
}
exitWhile:
file.flags = FS_INVALID;
return file;
}
-
- Posts:92
- Joined:Thu May 27, 2010 8:54 pm
- Location:Netherlands
Re: OS Development Series code question
Unfortunately, that doesn't help me.
Through a couple of DebugPrintf() functions in the FAT12 driver, I found out the cause; the values read from the bootsector are rubbish.
My OS tells me I have:
51136 Sectors
24404 FAT Size
45 Root entries
A root size of 0
And, last but not least... a root offset of... dun dun dun... 39014641
No wonder my OS hangs when trying to read anything
But why VPC works like a charm is way beyond me.
EDIT: I added the cmd_read_sect () function from chapter 20, and it reads the bootsector just fine.
Also, now I've recompiled the kernel to include this function, I get different values from the bootsector, though still wrong:
17803 Sectors
29837 FAT Size
0 Root entries
A root size of 0
and the root offset is now 1
Somehow, when automatically reading the bootsector when initializing the FAT12 driver, it gets garbage, or only part of the bootsector in the bootsector struct.
cmd_read_sect() always returns the same data, even in consecutive tries.
What bugs me is that the FAT12 init uses the same flpydsk_read_sector (0); command.
Seems as though the system can't properly dump that data into the bootsector struct.
Once every couple of tries, I can read the volume label and even the boot signature in the bootsector structure, though the FAT data is still corrupt.
So it does work, to a degree.
Through a couple of DebugPrintf() functions in the FAT12 driver, I found out the cause; the values read from the bootsector are rubbish.
My OS tells me I have:
51136 Sectors
24404 FAT Size
45 Root entries
A root size of 0
And, last but not least... a root offset of... dun dun dun... 39014641
No wonder my OS hangs when trying to read anything
But why VPC works like a charm is way beyond me.
EDIT: I added the cmd_read_sect () function from chapter 20, and it reads the bootsector just fine.
Also, now I've recompiled the kernel to include this function, I get different values from the bootsector, though still wrong:
17803 Sectors
29837 FAT Size
0 Root entries
A root size of 0
and the root offset is now 1
Somehow, when automatically reading the bootsector when initializing the FAT12 driver, it gets garbage, or only part of the bootsector in the bootsector struct.
cmd_read_sect() always returns the same data, even in consecutive tries.
What bugs me is that the FAT12 init uses the same flpydsk_read_sector (0); command.
Seems as though the system can't properly dump that data into the bootsector struct.
Once every couple of tries, I can read the volume label and even the boot signature in the bootsector structure, though the FAT data is still corrupt.
So it does work, to a degree.
-
- Posts:92
- Joined:Thu May 27, 2010 8:54 pm
- Location:Netherlands
Re: OS Development Series code question
Another thing worth mentioning...
the _purecall_handler doesn't work.
Even though it'll be a while until I'll be able to do multitasking, I've gone ahead and created a DLL project, (mscorlib.dll) which uses several interface classes with pure virtual functions to force their implementation.
When compiling, the linker complained about not being able to resolve __purecall
So, I googled a bit, and found this code:which does compile correctly.
You might want to change the _purecall_handler to this one to prevent future issues.
the _purecall_handler doesn't work.
Even though it'll be a while until I'll be able to do multitasking, I've gone ahead and created a DLL project, (mscorlib.dll) which uses several interface classes with pure virtual functions to force their implementation.
When compiling, the linker complained about not being able to resolve __purecall
So, I googled a bit, and found this code:
Code: Select all
extern "C" int __cdecl _purecall(void)
{
return 0;
}
You might want to change the _purecall_handler to this one to prevent future issues.
Re: OS Development Series code question
That is because you are using C++ and not C. C++ does name mangling meaning that "int __cdecel _purecall_handler(void)" will appear to the linker as "?_purecall_handler@@YAXXZ" or similar (its compiler depdentent, and even different between different versions of the same compiler - its a nightmare for linking complicated object files).the _purecall_handler doesn't work.
extern "C" is an instruction for C++ to prevent name mangling meaning that the linker can find the symbol at linktime.
This is the reason why C/C++ compatable source code has liberal sprinklings of
Code: Select all
#ifdef __cplusplus
extern "C" {
#endif
... //some code here
#ifdef __cplusplus
}
#endif
That aside, a page of gochas for people wanting to use C++ from these tutorials would be very useful IMO.
~Andrew

-
- Posts:92
- Joined:Thu May 27, 2010 8:54 pm
- Location:Netherlands
Re: OS Development Series code question
I verified, using an older, unmodified Demo21, after applying the extern "C" that it's not just name mangling.Andyhhp wrote:C++ does name mangling meaning that "int __cdecel _purecall_handler(void)" will appear to the linker as "?_purecall_handler@@YAXXZ" or similar (its compiler depdentent, and even different between different versions of the same compiler - its a nightmare for linking complicated object files).
extern "C" is an instruction for C++ to prevent name mangling meaning that the linker can find the symbol at linktime.
This is the reason why C/C++ compatable source code has liberal sprinklings ofThe ruby VM source code is the first example of this which comes to mind.Code: Select all
#ifdef __cplusplus extern "C" { #endif ... //some code here #ifdef __cplusplus } #endif
That aside, a page of gochas for people wanting to use C++ from these tutorials would be very useful IMO.
~Andrew
here's the error:
Code: Select all
Error 1 error LNK2001: unresolved external symbol __purecall Stream.obj
Code: Select all
extern "C" int __cdecl _purecall_handler()
{
// for now, halt the system 'til we have a way to display error
for (;;);
// print error message here
}
Also, I've not yet come across a pure virtual function in C (does it even exists?), so I cannot verify the OsDev _purecall_handler()
Re: OS Development Series code question
You make a good point. No such thing as a purecall exists in C - there is no concept of classes or inheritence.
Without looking into it futher, its possible that it is compiler specific.
~Andrew
Without looking into it futher, its possible that it is compiler specific.
~Andrew

-
- Posts:92
- Joined:Thu May 27, 2010 8:54 pm
- Location:Netherlands
Re: OS Development Series code question
I took a look at the bootsector of my floppy disk with a Hex-editor, and it makes me wonder why on Earth it won't place the correct values into the bpb structure.
Every value is what it's supposed to be, yet the values in the struct are garbage.
This appears to be caused by the exceptionally weird fact that the flpydsk_read_sector () function refuses to read the first sector when called by the FAT12 driver. Yet, when called by other code later on, it works fine. Trying to read the Bootsector after the other read makes the OEM label show up correctly as well as the boot signature at the end of the sector, but anything inbetween is still garbage.
On a side note: the BpbExt struct is wrong:should be
It doesn't affect the OS so far, but it would when one would try and access the BpbExt for additional information.
Every value is what it's supposed to be, yet the values in the struct are garbage.
This appears to be caused by the exceptionally weird fact that the flpydsk_read_sector () function refuses to read the first sector when called by the FAT12 driver. Yet, when called by other code later on, it works fine. Trying to read the Bootsector after the other read makes the OEM label show up correctly as well as the boot signature at the end of the sector, but anything inbetween is still garbage.
On a side note: the BpbExt struct is wrong:
Code: Select all
typedef struct _BIOS_PARAMATER_BLOCK_EXT {
uint32_t SectorsPerFat32;
uint16_t Flags;
uint16_t Version;
uint32_t RootCluster;
uint16_t InfoCluster;
uint16_t BackupBoot;
uint16_t Reserved[6];
}
Code: Select all
typedef struct _BIOS_PARAMATER_BLOCK_EXT {
uint8_t DriveNumber;
uint8_t Reserved;
uint8_t ExtBootSig;
uint32_t VolSerialNum;
uint8_t VolumeLabel[11];
uint64_t FileSystemType;
}
Re: OS Development Series code question
When you are working with structures like that, ensure that they are packed structures.
Compilers will typically word-align all items in a structure to make memory accesses faster. When you are looking for a specific bit pattern on disk, this makes things wrong.
That might explain why junk is being written.
~Andrew
Compilers will typically word-align all items in a structure to make memory accesses faster. When you are looking for a specific bit pattern on disk, this makes things wrong.
That might explain why junk is being written.
~Andrew

-
- Posts:92
- Joined:Thu May 27, 2010 8:54 pm
- Location:Netherlands
Re: OS Development Series code question
The structures are already packed to 1 byte alignment, heck, the data in the Bpb structure is correct: after some checking, I found out that the data gets corrupted once it is copied into the _MOUNT_INFO struct, when the values are converted to uint32_t, though that shouldn't matter, since uint32_t is larger than the uint16_t used in the Bpb struct. Also, I need to do a read (using the chapter 21 fdd read, which outputs the contents of the sector in hex) before the data displayed in the Bpb struct becomes valid. This makes me think there's a memory overlap somewhere.Andyhhp wrote:When you are working with structures like that, ensure that they are packed structures.
Compilers will typically word-align all items in a structure to make memory accesses faster. When you are looking for a specific bit pattern on disk, this makes things wrong.
That might explain why junk is being written.
~Andrew