OSDev.org

The Place to Start for Operating System Developers
It is currently Sun Mar 24, 2019 7:11 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 15 posts ] 
Author Message
 Post subject: Loading a 64bit kernel
PostPosted: Wed Jan 23, 2019 11:40 am 
Offline

Joined: Wed Oct 31, 2018 6:15 am
Posts: 18
I'd really appreciate some hints where I could start if I want to load a 64bit C kernel using my own bootloader (like resources to read..) . I understand that loading 64bit kernels is different since you have to (?) use the fastcall calling convention. I initially wanted to use an x64 PE kernel compiled with the Visual C++ compiler, but as I understand it's quite hard to configure the compiler, I thought I'd better go with ELF (I still like the PE idea more, since doing more research into PE executables may come in handy as I've been studying a little malware analysis on Windows).

EDIT: Reading @bzt's post from here with a little more attention ,it seems that he addressed quite a few of my issues. As far as I was able to understand, it should be fine to call the entry point with a simple 'call' provided I define it as having no arguments in C? Actually, it wouldn't make sense to behave otherwise.

EDIT:
1. My real problem is connecting the bootloader (assembled using NASM) and the kernel's executable (compiled using the Visual C++ compiler).
2. Things I managed to do so far: reading from disk, jumping into the stage 2 bootloader, setting up long mode.. I also managed to build the x86_64-elf-gcc cross compiler, but I'd still like it better if I could go with PE executables instead (I read GCC can also output executables for MinGW, but I'd rather not go with that).
3. With regard to long mode, could someone point me to some resources where I could read about the GDT (entries) needed in long mode? I know about the Intel/AMD manuals, but I'd like more information about the entries (like the null one etc).


Top
 Profile  
 
 Post subject: Re: Loading a 64bit kernel
PostPosted: Wed Jan 23, 2019 12:58 pm 
Offline
Member
Member

Joined: Wed Aug 30, 2017 8:24 am
Posts: 169
Well, you do what you usually do: Load the kernel image from disk into memory, prepare an environment it can work with, then jump to its entry point. You read the entry point out of the executable! It's written in the header somewhere. The executable format itself is pretty immaterial to the kernel. Only the bootloader needs to know. You can propably objcopy an ELF file into a PE one without too much damage. And how you call the entry point is between the bootloader and the kernel. I have the bootloader prepare a stack with an argument structure on it. Other conventions are possible.

Regarding the GDT: If you already have the manuals, what more do you need? Especially in the boot loader, you only need a null segment, a code segment, and a data segment. The only difference to protected mode is that you set the L bit in both of them, which was reserved before. The null segment is just the name for the first GDT entry, which is unusable thanks to the architecture. You can write there whatever you want, the CPU will never read it. The manuals will also tell you what kind of segments are still valid in long mode. In addition to a code and data seg, you will need a TSS. Actually one TSS per CPU.


Top
 Profile  
 
 Post subject: Re: Loading a 64bit kernel
PostPosted: Wed Jan 23, 2019 1:57 pm 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 1490
PhantomR wrote:
I understand that loading 64bit kernels is different since you have to (?) use the fastcall calling convention.

Pretty much. There are two calling conventions for x64 (AMD and Microsoft), but they're both very similar to fastcall for x86. GCC supports both.

