From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with archive (Exim 4.43) id 1NS0W6-0000LI-W4 for mharc-grub-devel@gnu.org; Mon, 04 Jan 2010 22:55:35 -0500 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1NS0W3-0000KS-D3 for grub-devel@gnu.org; Mon, 04 Jan 2010 22:55:31 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1NS0KG-0006kv-CJ for grub-devel@gnu.org; Mon, 04 Jan 2010 22:43:22 -0500 Received: from [199.232.76.173] (port=52757 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NS0K2-0006i3-Po for grub-devel@gnu.org; Mon, 04 Jan 2010 22:43:06 -0500 Received: from mx20.gnu.org ([199.232.41.8]:6268) by monty-python.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1NS09v-0006NH-4f for grub-devel@gnu.org; Mon, 04 Jan 2010 22:32:39 -0500 Received: from fg-out-1718.google.com ([72.14.220.152]) by mx20.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1NRuFV-0003Fg-V7 for grub-devel@gnu.org; Mon, 04 Jan 2010 16:14:02 -0500 Received: by fg-out-1718.google.com with SMTP id 16so1664390fgg.12 for ; Mon, 04 Jan 2010 13:13:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:message-id:date:from :user-agent:mime-version:to:subject:x-enigmail-version:content-type; bh=5910d5q3uaVzQStU3Q3W/j8kfB0a2AP7MxTKAUouV7E=; b=yGoYtskjWR6FAghJpDIVeowbLvJXbTqY0JPeIPrutxJjuJg2soiaWXxputhSh2pSx+ emSu3tv1RcWAOz1O9W6LkebyGc5fPoIW9Kpll7NRBVkCaPoCcfwGkhJxVGt0mJ//zWYH 37s1FcJ4M1em5QvCdeQWRsM7dXmqoaoUE2mi4= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=message-id:date:from:user-agent:mime-version:to:subject :x-enigmail-version:content-type; b=fr3ks43b6s/6oiXnB0cM9E4TpmOmLb2fZGEFHoeNlYUaEK4eYAOXC8beYVtJB96JN1 +Iqof/3TLMOWPisIcLORrvaR/N+JoVmVKg+j/G+rDmI8BwbRMlijmNM2sFDvMI+FmMw0 O1FNh65kQS05NI378Ejybncu5Xluq/TCjzN+A= Received: by 10.87.14.38 with SMTP id r38mr6019097fgi.42.1262639581122; Mon, 04 Jan 2010 13:13:01 -0800 (PST) Received: from debian.bg45.phnet ([81.62.107.61]) by mx.google.com with ESMTPS id 3sm52184160fge.0.2010.01.04.13.12.58 (version=TLSv1/SSLv3 cipher=RC4-MD5); Mon, 04 Jan 2010 13:12:59 -0800 (PST) Message-ID: <4B4259D3.5020004@gmail.com> Date: Mon, 04 Jan 2010 22:12:51 +0100 From: =?UTF-8?B?VmxhZGltaXIgJ8+GLWNvZGVyL3BoY29kZXInIFNlcmJpbmVua28=?= User-Agent: Mozilla-Thunderbird 2.0.0.22 (X11/20091109) MIME-Version: 1.0 To: The development of GRUB 2 X-Enigmail-Version: 0.95.0 Content-Type: multipart/signed; micalg=pgp-sha512; protocol="application/pgp-signature"; boundary="------------enigC19BAAC415D345DFBB42FFC2" X-detected-operating-system: by mx20.gnu.org: GNU/Linux 2.6 (newer, 2) X-detected-operating-system: by monty-python.gnu.org: GNU/Linux 2.6, seldom 2.4 (older, 4) Subject: [RFC] Tagged mbi X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: The development of GNU GRUB List-Id: The development of GNU GRUB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 05 Jan 2010 03:55:31 -0000 This is an OpenPGP/MIME signed message (RFC 2440 and 3156) --------------enigC19BAAC415D345DFBB42FFC2 Content-Type: multipart/mixed; boundary="------------020006060604080409070403" This is a multi-part message in MIME format. --------------020006060604080409070403 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Hello. Currently mbi contains a lot of pointers and substructures. It's has various problems like: -Unused fields occupy space if any subsequent fields is used. -Difficult to relocate since it may be spilled all over the memory -It's unstraightforward to e.g. specify 2 framebuffers I propose to use tagged MBI. I attach proposed patch for multiboot and grub2. Patch for grub2 is based on my efiboot branch The patched branches are available under people/phcoder/mbtag-spec and people/phcoder/taggedmbi. The parts for which I haven't defined tagged equivalent yet: -Symbols -ROM information table -Drives table -APM table --=20 Regards Vladimir '=CF=86-coder/phcoder' Serbinenko --------------020006060604080409070403 Content-Type: text/x-diff; name="mbtaggedimpl.diff" Content-Transfer-Encoding: quoted-printable Content-Disposition: inline; filename="mbtaggedimpl.diff" =3D=3D=3D modified file 'include/grub/i386/multiboot.h' --- include/grub/i386/multiboot.h 2009-12-17 23:59:02 +0000 +++ include/grub/i386/multiboot.h 2010-01-02 02:04:52 +0000 @@ -39,4 +39,7 @@ void grub_multiboot_set_bootdev (void); void grub_multiboot_set_accepts_video (int val); =20 +void grub_multiboot_set_tagged (int val); +int grub_multiboot_get_tagged (void); + #endif /* ! GRUB_MULTIBOOT_CPU_HEADER */ =3D=3D=3D modified file 'include/multiboot.h' --- include/multiboot.h 2010-01-02 17:50:06 +0000 +++ include/multiboot.h 2010-01-02 21:06:42 +0000 @@ -31,8 +31,11 @@ /* This should be in %eax. */ #define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002 =20 +/* 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 =20 /* Alignment of multiboot modules. */ #define MULTIBOOT_MOD_ALIGN 0x00001000 @@ -51,6 +54,9 @@ /* Must pass video information to OS. */ #define MULTIBOOT_VIDEO_MODE 0x00000004 =20 +/* 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 =20 @@ -254,6 +260,114 @@ }; typedef struct multiboot_mod_list multiboot_module_t; =20 +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]; =20 +}; + +#include + +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 grub_vbe_info_block vbe_control_info; + struct grub_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 */ =20 #endif /* ! MULTIBOOT_HEADER */ =3D=3D=3D modified file 'loader/i386/multiboot.c' --- loader/i386/multiboot.c 2010-01-02 17:50:06 +0000 +++ loader/i386/multiboot.c 2010-01-02 21:57:30 +0000 @@ -62,7 +62,6 @@ grub_err_t err; struct grub_relocator32_state state =3D { - .eax =3D MULTIBOOT_BOOTLOADER_MAGIC, .ecx =3D 0, .edx =3D 0, .eip =3D grub_multiboot_payload_eip, @@ -71,6 +70,11 @@ .esp =3D 0x7ff00 }; =20 + if (grub_multiboot_get_tagged ()) + state.eax =3D MULTIBOOT_BOOTLOADER_MAGIC_TAGGED; + else + state.eax =3D MULTIBOOT_BOOTLOADER_MAGIC; + mbi_size =3D grub_multiboot_get_mbi_size (); if (alloc_mbi < mbi_size) { @@ -197,6 +201,9 @@ /* Skip filename. */ grub_multiboot_init_mbi (argc - 1, argv + 1); =20 + if (header->flags & MULTIBOOT_TAGGED_MBI) + grub_multiboot_set_tagged (1); + if (header->flags & MULTIBOOT_AOUT_KLUDGE) { int offset =3D ((char *) header - buffer - =3D=3D=3D modified file 'loader/i386/multiboot_mbi.c' --- loader/i386/multiboot_mbi.c 2010-01-02 20:54:52 +0000 +++ loader/i386/multiboot_mbi.c 2010-01-02 21:01:58 +0000 @@ -55,9 +55,10 @@ static grub_size_t total_modcmd; static unsigned modcnt; static char *cmdline =3D NULL; -static grub_uint32_t bootdev; static int bootdev_set; static int accepts_video; +static int tagged; +static grub_uint32_t biosdev, slice, part; =20 void grub_multiboot_set_accepts_video (int val) @@ -65,6 +66,18 @@ accepts_video =3D val; } =20 +void +grub_multiboot_set_tagged (int val) +{ + tagged =3D val; +} + +int +grub_multiboot_get_tagged (void) +{ + return tagged; +} + /* Return the length of the Multiboot mmap that will be needed to alloca= te our platform's map. */ static grub_uint32_t @@ -89,12 +102,23 @@ grub_size_t grub_multiboot_get_mbi_size (void) { - return sizeof (struct multiboot_info) + ALIGN_UP (cmdline_size, 4) - + modcnt * sizeof (struct multiboot_mod_list) + total_modcmd - + ALIGN_UP (sizeof(PACKAGE_STRING), 4) + grub_get_multiboot_mmap_len= () - + sizeof (struct grub_vbe_info_block) - + sizeof (struct grub_vbe_mode_info_block) - + 256 * sizeof (struct multiboot_color); + if (tagged) + return sizeof (struct multiboot_tag) + + (sizeof (struct multiboot_tag_string) + ALIGN_UP (cmdline_size, = 4)) + + (sizeof (struct multiboot_tag_string) + + ALIGN_UP (sizeof (PACKAGE_STRING), 4)) + + (modcnt * sizeof (struct multiboot_tag_module) + total_modcmd) + + sizeof (struct multiboot_tag_basic_meminfo) + + sizeof (struct multiboot_tag_bootdev) + + (sizeof (struct multiboot_tag_mmap) + grub_get_multiboot_mmap_le= n ()) + + sizeof (struct multiboot_tag_vbe); + else + return sizeof (struct multiboot_info) + ALIGN_UP (cmdline_size, 4) + + modcnt * sizeof (struct multiboot_mod_list) + total_modcmd + + ALIGN_UP (sizeof(PACKAGE_STRING), 4) + grub_get_multiboot_mmap_l= en () + + sizeof (struct grub_vbe_info_block) + + sizeof (struct grub_vbe_mode_info_block) + + 256 * sizeof (struct multiboot_color); } =20 /* Fill previously allocated Multiboot mmap. */ @@ -158,40 +182,67 @@ =20 #if HAS_VBE static grub_err_t -fill_vbe_info (struct multiboot_info *mbi, grub_uint8_t *ptrorig, - grub_uint32_t ptrdest) +fill_vbe_info_real (struct grub_vbe_info_block *vbe_control_info, + struct grub_vbe_mode_info_block *vbe_mode_info, + multiboot_uint16_t *vbe_mode, + multiboot_uint16_t *vbe_interface_seg, + multiboot_uint16_t *vbe_interface_off, + multiboot_uint16_t *vbe_interface_len) { grub_vbe_status_t status; - grub_uint32_t vbe_mode; void *scratch =3D (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; =20 status =3D grub_vbe_bios_get_controller_info (scratch); if (status !=3D GRUB_VBE_STATUS_OK) return grub_error (GRUB_ERR_IO, "Can't get controller info."); - =20 - mbi->vbe_control_info =3D ptrdest; - grub_memcpy (ptrorig, scratch, sizeof (struct grub_vbe_info_block)); - ptrorig +=3D sizeof (struct grub_vbe_info_block); - ptrdest +=3D sizeof (struct grub_vbe_info_block); - =20 + + grub_memcpy (vbe_control_info, scratch, sizeof (struct grub_vbe_info_b= lock)); + status =3D grub_vbe_bios_get_mode (scratch); - vbe_mode =3D *(grub_uint32_t *) scratch; + *vbe_mode =3D *(grub_uint32_t *) scratch; if (status !=3D GRUB_VBE_STATUS_OK) return grub_error (GRUB_ERR_IO, "Can't get VBE mode."); - mbi->vbe_mode =3D vbe_mode; =20 - status =3D grub_vbe_bios_get_mode_info (vbe_mode, scratch); + status =3D grub_vbe_bios_get_mode_info (*vbe_mode, scratch); if (status !=3D GRUB_VBE_STATUS_OK) return grub_error (GRUB_ERR_IO, "Can't get mode info."); + grub_memcpy (vbe_mode_info, scratch, + sizeof (struct grub_vbe_mode_info_block)); + + /* FIXME: retrieve those. */ + *vbe_interface_seg =3D 0; + *vbe_interface_off =3D 0; + *vbe_interface_len =3D 0; + + return GRUB_ERR_NONE; +} + +static grub_err_t +fill_vbe_info (struct multiboot_info *mbi, grub_uint8_t *ptrorig, + grub_uint32_t ptrdest) +{ + struct grub_vbe_info_block *vbe_control_info; + struct grub_vbe_mode_info_block *vbe_mode_info; + grub_err_t err; + + vbe_control_info =3D (struct grub_vbe_info_block *) ptrorig; + mbi->vbe_control_info =3D ptrdest; + ptrorig +=3D sizeof (struct grub_vbe_info_block); + ptrdest +=3D sizeof (struct grub_vbe_info_block); + + vbe_mode_info =3D (struct grub_vbe_mode_info_block *) ptrorig; =20 mbi->vbe_mode_info =3D ptrdest; - grub_memcpy (ptrorig, scratch, sizeof (struct grub_vbe_mode_info_block= )); ptrorig +=3D sizeof (struct grub_vbe_mode_info_block); ptrdest +=3D sizeof (struct grub_vbe_mode_info_block); - =20 - /* FIXME: retrieve those. */ - mbi->vbe_interface_seg =3D 0; - mbi->vbe_interface_off =3D 0; - mbi->vbe_interface_len =3D 0; + + err =3D fill_vbe_info_real (vbe_control_info, + vbe_mode_info, + &(mbi->vbe_mode), + &(mbi->vbe_interface_seg), + &(mbi->vbe_interface_off), + &(mbi->vbe_interface_len)); + if (err) + return err; =20 mbi->flags |=3D MULTIBOOT_INFO_VBE_INFO; =20 @@ -276,16 +327,221 @@ mbi->flags |=3D MULTIBOOT_INFO_FRAMEBUFFER_INFO; =20 #if HAS_VBE + fill_vbe_info (mbi, ptrorig, ptrdest); +#endif + + return GRUB_ERR_NONE; +} + +static grub_err_t +set_video_info_tagged (struct multiboot_tag_framebuffer *tag, +#if HAS_VBE + int *vbe_active +#endif + ) +{ + struct grub_video_palette_data palette[256]; + grub_err_t err; + struct grub_video_mode_info mode_info; + void *framebuffer; + + tag->common.type =3D MULTIBOOT_TAG_TYPE_FRAMEBUFFER; + tag->common.size =3D 0; + =20 + err =3D set_video_mode (); + if (err) + return err; + + grub_video_get_palette (0, ARRAY_SIZE (palette), palette); + =20 +#if HAS_VBE + { + const char *adapter_name; + adapter_name =3D grub_video_get_active_adapter_name (); + =20 + *vbe_active =3D ((adapter_name + && grub_strcmp (adapter_name, + "VESA BIOS Extension Video Driver") =3D=3D 0) + || (HAS_VGA_TEXT && !adapter_name)); + } +#endif + + err =3D grub_video_get_info_and_fini (&mode_info, &framebuffer); + if (err) + return err; + =20 + tag->common.framebuffer_addr =3D (grub_addr_t) framebuffer; + tag->common.framebuffer_pitch =3D mode_info.pitch; + + tag->common.framebuffer_width =3D mode_info.width; + tag->common.framebuffer_height =3D mode_info.height; + =20 + tag->common.framebuffer_bpp =3D mode_info.bpp; + =20 + if (mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) + { + unsigned i; + tag->common.framebuffer_type =3D MULTIBOOT_FRAMEBUFFER_TYPE_INDEXE= D; + tag->framebuffer_palette_num_colors =3D mode_info.number_of_colors= ; + if (tag->framebuffer_palette_num_colors > ARRAY_SIZE (palette)) + tag->framebuffer_palette_num_colors =3D ARRAY_SIZE (palette); + tag->common.size =3D sizeof (struct multiboot_tag_framebuffer_comm= on) + + sizeof (multiboot_uint16_t) + tag->framebuffer_palette_num_colors + * sizeof (struct multiboot_color); + for (i =3D 0; i < tag->framebuffer_palette_num_colors; i++) + { + tag->framebuffer_palette[i].red =3D palette[i].r; + tag->framebuffer_palette[i].green =3D palette[i].g; + tag->framebuffer_palette[i].blue =3D palette[i].b; + } + } + else + { + tag->common.framebuffer_type =3D MULTIBOOT_FRAMEBUFFER_TYPE_RGB; + tag->framebuffer_red_field_position =3D mode_info.green_field_pos;= + tag->framebuffer_red_mask_size =3D mode_info.green_mask_size; + tag->framebuffer_green_field_position =3D mode_info.green_field_po= s; + tag->framebuffer_green_mask_size =3D mode_info.green_mask_size; + tag->framebuffer_blue_field_position =3D mode_info.blue_field_pos;= + tag->framebuffer_blue_mask_size =3D mode_info.blue_mask_size; + + tag->common.size =3D sizeof (struct multiboot_tag_framebuffer_comm= on) + 6; + } + + return GRUB_ERR_NONE; +} + +static grub_err_t +make_mbi_tagged (void *orig, grub_uint32_t dest, grub_off_t buf_off) +{ + grub_uint8_t *ptrorig =3D (grub_uint8_t *) orig + buf_off; +#if HAS_VBE + int vbe_active =3D 0; +#endif + grub_err_t err; + + { + struct multiboot_tag_string *tag =3D (struct multiboot_tag_string *)= ptrorig; + tag->type =3D MULTIBOOT_TAG_TYPE_CMDLINE; + tag->size =3D sizeof (struct multiboot_tag_string) + + ALIGN_UP (cmdline_size, 4);=20 + grub_memcpy (tag->string, cmdline, cmdline_size); + ptrorig +=3D tag->size; + } + + { + struct multiboot_tag_string *tag =3D (struct multiboot_tag_string *)= ptrorig; + tag->type =3D MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME; + tag->size =3D sizeof (struct multiboot_tag_string) + + ALIGN_UP (sizeof (PACKAGE_STRING), 4);=20 + grub_memcpy (tag->string, PACKAGE_STRING, sizeof (PACKAGE_STRING)); + ptrorig +=3D tag->size; + } + + { + unsigned i; + struct module *cur; + + for (i =3D 0, cur =3D modules; i < modcnt; i++, cur =3D cur->next) + { + struct multiboot_tag_module *tag + =3D (struct multiboot_tag_module *) ptrorig; + tag->type =3D MULTIBOOT_TAG_TYPE_MODULE; + tag->size =3D sizeof (struct multiboot_tag_module) + + ALIGN_UP (sizeof (cur->cmdline_size), 4);=20 + + tag->mod_start =3D dest + cur->start; + tag->mod_end =3D tag->mod_start + cur->size; + grub_memcpy (tag->cmdline, cur->cmdline, cur->cmdline_size); + ptrorig +=3D tag->size; + } + } + + { + struct multiboot_tag_mmap *tag =3D (struct multiboot_tag_mmap *) ptr= orig; + tag->type =3D MULTIBOOT_TAG_TYPE_MMAP; + tag->size =3D sizeof (struct multiboot_tag_mmap)=20 + + grub_get_multiboot_mmap_len ();=20 + grub_fill_multiboot_mmap (tag->entries); + ptrorig +=3D tag->size; + } + + { + struct multiboot_tag_basic_meminfo *tag + =3D (struct multiboot_tag_basic_meminfo *) ptrorig; + tag->type =3D MULTIBOOT_TAG_TYPE_BASIC_MEMINFO; + tag->size =3D sizeof (struct multiboot_tag_basic_meminfo);=20 + + /* Convert from bytes to kilobytes. */ + tag->mem_lower =3D grub_mmap_get_lower () / 1024; + tag->mem_upper =3D grub_mmap_get_upper () / 1024; + ptrorig +=3D tag->size; + } + + if (bootdev_set) + { + struct multiboot_tag_bootdev *tag + =3D (struct multiboot_tag_bootdev *) ptrorig; + tag->type =3D MULTIBOOT_TAG_TYPE_BOOTDEV; + tag->size =3D sizeof (struct multiboot_tag_bootdev);=20 + + tag->biosdev =3D biosdev; + tag->slice =3D slice; + tag->part =3D part; + ptrorig +=3D tag->size; + } + + { + struct multiboot_tag_framebuffer *tag + =3D (struct multiboot_tag_framebuffer *) ptrorig; + err =3D set_video_info_tagged (tag, +#if HAS_VBE + &vbe_active +#endif + ); + if (err) + { + grub_print_error (); + grub_errno =3D GRUB_ERR_NONE; + } + else + ptrorig +=3D tag->common.size; + } + +#if HAS_VBE if (vbe_active) - fill_vbe_info (mbi, ptrorig, ptrdest); + { + struct multiboot_tag_vbe *tag =3D (struct multiboot_tag_vbe *) ptr= orig; + tag->type =3D MULTIBOOT_TAG_TYPE_VBE; + tag->size =3D sizeof (struct multiboot_tag_vbe); + err =3D fill_vbe_info_real (&(tag->vbe_control_info), + &(tag->vbe_mode_info), + &(tag->vbe_mode), + &(tag->vbe_interface_seg), + &(tag->vbe_interface_off), + &(tag->vbe_interface_len)); + if (err) + { + grub_print_error (); + grub_errno =3D GRUB_ERR_NONE; + } + else + ptrorig +=3D tag->size; + } #endif + =20 + { + struct multiboot_tag *tag =3D (struct multiboot_tag *) ptrorig; + tag->type =3D MULTIBOOT_TAG_TYPE_END; + tag->size =3D sizeof (struct multiboot_tag); + ptrorig +=3D tag->size; + } =20 return GRUB_ERR_NONE; } =20 -grub_err_t -grub_multiboot_make_mbi (void *orig, grub_uint32_t dest, grub_off_t buf_= off, - grub_size_t bufsize) +static grub_err_t +make_mbi (void *orig, grub_uint32_t dest, grub_off_t buf_off) { grub_uint8_t *ptrorig =3D (grub_uint8_t *) orig + buf_off; grub_uint32_t ptrdest =3D dest + buf_off; @@ -296,9 +552,6 @@ grub_size_t mmap_size; grub_err_t err; =20 - if (bufsize < grub_multiboot_get_mbi_size ()) - return grub_error (GRUB_ERR_OUT_OF_MEMORY, "mbi buffer is too small"= ); - mbi =3D (struct multiboot_info *) ptrorig; ptrorig +=3D sizeof (*mbi); ptrdest +=3D sizeof (*mbi); @@ -356,7 +609,8 @@ =20 if (bootdev_set) { - mbi->boot_device =3D bootdev; + mbi->boot_device =3D (((biosdev & 0xff) << 24) | ((slice & 0xff) <= < 16)=20 + | ((part & 0xff) << 8) | 0xff); mbi->flags |=3D MULTIBOOT_INFO_BOOTDEV; } =20 @@ -374,6 +628,19 @@ return GRUB_ERR_NONE; } =20 +grub_err_t +grub_multiboot_make_mbi (void *orig, grub_uint32_t dest, grub_off_t buf_= off, + grub_size_t bufsize) +{ + if (bufsize < grub_multiboot_get_mbi_size ()) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "mbi buffer is too small"= ); + + if (tagged) + return make_mbi_tagged (orig, dest, buf_off); + else + return make_mbi (orig, dest, buf_off); +} + void grub_multiboot_free_mbi (void) { @@ -403,6 +670,7 @@ char *p; int i; =20 + tagged =3D 0; grub_multiboot_free_mbi (); =20 for (i =3D 0; i < argc; i++) @@ -486,9 +754,11 @@ grub_multiboot_set_bootdev (void) { char *p; - grub_uint32_t biosdev, slice =3D ~0, part =3D ~0; grub_device_t dev; =20 + slice =3D ~0; + part =3D ~0; + #ifdef GRUB_MACHINE_PCBIOS biosdev =3D grub_get_root_biosnumber (); #else @@ -517,7 +787,5 @@ if (dev) grub_device_close (dev); =20 - bootdev =3D ((biosdev & 0xff) << 24) | ((slice & 0xff) << 16)=20 - | ((part & 0xff) << 8) | 0xff; bootdev_set =3D 1; } --------------020006060604080409070403 Content-Type: text/x-diff; name="mbtagged.diff" Content-Transfer-Encoding: quoted-printable Content-Disposition: inline; filename="mbtagged.diff" =3D=3D=3D 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 @@ =20 /* 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 =09 .text =3D=3D=3D 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, ...); =20 +static void +tagged (unsigned long addr) +{ + struct multiboot_tag *tag; + + for (tag =3D (struct multiboot_tag *) addr; tag->type !=3D MULTIBOOT_T= AG_TYPE_END; + tag =3D (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 =3D %s\n", + ((struct multiboot_tag_string *) tag)->string); + break; + case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME: + printf ("Boot loader name =3D %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 =3D %uKB, mem_upper =3D %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"); + =20 + for (mmap =3D ((struct multiboot_tag_mmap *) tag)->entries; + (multiboot_uint8_t *) mmap=20 + < (multiboot_uint8_t *) tag + tag->size; + mmap =3D (multiboot_memory_map_t *) ((unsigned long) mmap + + mmap->size + + sizeof (mmap->size))) + printf (" size =3D 0x%x, base_addr =3D 0x%x%x," + " length =3D 0x%x%x, type =3D 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 + =3D (struct multiboot_tag_framebuffer *) tag; + void *fb =3D (void *) (unsigned long) tagfb->common.framebuffer_add= r; + + switch (tagfb->common.framebuffer_type) + { + case MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED: + { + unsigned best_distance, distance; + struct multiboot_color *palette; + =20 + palette =3D tagfb->framebuffer_palette; + + color =3D 0; + best_distance =3D 4*256*256; + =20 + for (i =3D 0; i < tagfb->framebuffer_palette_num_colors; i++) + { + distance =3D (0xff - palette[i].blue)=20 + * (0xff - palette[i].blue) + + palette[i].red * palette[i].red + + palette[i].green * palette[i].green; + if (distance < best_distance) + { + color =3D i; + best_distance =3D distance; + } + } + } + break; + + case MULTIBOOT_FRAMEBUFFER_TYPE_RGB: + color =3D ((1 << tagfb->framebuffer_blue_mask_size) - 1)=20 + << tagfb->framebuffer_blue_field_position; + break; + + default: + color =3D 0xffffffff; + break; + } + =20 + for (i =3D 0; i < tagfb->common.framebuffer_width + && i < tagfb->common.framebuffer_height; i++) + { + switch (tagfb->common.framebuffer_bpp) + { + case 8: + { + multiboot_uint8_t *pixel =3D fb + + tagfb->common.framebuffer_pitch * i + i; + *pixel =3D color; + } + break; + case 15: + case 16: + { + multiboot_uint16_t *pixel + =3D fb + tagfb->common.framebuffer_pitch * i + 2 * i; + *pixel =3D color; + } + break; + case 24: + { + multiboot_uint32_t *pixel + =3D fb + tagfb->common.framebuffer_pitch * i + 3 * i; + *pixel =3D (color & 0xffffff) | (*pixel & 0xff000000); + } + break; + + case 32: + { + multiboot_uint32_t *pixel + =3D fb + tagfb->common.framebuffer_pitch * i + 4 * i; + *pixel =3D 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 (); =20 + if (magic =3D=3D MULTIBOOT_BOOTLOADER_MAGIC_TAGGED) + { + tagged (addr); + return; + } + /* Am I booted by a Multiboot-compliant boot loader? */ if (magic !=3D MULTIBOOT_BOOTLOADER_MAGIC) { =3D=3D=3D 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 =20 +/* 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 =20 /* Alignment of multiboot modules. */ #define MULTIBOOT_MOD_ALIGN 0x00001000 @@ -51,6 +54,9 @@ /* Must pass video information to OS. */ #define MULTIBOOT_VIDEO_MODE 0x00000004 =20 +/* 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 =20 @@ -254,6 +260,122 @@ }; typedef struct multiboot_mod_list multiboot_module_t; =20 +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]; =20 +}; + +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 */ =20 #endif /* ! MULTIBOOT_HEADER */ =3D=3D=3D 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. =20 +If bit 3 in the @samp{flags} word is set, the multiboot information=20 +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 @@ =20 @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-tagge= d 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 @@ =20 =20 @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 =20 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. =20 +@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 o= f type @samp{0} and size @samp{8}. + +@subsection Basic non-tagged structure The format of the Multiboot information structure (as defined so far) follows: =20 @@ -655,6 +676,7 @@ information structure to be expanded in the future without breaking anything. =20 +@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. =20 +Corresponding tag is: + +@example +@group + +-------------------+ +0 | type =3D 4 | +4 | size =3D 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. =20 +Corresponding tag is: +@example +@group + +-------------------+ +0 | type =3D 5 | +4 | size =3D 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 =3D 1 | +4 | size | +8-xx | string | + +-------------------+ +@end group +@end example + +@samp{string} contains zero-terminated UTF-8 string padded to have lengt= h 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. =20 +Corresponding tag is: + +@example +@group + +-------------------+ +0 | type =3D 3 | +4 | size | +8 | mod_start | +12 | mod_end | +16-xx | string | =20 + +-------------------+ +@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. =20 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. =20 +@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. =20 +The corresponding tag is +@example +@group + +-------------------+ +0 | type =3D 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). =20 +@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}. =20 +@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. =20 +Corresponding tag is: +@example +@group + +-------------------+ +0 | type =3D 2 | +4 | size | +8-xx | string | + +-------------------+ +@end group +@end example + +@samp{string} contains zero-terminated UTF-8 string padded to have lengt= h 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. =20 +@subsection VBE info If bit 11 in the @samp{flags} is set, the @sc{vbe} table is available. =20 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. =20 +Corresponding tag is: +@example +@group + +-------------------+ +0 | type =3D 7 | +4 | size =3D 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 avai= lable. =20 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 fi= elds @samp{framebuffer_width}, @samp{framebuffer_height} contain framebuf= fer dimensions in pixels. The field @samp{framebuffer_bpp} contains numbe= r of bits per pixel. If @samp{framebuffer_type} is set to 0 it means inde= xed 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 ch= aracters and not in pixels. @samp{framebuffer_bpp} is equal 16 (16 bits p= er character) and @samp{framebuffer_pitch} is expressed in bytes per text= line. All further values of @samp{framebuffer_type} are reserved for future ex= pansion =20 +Corresponding tag is: +@example +@group + +--------------------+ +0 | type =3D 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 form= at: + +@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 addres= s. + +If @samp{framebuffer_type} is @samp{1} or @samp{2} color_info has the s= ame format as non-tagged version. + @node Examples @chapter Examples =20 --------------020006060604080409070403-- --------------enigC19BAAC415D345DFBB42FFC2 Content-Type: application/pgp-signature; name="signature.asc" Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="signature.asc" -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iF4EAREKAAYFAktCWdkACgkQNak7dOguQgnD4wD/TTBt3RcwAcOsIcSBdKIZT4FU g7r6q16kxvWt2wp6/awA/jGu/1NyqIgoSs40DdmzNkIm11ahjUrndBaAP0v0D9ng =8Axz -----END PGP SIGNATURE----- --------------enigC19BAAC415D345DFBB42FFC2--