Making bootsector for USB pen

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
User avatar
Revelation
Member
Member
Posts: 47
Joined: Sat Jun 21, 2008 8:15 am

Making bootsector for USB pen

Post by Revelation »

Hi,

Most of the tutorials concerning boot sectors I find online are intended for floppies. But I think we are long past the floppy era, and my computer, lacking a floppy drive of course, silently confirms this. :wink:

What I am trying to do now is create a small OS on a USB memory stick. The boot loader I am using now is a copy of this one. The problem I have is converting the FAT12 header for a floppy to a decent header for a 1.1 GB memory pen. If I use the original boot loader, my memory stick size is reduced to 1.44 mb, which is very inconvenient.

OEM_ID db "QUASI-OS"
BytesPerSector dw 0x0200
SectorsPerCluster db 0x01
ReservedSectors dw 0x0001
TotalFATs db 0x02
MaxRootEntries dw 0x00E0
TotalSectorsSmall dw 0x0B40
MediaDescriptor db 0xF0
SectorsPerFAT dw 0x0009
SectorsPerTrack dw 0x0012
NumHeads dw 0x0002
HiddenSectors dd 0x00000000
TotalSectorsLarge dd 0x00000000
DriveNumber db 0x00
Flags db 0x00
Signature db 0x29
VolumeID dd 0xFFFFFFFF
VolumeLabel db "QUASI BOOT"
SystemID db "FAT12 "
Who can help me?
Now is the winter of my disk content.
User avatar
mutex
Member
Member
Posts: 131
Joined: Sat Jul 07, 2007 7:49 pm

Re: Making bootsector for USB pen

Post by mutex »

Dont get stuck with the bootloading stuff. Use grub on it. Very easy to install and very powerfull. If you need to load a 1.44mb image grub can do this for you easily.

My recomendation would be to focus on the kernel and setting up a runnable environment. Use multiboot for loading your kernel with grub.. If you need help there are a lot of info in grub-manual with actual sourcecode for having a c-kernel loaded...

-
Thomas
User avatar
suthers
Member
Member
Posts: 672
Joined: Tue Feb 20, 2007 3:00 pm
Location: London UK
Contact:

Re: Making bootsector for USB pen

Post by suthers »

I disagree, writing a bootloader is a very good exercise, that often teaches people a lot of good lessons before they start coding their kernel.
For example, I learned how to code in assembly when I wrote my bootloader (before I only knew the basics...).
Sorry, I can't help you, I've never written a bootloader for a flash drive..., but I think it's a good exercise so don't quit (though I know loads of people are going to disagree with me...)
Jules
User avatar
Dex
Member
Member
Posts: 1444
Joined: Fri Jan 27, 2006 12:00 am
Contact:

Re: Making bootsector for USB pen

Post by Dex »

I would say the answer to your ?, could be Fat16, it works the same as fat12, but bigger.
I would get "bootprog" see here: http://alexfru.chat.ru/epm.html#bootprog
It come with a fat12 and a fat16 loader, plus a program that will take the BPB info etc from the origanal BPB and jump over it to load the boot loader.
You will need to format the fob fat16, than mode your load as per the examples in the bootprog zip.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Making bootsector for USB pen

Post by Combuster »

There is no real difference between an USB drive and a Floppy drive working different - it's just what's on them. Floppies are usually FAT12, but most other FSes will work as well. An USB drive is larger, and hence doesn't use FAT12 because it can't handle the disk size (with the normal block size, 2¹² * 1024 = 4MB max, can be larger) thus it uses something different - which is in most cases either FAT16 (which with 4096b sectors can go up to 256MB, more with larger sectors) or FAT32 (anything into the TBs) The way the bios boots your USB drive is the same as it does for regular floppies or harddisks

Once you know what FS is actually on your drive, the only thing left is to change the FS-dependent code and everything should work. Or you could, as dex said, force the filesystem of your choice and be done without different pieces of code :)

Note that CDs are bound by specific standards, and are therefore booted differently on PCs by convention. In that respect some other non-PC architectures make even that easy :)
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
Revelation
Member
Member
Posts: 47
Joined: Sat Jun 21, 2008 8:15 am

Re: Making bootsector for USB pen

Post by Revelation »

I already tried GRUB before, but I failed to do so somehow. I already have grub for my Vista - Ubuntu dual boot, and I figured I could just add the memory stick to the list (menu.lst), but I was wrong.

I also looked at the boot16.asm file, which had question marks behind almost every variable, like TotalSectorsLarge. Ignoring that, I DDd it to my stick, but it rendered it unmountable. Thus, that file doesn't work unfortunately. Why does there have to be such information in the bootsector anyway, when without one the format can just be read?

