=== modified file 'doc/boot.S' --- doc/boot.S 2010-01-02 17:52:11 +0000 +++ doc/boot.S 2010-01-04 19:44:53 +0000 @@ -30,9 +30,9 @@ /* The flags for the Multiboot header. */ #ifdef __ELF__ -# define MULTIBOOT_HEADER_FLAGS 0x00000007 +# define MULTIBOOT_HEADER_FLAGS 0x0000000f #else -# define MULTIBOOT_HEADER_FLAGS 0x00010007 +# define MULTIBOOT_HEADER_FLAGS 0x0001000f #endif .text === modified file 'doc/kernel.c' --- doc/kernel.c 2010-01-02 17:52:11 +0000 +++ doc/kernel.c 2010-01-04 19:43:33 +0000 @@ -47,6 +47,153 @@ static void putchar (int c); void printf (const char *format, ...); +static void +tagged (unsigned long addr) +{ + struct multiboot_tag *tag; + + for (tag = (struct multiboot_tag *) addr; tag->type != MULTIBOOT_TAG_TYPE_END; + tag = (struct multiboot_tag *) ((multiboot_uint8_t *) tag + tag->size)) + { + printf ("Tag 0x%x, Size 0x%x\n", tag->type, tag->size); + switch (tag->type) + { + case MULTIBOOT_TAG_TYPE_CMDLINE: + printf ("Command line = %s\n", + ((struct multiboot_tag_string *) tag)->string); + break; + case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME: + printf ("Boot loader name = %s\n", + ((struct multiboot_tag_string *) tag)->string); + break; + case MULTIBOOT_TAG_TYPE_MODULE: + printf ("Module at 0x%x-0x%x. Command line %s\n", + ((struct multiboot_tag_module *) tag)->mod_start, + ((struct multiboot_tag_module *) tag)->mod_end, + ((struct multiboot_tag_module *) tag)->cmdline); + break; + case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO: + printf ("mem_lower = %uKB, mem_upper = %uKB\n", + ((struct multiboot_tag_basic_meminfo *) tag)->mem_lower, + ((struct multiboot_tag_basic_meminfo *) tag)->mem_upper); + break; + case MULTIBOOT_TAG_TYPE_BOOTDEV: + printf ("Boot device 0x%x,%u,%u\n", + ((struct multiboot_tag_bootdev *) tag)->biosdev, + ((struct multiboot_tag_bootdev *) tag)->slice, + ((struct multiboot_tag_bootdev *) tag)->part); + break; + case MULTIBOOT_TAG_TYPE_MMAP: + { + multiboot_memory_map_t *mmap; + + printf ("mmap\n"); + + for (mmap = ((struct multiboot_tag_mmap *) tag)->entries; + (multiboot_uint8_t *) mmap + < (multiboot_uint8_t *) tag + tag->size; + mmap = (multiboot_memory_map_t *) ((unsigned long) mmap + + mmap->size + + sizeof (mmap->size))) + printf (" size = 0x%x, base_addr = 0x%x%x," + " length = 0x%x%x, type = 0x%x\n", + (unsigned) mmap->size, + (unsigned) (mmap->addr >> 32), + (unsigned) (mmap->addr & 0xffffffff), + (unsigned) (mmap->len >> 32), + (unsigned) (mmap->len & 0xffffffff), + (unsigned) mmap->type); + } + break; + case MULTIBOOT_TAG_TYPE_FRAMEBUFFER: + { + multiboot_uint32_t color; + unsigned i; + struct multiboot_tag_framebuffer *tagfb + = (struct multiboot_tag_framebuffer *) tag; + void *fb = (void *) (unsigned long) tagfb->common.framebuffer_addr; + + switch (tagfb->common.framebuffer_type) + { + case MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED: + { + unsigned best_distance, distance; + struct multiboot_color *palette; + + palette = tagfb->framebuffer_palette; + + color = 0; + best_distance = 4*256*256; + + for (i = 0; i < tagfb->framebuffer_palette_num_colors; i++) + { + distance = (0xff - palette[i].blue) + * (0xff - palette[i].blue) + + palette[i].red * palette[i].red + + palette[i].green * palette[i].green; + if (distance < best_distance) + { + color = i; + best_distance = distance; + } + } + } + break; + + case MULTIBOOT_FRAMEBUFFER_TYPE_RGB: + color = ((1 << tagfb->framebuffer_blue_mask_size) - 1) + << tagfb->framebuffer_blue_field_position; + break; + + default: + color = 0xffffffff; + break; + } + + for (i = 0; i < tagfb->common.framebuffer_width + && i < tagfb->common.framebuffer_height; i++) + { + switch (tagfb->common.framebuffer_bpp) + { + case 8: + { + multiboot_uint8_t *pixel = fb + + tagfb->common.framebuffer_pitch * i + i; + *pixel = color; + } + break; + case 15: + case 16: + { + multiboot_uint16_t *pixel + = fb + tagfb->common.framebuffer_pitch * i + 2 * i; + *pixel = color; + } + break; + case 24: + { + multiboot_uint32_t *pixel + = fb + tagfb->common.framebuffer_pitch * i + 3 * i; + *pixel = (color & 0xffffff) | (*pixel & 0xff000000); + } + break; + + case 32: + { + multiboot_uint32_t *pixel + = fb + tagfb->common.framebuffer_pitch * i + 4 * i; + *pixel = color; + } + break; + } + } + break; + } + } + } +} + + /* Check if MAGIC is valid and print the Multiboot information structure pointed by ADDR. */ void @@ -57,6 +204,12 @@ /* Clear the screen. */ cls (); + if (magic == MULTIBOOT_BOOTLOADER_MAGIC_TAGGED) + { + tagged (addr); + return; + } + /* Am I booted by a Multiboot-compliant boot loader? */ if (magic != MULTIBOOT_BOOTLOADER_MAGIC) { === modified file 'doc/multiboot.h' --- doc/multiboot.h 2010-01-02 17:52:11 +0000 +++ doc/multiboot.h 2010-01-04 20:35:55 +0000 @@ -31,8 +31,11 @@ /* This should be in %eax. */ #define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002 +/* This should be in %eax. */ +#define MULTIBOOT_BOOTLOADER_MAGIC_TAGGED 0x3BADB002 + /* The bits in the required part of flags field we don't support. */ -#define MULTIBOOT_UNSUPPORTED 0x0000fff8 +#define MULTIBOOT_UNSUPPORTED 0x0000fff0 /* Alignment of multiboot modules. */ #define MULTIBOOT_MOD_ALIGN 0x00001000 @@ -51,6 +54,9 @@ /* Must pass video information to OS. */ #define MULTIBOOT_VIDEO_MODE 0x00000004 +/* Must pass tagged mbi to OS. */ +#define MULTIBOOT_TAGGED_MBI 0x00000008 + /* This flag indicates the use of the address fields in the header. */ #define MULTIBOOT_AOUT_KLUDGE 0x00010000 @@ -254,6 +260,122 @@ }; typedef struct multiboot_mod_list multiboot_module_t; +struct multiboot_tag +{ + multiboot_uint32_t type; + multiboot_uint32_t size; +}; + +struct multiboot_tag_string +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + char string[0]; +}; + +struct multiboot_tag_module +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint32_t mod_start; + multiboot_uint32_t mod_end; + char cmdline[0]; +}; + +struct multiboot_tag_basic_meminfo +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint32_t mem_lower; + multiboot_uint32_t mem_upper; +}; + +struct multiboot_tag_bootdev +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint32_t biosdev; + multiboot_uint32_t slice; + multiboot_uint32_t part; +}; + +struct multiboot_tag_mmap +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + struct multiboot_mmap_entry entries[0]; +}; + +struct multiboot_vbe_info_block +{ + multiboot_uint8_t external_specification[512]; +}; + +struct multiboot_vbe_mode_info_block +{ + multiboot_uint8_t external_specification[256]; +}; + +struct multiboot_tag_vbe +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + + multiboot_uint16_t vbe_mode; + multiboot_uint16_t vbe_interface_seg; + multiboot_uint16_t vbe_interface_off; + multiboot_uint16_t vbe_interface_len; + + struct multiboot_vbe_info_block vbe_control_info; + struct multiboot_vbe_mode_info_block vbe_mode_info; +}; + +struct multiboot_tag_framebuffer_common +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + + multiboot_uint64_t framebuffer_addr; + multiboot_uint32_t framebuffer_pitch; + multiboot_uint32_t framebuffer_width; + multiboot_uint32_t framebuffer_height; + multiboot_uint8_t framebuffer_bpp; + multiboot_uint8_t framebuffer_type; +}; + +struct multiboot_tag_framebuffer +{ + struct multiboot_tag_framebuffer_common common; + + union + { + struct + { + multiboot_uint16_t framebuffer_palette_num_colors; + struct multiboot_color framebuffer_palette[0]; + }; + struct + { + multiboot_uint8_t framebuffer_red_field_position; + multiboot_uint8_t framebuffer_red_mask_size; + multiboot_uint8_t framebuffer_green_field_position; + multiboot_uint8_t framebuffer_green_mask_size; + multiboot_uint8_t framebuffer_blue_field_position; + multiboot_uint8_t framebuffer_blue_mask_size; + }; + }; +}; + +#define MULTIBOOT_TAG_TYPE_END 0 +#define MULTIBOOT_TAG_TYPE_CMDLINE 1 +#define MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME 2 +#define MULTIBOOT_TAG_TYPE_MODULE 3 +#define MULTIBOOT_TAG_TYPE_BASIC_MEMINFO 4 +#define MULTIBOOT_TAG_TYPE_BOOTDEV 5 +#define MULTIBOOT_TAG_TYPE_MMAP 6 +#define MULTIBOOT_TAG_TYPE_VBE 7 +#define MULTIBOOT_TAG_TYPE_FRAMEBUFFER 8 + #endif /* ! ASM_FILE */ #endif /* ! MULTIBOOT_HEADER */ === modified file 'doc/multiboot.texi' --- doc/multiboot.texi 2010-01-04 19:44:39 +0000 +++ doc/multiboot.texi 2010-01-04 21:05:10 +0000 @@ -414,6 +414,9 @@ mode table (@pxref{Boot information format}) must be available to the kernel. +If bit 3 in the @samp{flags} word is set, the multiboot information +must be in tagged format. + If bit 16 in the @samp{flags} word is set, then the fields at offsets 12-28 in the Multiboot header are valid, and the boot loader should use them instead of the fields in the actual executable header to calculate @@ -515,7 +518,7 @@ @table @samp @item EAX -Must contain the magic value @samp{0x2BADB002}; the presence of this +Must contain the magic value @samp{0x2BADB002} if Boot info is non-tagged and @samp{0x3BADB002} otherwise; the presence of this value indicates to the operating system that it was loaded by a Multiboot-compliant boot loader (e.g. as opposed to another type of boot loader that the operating system can also be loaded from). @@ -578,9 +581,8 @@ @node Boot information format -@section Boot information format - -FIXME: Split this chapter like the chapter ``OS image format''. +@section Boot information +@subsection Boot information format Upon entry to the operating system, the @code{EBX} register contains the physical address of a @dfn{Multiboot information} data structure, @@ -595,6 +597,25 @@ operating system's responsibility to avoid overwriting this memory until it is done using it. +@subsection Basic tags structure +Boot information can be passed in one of two formats: pointer-based +or tag-based. Tag-based format must be used if and only it was requested +in multiboot header. Every tag begins with following fields: + +@example +@group + +-------------------+ +0 | type | +4-7 | size | + +-------------------+ +@end group +@end example + +@samp{type} contains an identifier of contents of the rest of the tag. +@samp{size} contains the size of tag including header fields. +Tags follow one another without any gaps. Tags are terminated by a tag of type @samp{0} and size @samp{8}. + +@subsection Basic non-tagged structure The format of the Multiboot information structure (as defined so far) follows: @@ -655,6 +676,7 @@ information structure to be expanded in the future without breaking anything. +@subsection Basic memory information If bit 0 in the @samp{flags} word is set, then the @samp{mem_*} fields are valid. @samp{mem_lower} and @samp{mem_upper} indicate the amount of lower and upper memory, respectively, in kilobytes. Lower memory starts @@ -663,6 +685,20 @@ upper memory is maximally the address of the first upper memory hole minus 1 megabyte. It is not guaranteed to be this value. +Corresponding tag is: + +@example +@group + +-------------------+ +0 | type = 4 | +4 | size = 16 | +8 | mem_lower | +12-15 | mem_upper | + +-------------------+ +@end group +@end example + +@subsection BIOS Boot device If bit 1 in the @samp{flags} word is set, then the @samp{boot_device} field is valid, and indicates which @sc{bios} disk device the boot loader loaded the OS image from. If the OS image was not loaded from a @@ -705,11 +741,39 @@ @samp{part1} will be 5, and @samp{part2} and @samp{part3} will both be 0xFF. +Corresponding tag is: +@example +@group + +-------------------+ +0 | type = 5 | +4 | size = 20 | +8 | biosdev | +12 | partition | +16-19 | sub-parition | + +-------------------+ +@end group +@end example + +@subsection Boot command line If bit 2 of the @samp{flags} longword is set, the @samp{cmdline} field is valid, and contains the physical address of the command line to be passed to the kernel. The command line is a normal C-style -zero-terminated string. - +UTF-8 zero-terminated string. + +Corresponding tag is: +@example +@group + +-------------------+ +0 | type = 1 | +4 | size | +8-xx | string | + +-------------------+ +@end group +@end example + +@samp{string} contains zero-terminated UTF-8 string padded to have length divisible by 4. + +@subsection Modules If bit 3 of the @samp{flags} is set, then the @samp{mods} fields indicate to the kernel what boot modules were loaded along with the kernel image, and where they can be found. @samp{mods_count} contains @@ -734,7 +798,7 @@ The first two fields contain the start and end addresses of the boot module itself. The @samp{string} field provides an arbitrary string to be associated with that particular boot module; it is a zero-terminated -ASCII string, just like the kernel command line. The @samp{string} field +UTF-8 string, just like the kernel command line. The @samp{string} field may be 0 if there is no string associated with the module. Typically the string might be a command line (e.g. if the operating system treats boot modules as executable programs), or a pathname (e.g. if the operating @@ -742,6 +806,25 @@ is specific to the operating system. The @samp{reserved} field must be set to 0 by the boot loader and ignored by the operating system. +Corresponding tag is: + +@example +@group + +-------------------+ +0 | type = 3 | +4 | size | +8 | mod_start | +12 | mod_end | +16-xx | string | + +-------------------+ +@end group +@end example + +Tag is padded in the way to have size divisible by 4. + +One tag appears per module. + +@subsection Symbols @strong{Caution:} Bits 4 & 5 are mutually exclusive. If bit 4 in the @samp{flags} word is set, then the following fields in @@ -795,6 +878,7 @@ @samp{shdr_num} may be 0, indicating no symbols, even if bit 5 in the @samp{flags} word is set. +@subsection Memory map If bit 6 in the @samp{flags} word is set, then the @samp{mmap_*} fields are valid, and indicate the address and length of a buffer containing a memory map of the machine provided by the @sc{bios}. @samp{mmap_addr} is @@ -824,6 +908,18 @@ The map provided is guaranteed to list all standard @sc{ram} that should be available for normal use. +The corresponding tag is +@example +@group + +-------------------+ +0 | type = 6 | +4 | size | +8-xx | entries | + +-------------------+ +@end group +@end example + +@subsection Drives table If bit 7 in the @samp{flags} is set, then the @samp{drives_*} fields are valid, and indicate the address of the physical address of the first drive structure and the size of drive structures. @samp{drives_addr} @@ -878,16 +974,32 @@ array may contain any number of I/O ports that are not related to the drive actually (such as @sc{dma} controller's ports). +@subsection Configuration table If bit 8 in the @samp{flags} is set, then the @samp{config_table} field is valid, and indicates the address of the @sc{rom} configuration table returned by the @dfn{GET CONFIGURATION} @sc{bios} call. If the @sc{bios} call fails, then the size of the table must be @emph{zero}. +@subsection Boot loader name If bit 9 in the @samp{flags} is set, the @samp{boot_loader_name} field is valid, and contains the physical address of the name of a boot loader booting the kernel. The name is a normal C-style zero-terminated string. +Corresponding tag is: +@example +@group + +-------------------+ +0 | type = 2 | +4 | size | +8-xx | string | + +-------------------+ +@end group +@end example + +@samp{string} contains zero-terminated UTF-8 string padded to have length divisible by 4. + +@subsection APM table If bit 10 in the @samp{flags} is set, the @samp{apm_table} field is valid, and contains the physical address of an @sc{apm} table defined as below: @@ -920,6 +1032,7 @@ @uref{http://www.microsoft.com/hwdev/busbios/amp_12.htm, Advanced Power Management (APM) BIOS Interface Specification}, for more information. +@subsection VBE info If bit 11 in the @samp{flags} is set, the @sc{vbe} table is available. The fields @samp{vbe_control_info} and @samp{vbe_mode_info} contain @@ -942,6 +1055,25 @@ Multiboot boot loaders may simulate @sc{vbe} on non-@sc{vbe} modes, as if they were @sc{vbe} modes. +Corresponding tag is: +@example +@group + +-------------------+ +0 | type = 7 | +4 | size = 784 | +8 | vbe_mode | +10 | vbe_interface_seg | +12 | vbe_interface_off | +14 | vbe_interface_len | +16 | vbe_control_info | +528-783 | vbe_mode_info | + +-------------------+ +@end group +@end example + +Notice that the tag contains VBE control and mode information structures directly rather than a pointer to them + +@subsection Framebuffer info If bit 12 in the @samp{flags} is set, the @sc{Framebuffer} table is available. The field @samp{framebuffer_addr} contains framebuffer physical address. This field is 64-bit wide but bootloader @dfn{should} set it under 4GiB if possible for compatibility with payloads which aren't aware of PAE or amd64. The field @samp{framebuffer_pitch} contains pitch in bytes. The fields @samp{framebuffer_width}, @samp{framebuffer_height} contain framebuffer dimensions in pixels. The field @samp{framebuffer_bpp} contains number of bits per pixel. If @samp{framebuffer_type} is set to 0 it means indexed color. In this case color_info is defined as follows: @@ -959,7 +1091,7 @@ +-------------+ 0 | red_value | 1 | green_value | -2 | blue_value | +2-2 | blue_value | +-------------+ @end group @end example @@ -981,6 +1113,40 @@ If @samp{framebuffer_type} is set to 2 it means EGA text. In this case @samp{framebuffer_width} and @samp{framebuffer_height} are expressed in characters and not in pixels. @samp{framebuffer_bpp} is equal 16 (16 bits per character) and @samp{framebuffer_pitch} is expressed in bytes per text line. All further values of @samp{framebuffer_type} are reserved for future expansion +Corresponding tag is: +@example +@group + +--------------------+ +0 | type = 8 | +4 | size | +8 | framebuffer_addr | +16 | framebuffer_pitch | +20 | framebuffer_width | +24 | framebuffer_height | +28 | framebuffer_bpp | +29 | framebuffer_type | +30 | color_info | + +--------------------+ +@end group +@end example + +If @samp{framebuffer_type} is @samp{0} color_info has the following format: + +@example +@group + +---------------------------------+ +0 | framebuffer_palette_num_colors | +4-xx | framebuffer_palette | + +---------------------------------+ +@end group +@end example + +With @samp{framebuffer_palette_num_colors} and @samp{framebuffer_palette} having the same format as in non-tagged version + +Note: @samp{framebuffer_palette} contains the palette and not its address. + +If @samp{framebuffer_type} is @samp{1} or @samp{2} color_info has the same format as non-tagged version. + @node Examples @chapter Examples