OS Development Series code question

For programming questions that do not fit in the other forums.

Moderator:Moderators

halofreak1990
Posts:92
Joined:Thu May 27, 2010 8:54 pm
Location:Netherlands
OS Development Series code question

Post by halofreak1990 » Tue Jun 15, 2010 9:22 am

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.

User avatar
Mike
Site Admin
Posts:465
Joined:Sat Oct 20, 2007 7:58 pm
Contact:

Re: OS Development Series code question

Post by Mike » Tue Jun 15, 2010 5:47 pm

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.

halofreak1990
Posts:92
Joined:Thu May 27, 2010 8:54 pm
Location:Netherlands

Re: OS Development Series code question

Post by halofreak1990 » Sun Jun 20, 2010 8:57 pm

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.

User avatar
Mike
Site Admin
Posts:465
Joined:Sat Oct 20, 2007 7:58 pm
Contact:

Re: OS Development Series code question

Post by Mike » Mon Jun 21, 2010 12:27 am

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.
Lead Programmer for BrokenThorn Entertainment, Co.
Website: http://www.brokenthorn.com
Email: webmaster@brokenthorn.com

halofreak1990
Posts:92
Joined:Thu May 27, 2010 8:54 pm
Location:Netherlands

Re: OS Development Series code question

Post by halofreak1990 » Mon Jun 21, 2010 8:45 am

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. :cry:
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\

pathos
Moderator
Posts:97
Joined:Thu Jan 10, 2008 6:43 pm
Location:USA

Re: OS Development Series code question

Post by pathos » Mon Jun 21, 2010 1:57 pm

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.
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.

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;
}

halofreak1990
Posts:92
Joined:Thu May 27, 2010 8:54 pm
Location:Netherlands

Re: OS Development Series code question

Post by halofreak1990 » Mon Jun 21, 2010 8:54 pm

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.

halofreak1990
Posts:92
Joined:Thu May 27, 2010 8:54 pm
Location:Netherlands

Re: OS Development Series code question

Post by halofreak1990 » Mon Jul 05, 2010 6:17 pm

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:

Code: Select all

extern "C" int __cdecl _purecall(void)   
{   
    return 0;   
}
which does compile correctly.
You might want to change the _purecall_handler to this one to prevent future issues.

Andyhhp
Moderator
Posts:387
Joined:Tue Oct 23, 2007 10:05 am
Location:127.0.0.1
Contact:

Re: OS Development Series code question

Post by Andyhhp » Tue Jul 06, 2010 11:55 pm

the _purecall_handler doesn't work.
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).

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
The ruby VM source code is the first example of this which comes to mind.


That aside, a page of gochas for people wanting to use C++ from these tutorials would be very useful IMO.

~Andrew
Image

halofreak1990
Posts:92
Joined:Thu May 27, 2010 8:54 pm
Location:Netherlands

Re: OS Development Series code question

Post by halofreak1990 » Thu Jul 08, 2010 9:33 pm

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 of

Code: Select all

#ifdef __cplusplus
extern "C" {
#endif
... //some code here
#ifdef __cplusplus
}
#endif
The ruby VM source code is the first example of this which comes to mind.

That aside, a page of gochas for people wanting to use C++ from these tutorials would be very useful IMO.

~Andrew
I verified, using an older, unmodified Demo21, after applying the extern "C" that it's not just name mangling.
here's the error:

Code: Select all

Error	1	error LNK2001: unresolved external symbol __purecall	Stream.obj	
using

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
}
MSVC is really looking for __purecall (the extra underscore at the beginning is added because of C++), which translates to _purecall() in plain C.
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()

Andyhhp
Moderator
Posts:387
Joined:Tue Oct 23, 2007 10:05 am
Location:127.0.0.1
Contact:

Re: OS Development Series code question

Post by Andyhhp » Thu Jul 08, 2010 11:41 pm

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
Image

halofreak1990
Posts:92
Joined:Thu May 27, 2010 8:54 pm
Location:Netherlands

Re: OS Development Series code question

Post by halofreak1990 » Tue Jul 20, 2010 2:00 pm

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:

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];
}
should be

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;
}
It doesn't affect the OS so far, but it would when one would try and access the BpbExt for additional information.

Andyhhp
Moderator
Posts:387
Joined:Tue Oct 23, 2007 10:05 am
Location:127.0.0.1
Contact:

Re: OS Development Series code question

Post by Andyhhp » Tue Jul 20, 2010 2:27 pm

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
Image

halofreak1990
Posts:92
Joined:Thu May 27, 2010 8:54 pm
Location:Netherlands

Re: OS Development Series code question

Post by halofreak1990 » Tue Jul 20, 2010 5:54 pm

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
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
Moderator
Posts:387
Joined:Tue Oct 23, 2007 10:05 am
Location:127.0.0.1
Contact:

Re: OS Development Series code question

Post by Andyhhp » Tue Jul 20, 2010 6:04 pm

Try giving yourself more stack space?
Image

Post Reply