Can I strip the information from my USB drive?
Now is the winter of my disk content.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Making bootsector for USB pen

Post by Combuster »

That file had question marks for a reason - it doesn't yet know what the size of the drive is. Yet you put it on the drive, overwriting exactly that info it needed. (Which is also what the OS needs to read it, rendering the device unusable).

Use a tool that can put a bootsector in place when formatting the drive. When it does so, it copies the bootsector over, then overwrite those parts that are needed to access the file system. The bootloader is written such that it reserves those areas for data, so when the formatting tool has put everything in place, the blank areas are filled in with the properties of the filesystem - for you and the OS to read.

Much more humane than DDing bits of code over and hoping you got everything right :wink:
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
JJeronimo
Member
Member
Posts: 202
Joined: Wed Oct 18, 2006 3:29 pm

Re: Making bootsector for USB pen

Post by JJeronimo »

Never done that before, but my hints would be:

- First of all, there's a little problem about pens: some
pens have a MBR and partitions; some pens just have
a filesystem stored is it, from byte 0 on. For this, the
boot sector still needs to take into account the "offset"
of the filesystem, which the chinloader (possible the
MBR boot code) is supposed to have passed to it.
- Blindly assume the BIOS supports LBA. I think this is
reasonable for pens...
- As is usually done for FAT boot sectors, write a version
for FAT16 and another one for FAT32. I think it's
somewhat useless to write one for supporting FAT 12.
Besides pretty limited in max volume size, the table is
also complicated to parse (not that you couldn't write
code for that, but it's not worth the effort!).
- There's another little point here: I think existing FAT
boot sectors for hard disk partitions can do the job, so
take this into account too.

As about the header, you do not want to tie your code to
the data you declare in your header. That's because your
boot sector is supposed to be *installed* in the file system
image, so it has to take into account the real values of the
file system that is being booted...

Hope this helps.

JJ
User avatar
Revelation
Member
Member
Posts: 47
Joined: Sat Jun 21, 2008 8:15 am

Re: Making bootsector for USB pen

Post by Revelation »

Thank you all :)

I've written some code (inspired by this) that reads the boot sector from any disk. If I'm not mistaking, it supports every FAT. Now I can write a boot code installer.

Code: Select all

// This application reads FAT boot sectors from any drive and prints the results to the screen.
// Compatible with FAT, FAT12 and FAT16. Not compatible with FAT32 yet.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

// this struct contains the whole 512 bytes of the boot sector
typedef struct BPB
{
   unsigned char jumpCode[3];
   unsigned char oemName[8];
   unsigned short bytes_Sector;
   unsigned char sec_Cluster;
   unsigned short size_Sector_Reserved;
   unsigned char fatCount;
   unsigned short Max_Root_Entry;
   unsigned short Total_Sector_FS;
   unsigned char Media_Type;
   unsigned short sectors_per_fat;
   unsigned short sectors_per_track;
   unsigned short total_Head_Count;
   unsigned long no_Sectors_Before_Part;
   unsigned long no_Sector_FS32;
   unsigned char BIOS_13h_Drive_No;
   unsigned char reserved;
   unsigned char ext_Boot_Part_Signature;
   unsigned long vol_Serial_Number;
   unsigned char vol_Label_Name[11];
   unsigned char FS_Type[8];
   unsigned char boot_Code[448];
   unsigned short signature;
} __attribute__((__packed__)) BPB;


void printbpb(BPB bpb)
{
   printf("Disk Information: \n");
   printf("===========================\n");
   printf("Assembly Instruction to jump to Boot code: 0x%x\n",
          bpb.jumpCode);
   printf("OEM Name: \"%.8s\"\n", bpb.oemName); // this string may not be zero terminated!
   printf("Bytes per sector: %d\n", bpb.bytes_Sector);
   printf("Sector per cluster: %d\n", bpb.sec_Cluster);
   printf("Size in sector for reserved area(Boot Sector): %d\n", bpb.size_Sector_Reserved);
   printf("Number of FATs(File Allocation Table): %d\n", bpb.fatCount);
   printf("Number of files for root directory: %d\n", bpb.Max_Root_Entry);
   printf("Number of Sectors in File System: %d\n", bpb.Total_Sector_FS);
   printf("Media Type: 0x%x\n", bpb.Media_Type);
   printf("Number of Sectors for each FAT: %d\n", bpb.sectors_per_fat);
   printf("Sectors per track: %d\n", bpb.sectors_per_track);
   printf("Number of head in storage device: %d\n", bpb.total_Head_Count);
   printf("BIOS INT13h Drive number: 0x%x\n", bpb.BIOS_13h_Drive_No);
   printf("Number of large sectors: 0x%x\n", bpb.no_Sector_FS32);
   printf("Volume Serial Number: %d\n", bpb.vol_Serial_Number);
   printf("Volume label Name: \"%.11s\"\n", bpb.vol_Label_Name); // this string may not be zero terminated!
   printf("File system type: \"%.8s\"\n", bpb.FS_Type); // this string may not be zero terminated!
   printf("Boot Sector Signature: 0x%x\n", bpb.signature);

}