PhantomR wrote:
I initially wanted to use an x64 PE kernel compiled with the Visual C++ compiler, but as I understand it's quite hard to configure the compiler, I thought I'd better go with ELF (I still like the PE idea more, since doing more research into PE executables may come in handy as I've been studying a little malware analysis on Windows).

I've never tried building x86_64-pe-gcc (or x86_64-coff-gcc), but it might be worth a shot. If it works, you'll have a copy of GCC that directly produces PE executables.

If it doesn't work, you can always use objcopy.

PhantomR wrote:
As far as I was able to understand, it should be fine to call the entry point with a simple 'call' provided I define it as having no arguments in C? Actually, it wouldn't make sense to behave otherwise.

Correct. However, at some point you will want to pass arguments to functions from assembly (or call assembly functions from C), so you might as well learn how to do it.

PhantomR wrote:
3. With regard to long mode, could someone point me to some resources where I could read about the GDT (entries) needed in long mode? I know about the Intel/AMD manuals, but I'd like more information about the entries (like the null one etc).

At minimum, you need a null descriptor, a 64-bit ring 0 code descriptor, and a ring 0 data descriptor. Here's an example of such code. This example skips some steps that are "required" according to the Intel/AMD manuals. If you decide to follow the officially-sanctioned method to enter long mode, you'll also need a 32-bit ring 0 code descriptor.


Top
 Profile  
 
 Post subject: Re: Loading a 64bit kernel
PostPosted: Wed Jan 23, 2019 4:08 pm 
Offline
Member
Member
User avatar

Joined: Wed Oct 27, 2004 11:00 pm
Posts: 846
Location: WA
PhantomR wrote:
I initially wanted to use an x64 PE kernel compiled with the Visual C++ compiler, but as I understand it's quite hard to configure the compiler, I thought I'd better go with ELF (I still like the PE idea more, since doing more research into PE executables may come in handy as I've been studying a little malware analysis on Windows).

the reason you have heard that is because people like to lie to you -- after all, VC++ was specifically designed for OSdev (it is what MS uses to build windows)

to configure VisualStudio to compile your kernel there is a number of things you have to do:
1) in build settings, under linker section, change your build target -- change it to "freestanding"

... and your done! thats it!

(yes, 1 is a number...) -- note though that this doesn't include properly supporting global object construction/destruction, for which the process is (iirc) almost exactly like it is with GCC

in fact, it is so easy to do that the person who wrote our wiki guide for VC++ had to think up some way to make it seem more complicated, so instead he listed every single option in build settings, and gave his own personal recommendation for each one (and for most of them he actually recommended the default settings!)

this will work if your PE loader is fully-functional, to make things a little easier for yourself you might also want to strip relocations and specify your base address (since you should have paging enabled before loading your kernel, you can hardcode the load address and simplify your loader significantly by avoiding the need for supporting runtime relocations)



now if you want to load with GRUB (no good reason for that in 2019...) there are 2 other changes you have to make, but its not hard

if you are writing your own bootloader, for the bootloader you have to:
1) in build settings, under linker section, change your build target -- change it to "UEFI application"

... and your done! hit "build" and you have yourself a working UEFI bootloader (assuming your own code follows the UEFI rules...)

_________________
## ---- ----- ------ Intel Manuals
OSdev wiki


Top
 Profile  
 
 Post subject: Re: Loading a 64bit kernel
PostPosted: Thu Jan 24, 2019 2:37 am 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 1490
JAAman wrote:
in build settings, under linker section, change your build target

Where are these build targets documented? Microsoft's Visual Studio documentation makes no mention of them.


Top
 Profile  
 
 Post subject: Re: Loading a 64bit kernel
PostPosted: Thu Jan 24, 2019 3:31 am 
Offline
Member
Member

Joined: Thu Jul 05, 2012 5:12 am
Posts: 921
Location: Finland
JAAman wrote:
VC++ was specifically designed for OSdev


Does the license even allow this for other users? I could easily change my build scripts to use cl.exe as a compiler (for kernel, tools are normal programs), but I'm quite sure that this would violate the terms of usage. If not forbidden outright, it would be morally/ethically questionable. It is clear that the intent for the cl.exe is to produce executables that run on MS platforms.

However, how about UEFI applications? That an interesting question. Maybe this is not clear at all.

_________________
Undefined behavior since 2012


Top
 Profile  
 
 Post subject: Re: Loading a 64bit kernel
PostPosted: Thu Jan 24, 2019 4:17 am 
Offline
Member
Member

Joined: Tue May 13, 2014 3:02 am
Posts: 253
Location: Private, UK
JAAman wrote:
VC++ was specifically designed for OSdev (it is what MS uses to build windows)