int main(int argc, char** argv)
{
	FILE*  drivefile;
	char bootsector[512];
	BPB bpb;
	
	if (argc < 2)
	{
		printf("The following error occurred: Application needs disk location.\n");
		return 1;
	}
	
	const char* drivename = argv[1]; // /dev/sdf1 on UNIX for example; A: on WINDOWS
	
	drivefile = fopen(drivename, "rb"); // force binary, for WINDOWS

	if (!drivefile)
	{
		perror ("The following error occurred");
		return 2;
	}
	
	// clear buffer
	memset(bootsector, 0, 512);

	// read bootsector
	fread(bootsector, 512, 1, drivefile);
	
	memcpy(&bpb, bootsector, 512);
	
	printbpb(bpb);
	
	fclose(drivefile);
	
	return 0;
}
I hope other people find this code useful :)


edit: there are still some errors in the code.. trying to fix them.
edit: I see there is no support for FAT32...
Last edited by Revelation on Sun Jun 22, 2008 8:55 am, edited 3 times in total.
Now is the winter of my disk content.
JJeronimo
Member
Member
Posts: 202
Joined: Wed Oct 18, 2006 3:29 pm

Re: Making bootsector for USB pen

Post by JJeronimo »

Revelation wrote:Thank you all :)
Not at all.
I've written some code (inspired by this) that reads the boot sector from any disk. If I'm not mistaking, it supports every FAT. Now I can write a boot code installer.
I forgot to give you a pointer that might be useful, which is the FAT Spec from Microsoft itself:

http://www.nondot.org/sabre/os/files/Fi ... Format.pdf

JJ
User avatar
Revelation
Member
Member
Posts: 47
Joined: Sat Jun 21, 2008 8:15 am

Re: Making bootsector for USB pen

Post by Revelation »

Thanks JJernimo!

I am still checking my code, because I know it gives wrong results. bytes_Sector for example should be 512 and my app returns 8194. Really weird, because the value of the variable above it is correct.
Now is the winter of my disk content.
Korona
Member
Member
Posts: 1000
Joined: Thu May 17, 2007 1:27 pm
Contact:

Re: Making bootsector for USB pen

Post by Korona »

I don't know if that causes any problem in this case but generally structures that the compiler must not align or reorganize should be marked with __attribute((__packed__)).
managarm: Microkernel-based OS capable of running a Wayland desktop (Discord: https://discord.gg/7WB6Ur3). My OS-dev projects: [mlibc: Portable C library for managarm, qword, Linux, Sigma, ...] [LAI: AML interpreter] [xbstrap: Build system for OS distributions].
User avatar
Revelation
Member
Member
Posts: 47
Joined: Sat Jun 21, 2008 8:15 am

Re: Making bootsector for USB pen

Post by Revelation »

You hit the nail on the head :) I've adapted the source posted above.
Now is the winter of my disk content.
JJeronimo
Member
Member
Posts: 202
Joined: Wed Oct 18, 2006 3:29 pm

Re: Making bootsector for USB pen

Post by JJeronimo »

Korona wrote:I don't know if that causes any problem in this case but generally structures that the compiler must not align or reorganize should be marked with __attribute((__packed__)).
I was to suggest this, but forgot...

JJ
User avatar
kmcguire
Member
Member
Posts: 120
Joined: Tue Nov 09, 2004 12:00 am
Location: United States
Contact:

Re: Making bootsector for USB pen

Post by kmcguire »

Korona wrote:I don't know if that causes any problem in this case but generally structures that the compiler must not align or reorganize should be marked with __attribute((__packed__)).
Structures that have member fields that you do not want padded to maintain alignment on word boundaries need to use the __attribute__((__packed__)) expression. The C compiler should never reorganize the members of a structure! The padding increases the performance of data access (if you have ever noticed inside the manuals for a processor's instruction set it will hint to performance decreases on unaligned memory accesses for some stuff).

The alignment of the structure it's self comes from it's creation. Such that if you create the structure as a local variable then it is automatically aligned by the stack's word size. While, if you create the structure using a pointer, then the structure may or may not be aligned no matter if you used the __packed__ attribute or not.
Post Reply