But Windows is the only OS (of any significance) built with VC++ and has been heavily customised for the needs of that one product. Although admittedly VC++ was developed from the earlier "Microsoft C Compiler" (later "Microsoft C/C++ Compiler") that was also (in various versions) used to build Xenix, OS/2 and parts of MS-DOS (although the MS-DOS "kernel" was always 100% ASM). Of course, since it hasn't been used to build anything non-Windows since the early 1990s, there's little reason for Microsoft to care if you run into issues doing so.

On the other hand, I can think of at least a dozen operating systems that are built with GCC and the GCC developers are interested in fixing issues that arise even in the most obscure of situations. They're not tied to the compilation needs of any one product.

I don't think either compiler can be accurately described as being "specifically designed for OSdev", only that they are both suitable for building kernels to different degrees.

_________________
Image


Top
 Profile  
 
 Post subject: Re: Loading a 64bit kernel
PostPosted: Thu Jan 24, 2019 9:46 am 
Offline
Member
Member
User avatar

Joined: Wed Oct 27, 2004 11:00 pm
Posts: 846
Location: WA
Antti wrote:
JAAman wrote:
VC++ was specifically designed for OSdev


Does the license even allow this for other users? I could easily change my build scripts to use cl.exe as a compiler (for kernel, tools are normal programs), but I'm quite sure that this would violate the terms of usage. If not forbidden outright, it would be morally/ethically questionable. It is clear that the intent for the cl.exe is to produce executables that run on MS platforms.

yes, this is completely allowed by the license agreement (they changed it recently, and I carefully examined it to be sure this is allowed because some people have falsely claimed that it wasn't allowed)

there are a few components of VS that are not allowed for use for anything not targeting windows (under the new license they have a separate license that covers them) -- but these are all windows-specific advanced debug tools and a few libraries (MFC and ATL, iirc, don't remember if this included the windows header files also? but I actually don't think it did but might include the new library that replaced them) and would be mostly pointless for anything not targeting windows anyway, older versions of the license were not as clear, and included everything in a single license which mentioned "portions" which were not allowed to use for anything not targeting windows

CL does not have a separate license, and falls under the main license... which comes specifically configured for android and ios development! (if you check the android and IOS options in the installer) and thus clearly not intended for windows only development (though android and IOS targeting use a different compiler (clang, iirc), the CL license is the same as the VS license)

let me be very clear here: while the current license is much more clear, it has never been a violation of the license to OSdev using VS/VC++/MASM



if you use CL, however, remember that it isn't incredibly buggy, and therefore you should not ever use /Wall /Werror... as this will not be capable of compiling anything non-trivial (or perhaps even trivial code)



Quote:
Where are these build targets documented? Microsoft's Visual Studio documentation makes no mention of them.

just looked it up, and my memory was a little off... the setting I was referring to is called "subsystem" (in Linker->System, or on the commandline: "/SUBSYSTEM:<specify target subsystem>) and it is documented (though the current options don't provide the "freestanding" option I thought I remembered... that is what time does to memory) but it isn't necessary for OSdev at all... instead the option that you need (I correctly remembered that only 1 option was needed...) is to specify the entry point (in Linker->Advanced, or on the commandline "/ENTRY:<function name>") of course even this is only necessary if you don't want to use the default entrypoint function name


while no option is strictly necessary, there are only 3 options that are relevant for OSdev (that aren't directly related to regular application development)

1) disable exceptions (C++ ->code generation->Enable C++ Exceptions -- on the commandline this is: nothing specified) -- the code shouldn't produce any exception code if you don't use exceptions in your code, therefore this should be irrelevant (it would only affect the CRT code, which shouldn't exist in your OS kernel or bootloader), in fact I'm not convinced this actually has any effect at all (I think, but I don't know, if exceptions exist in the code being compiled, it will default to something rather than failing with an error -- the option exists to allow you to choose between different types of exception handling, not to disable exception handling)

2) disable standard libraries (Linker->Input->Ignore All Default Libraries -- on the commandline this is /NODEFAULTLIB) again, this isn't necessary but will prevent the compiler from searching the standard libraries for code you call but fail to provide (I consider this the OSdev equivalent to using /Werror -- turns what could be incorrect code generation into a hard error)

3) entrypoint (Linker->Advanced->Entry Point -- on the commandline this is /ENTRY:<specify entry point function name>) this will allow you to specify the true entry point function name, overriding the default one provided by the CRT (necessary if you don't use the default function name)

_________________
## ---- ----- ------ Intel Manuals
OSdev wiki


Top
 Profile  
 
 Post subject: Re: Loading a 64bit kernel
PostPosted: Thu Jan 24, 2019 10:24 am 
Offline
Member
Member
User avatar

Joined: Fri Oct 27, 2006 9:42 am
Posts: 1438
Location: Athens, GA, USA
Where is is said that VC++ is used for Windows itself? I am not questioning the claim, so much as questioning how you found this out - Microsoft are very tight-lipped about their internal procedures, AFAICT. From what little I have ever heard about it, it has always been my understanding that they used a different, internal-use-only compiler for Windows proper, but I never looked into it (nor ever cared) so I do not know.

Keep in mind that I have no horse in this race; my OS dev isn't in C or C++, and the only concern I have about other people's tools is being able to give useful advice.

JAAman wrote:
Antti wrote:
JAAman wrote:
VC++ was specifically designed for OSdev


Does the license even allow this for other users? I could easily change my build scripts to use cl.exe as a compiler (for kernel, tools are normal programs), but I'm quite sure that this would violate the terms of usage. If not forbidden outright, it would be morally/ethically questionable. It is clear that the intent for the cl.exe is to produce executables that run on MS platforms.

yes, this is completely allowed by the license agreement (they changed it recently, and I carefully examined it to be sure this is allowed because some people have falsely claimed that it wasn't allowed)


They were stating it because it wasn't true in the past (the older license, for both VC++ and MASM, specifically prohibited cross-development in general, and OS dev in particular). TBH, I really doubt anyone else here has looked at the VC++ license in recent years.

Not that it matters; using VC++ means you can't self-host, and I rather doubt anyone here would want to be in that position. As terrible as GCC and LLVM are, they are at least portable. I'll keep my own counsel on the wisdom of using C/C++ in the first place... (for further Illumination fnord seen my .sig, or consult your pineal gland).

_________________
Rev. First Speaker Schol-R-LEA;2 LCF ELF JAM POEE KoR KCO PPWMTF
μή εἶναι βασιλικήν ἀτραπόν ἐπί γεωμετρίαν
Lisp programmers tend to seem very odd to outsiders, just like anyone else who has had a religious experience they can't quite explain to others.


Top
 Profile  
 
 Post subject: Re: Loading a 64bit kernel
PostPosted: Thu Jan 24, 2019 12:12 pm 
Offline
Member
Member
User avatar

Joined: Wed Oct 27, 2004 11:00 pm
Posts: 846
Location: WA
Schol-R-LEA wrote:
They were stating it because it wasn't true in the past (the older license, for both VC++ and MASM, specifically prohibited cross-development in general, and OS dev in particular).

that is a myth, created by the combination of assuming it would be the case (because, you know, MS is evil...) and failing to read the license carefully

the MASM32 license was often quoted here on this forum as "proof" that the license for MASM and VC++ forbid OSdev... problem is, MASM32 is a separate non-MS product that consists of a set of tools and libraries for use with MASM for Win32 ASM development

the older VS license was a lot more complicated than the current one (the current one is only 3-4 short paragraphs), and included all rules for all tools (currently, some tools utilize a separate license, which does still forbid non-windows development) -- there was a clause, in that license, which forbade "development not targeting windows" (don't recall the exact wording now) ... what many people missed (because they assumed or had been told, that MS wouldn't allow OSdev) was that this clause was in a section applying to libraries bundled with VS (and not to VS itself, nor to the MS compilers) -- this section applies to the MFC library, the ATL library, the STL, std-c, and CRT libraries

now when it comes to MASM there is one other factor: MASM was not bundled with VS, instead it was part of the DDK (driver development kit) which had its own license, which also restricts use of some of its components to windows development -- I don't believe this applied to MASM though, however I never read that license, so I don't know for sure (I don't consider MASM a good choice for OSdev, I prefer NASM myself)



edit:

I just realized, my previous post may have unintentionally implied that I hadn't read the previous license, and was only reading the new one in response to people's comments about it

this is not true, I have read the license for every version I have ever had (and do so habitually, as to ensure that I fully understand any restrictions on what I can and cannot do with it) -- this includes VC6 (starter), 2008 (express), 2010 (express), 2012 (express), 2013 (express), 2015 (express?), and 2017 (community)

I have completely read and understood all terms in all products, this is not something I only did with the recent version after the recent changes

NOTE: while the wording, length, and complexity of the document has changed, what it does and what it does not allow has not substantially changed -- however it is easier to understand now (and clearer that there are no cross-development restrictions on the main VS/VC++ products)

_________________
## ---- ----- ------ Intel Manuals
OSdev wiki


Top
 Profile  
 
 Post subject: Re: Loading a 64bit kernel
PostPosted: Thu Jan 24, 2019 12:34 pm 
Offline
Member
Member
User avatar

Joined: Fri Oct 27, 2006 9:42 am
Posts: 1438
Location: Athens, GA, USA
JAAman wrote:
Schol-R-LEA wrote:
They were stating it because it wasn't true in the past (the older license, for both VC++ and MASM, specifically prohibited cross-development in general, and OS dev in particular).

that is a myth, created by the combination of assuming it would be the case (because, you know, MS is evil...)


I assumed it because MS aren't stupid. Would you want to support a the development of a competitor to your commercial product? More importantly, would you want to handle the technical support for all the possible use cases of a tool being (mis)used for cross-development, when it wasn't intended for it in the first place?

It isn't the same situation as the FOSS tools at all; those explicitly place support on the community, not paid support technicians. The two models have different advantages and disadvantages, but they really can't be compared in this instance - the two support models are simply too different from each other, not better or worse in any meaningful way.

And as I already said, I don't have any interest in this personally.

_________________
Rev. First Speaker Schol-R-LEA;2 LCF ELF JAM POEE KoR KCO PPWMTF
μή εἶναι βασιλικήν ἀτραπόν ἐπί γεωμετρίαν
Lisp programmers tend to seem very odd to outsiders, just like anyone else who has had a religious experience they can't quite explain to others.


Top
 Profile  
 
 Post subject: Re: Loading a 64bit kernel
PostPosted: Thu Jan 24, 2019 9:40 pm 
Offline
Member
Member
User avatar

Joined: Thu Oct 13, 2016 4:55 pm
Posts: 236
PhantomR wrote:
EDIT: Reading @bzt's post from here with a little more attention ,it seems that he addressed quite a few of my issues. As far as I was able to understand, it should be fine to call the entry point with a simple 'call' provided I define it as having no arguments in C? Actually, it wouldn't make sense to behave otherwise.

EDIT:
1. My real problem is connecting the bootloader (assembled using NASM) and the kernel's executable (compiled using the Visual C++ compiler).
As you have said, if you don't pass arguments, then setting up a stack, clearing bss and jumping to the entry point is pretty much all you need. That's exactly why my boot loader uses memory mapped structures, as that's architecture, platform and ABI agnostic. See https://forum.osdev.org/viewtopic.php?f=2&t=33362

Quote:
2. Things I managed to do so far: reading from disk, jumping into the stage 2 bootloader, setting up long mode.. I also managed to build the x86_64-elf-gcc cross compiler, but I'd still like it better if I could go with PE executables instead (I read GCC can also output executables for MinGW, but I'd rather not go with that).
I don't have VC++, but regarding to PE executables you should take a look at my boot loader's source. It sets up long mode, and able to load both ELF64 and PE32+ executables. There's a BIOS (fully written in Assembly) and an UEFI version (written in C with GNU EFI lib). It can be useful to see how to parse the PE structures in the binary. Some nasty sign extension tricks are required if you have a higher-half kernel because PE format can't store 64 bit address in some cases.

Quote:
3. With regard to long mode, could someone point me to some resources where I could read about the GDT (entries) needed in long mode? I know about the Intel/AMD manuals, but I'd like more information about the entries (like the null one etc).
I think manuals and the wiki are your best chance.

Cheers,
bzt


Top
 Profile  
 
 Post subject: Re: Loading a 64bit kernel
PostPosted: Fri Jan 25, 2019 8:15 am 
Offline
Member
Member

Joined: Tue May 13, 2014 3:02 am
Posts: 253
Location: Private, UK
Schol-R-LEA wrote:
Where is is said that VC++ is used for Windows itself? I am not questioning the claim, so much as questioning how you found this out - Microsoft are very tight-lipped about their internal procedures, AFAICT. From what little I have ever heard about it, it has always been my understanding that they used a different, internal-use-only compiler for Windows proper, but I never looked into it (nor ever cared) so I do not know.


There is/was a (more-or-less successful) project to build a functional Windows OS based on "leaked" NT 4.0 code. If you know the right search terms (I won't detail them here due to the obviously dubious legal status of the project... Somewhat ironically, you can find the code on a certain Microsoft-owned source code hosting service.) you can find not only the complete source code to a functioning version of Windows (albeit not one that's exactly identical to any official release), but also the build environment used. The compiler is the standard VC++ 7.0 (2002) compiler. Obviously this is newer than most of the code, so wasn't what was used for actual NT 4.0 releases, but it's a good indicator that the standard compiler is capable.

Additionally, Microsoft did release the source code to (most of) the Windows Server 2003 kernel under an academic licence as the Windows Research Kernel (WRK). It's compiled with the standard VC++ 7.1 (2003) compiler.

With older versions, you may be correct (although it's pretty much certain that all versions were built with some variant of the VC++/MS C/C++ compiler family, the exact versions used may not have been commercially released; I believe that older Windows DDKs included some "special" compilers needed for building drivers, etc.), but these days it's almost certain that the Windows kernel is built with standard commercially available tools.

_________________
Image


Top
 Profile  
 
 Post subject: Re: Loading a 64bit kernel
PostPosted: Fri Jan 25, 2019 10:52 am 
Offline
Member
Member
User avatar

Joined: Fri Oct 27, 2006 9:42 am
Posts: 1438
Location: Athens, GA, USA
mallard wrote:
With older versions, you may be correct (although it's pretty much certain that all versions were built with some variant of the VC++/MS C/C++ compiler family, the exact versions used may not have been commercially released; I believe that older Windows DDKs included some "special" compilers needed for building drivers, etc.), but these days it's almost certain that the Windows kernel is built with standard commercially available tools.


Interesting. OK, then, thank you for the information, I didn't realize that.

_________________
Rev. First Speaker Schol-R-LEA;2 LCF ELF JAM POEE KoR KCO PPWMTF
μή εἶναι βασιλικήν ἀτραπόν ἐπί γεωμετρίαν
Lisp programmers tend to seem very odd to outsiders, just like anyone else who has had a religious experience they can't quite explain to others.


Top
 Profile  
 
 Post subject: Re: Loading a 64bit kernel
PostPosted: Wed Feb 06, 2019 7:53 pm 
Offline

Joined: Wed Oct 31, 2018 6:15 am
Posts: 18
Thank you very much to all of you who responed! I'm sorry for the delay.. I'll get back to this topic when I'm closer to loading the C kernel.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 15 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: doubletriplefault, nck and 11 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group