thank you for response.
Sorry for the confusion. It was my fault. I just use qemu to debug my
change.It is a kernel panic. It panic so early, so that I made a mistake and
consideredit as a panic in grub.
I am using grub repo (revno: 3116). Now, I can see the kernel panic message:
"PANIC: early exception 08 rip 246:10 error ffffff8102b785 cr2
ffffffffff47900b"The panic message comes from linux kernel: early_idt_handlers
in the filearch/x86/kernel/head_64.S.
So, it doesn't matter with grub.
/* For the Linux/i386 boot protocol version 2.03. */ struct
linux_kernel_header {@@ -130,6 +146,8 @@ grub_uint16_t pad1;
/* Unused */ grub_uint32_t cmd_line_ptr; /* Points to the kernel
command line */ grub_uint32_t initrd_addr_max; /* Highest address for
initrd */+ grub_uint32_t pad2[8];+ grub_uint64_t setup_data; } __attribute__
((packed));And then, I tried to use setup_data field to pass an pointer (which
points to a binaryblob) to Linux kernel, === modified file
'grub-core/loader/i386/linux.c'--- grub-core/loader/i386/linux.c
2011-03-09 17:38:31 +0000+++ grub-core/loader/i386/linux.c 2011-03-28
15:44:34 +0000@@ -994,7 +994,89 @@ return grub_errno; }
-static grub_command_t cmd_linux, cmd_initrd;+static grub_err_t+grub_cmd_ucode
(grub_command_t cmd __attribute__ ((unused)),+ int argc, char
*argv[])+{+ grub_file_t file = 0;+ grub_ssize_t size;+ grub_addr_t addr_min,
addr_max;+ grub_err_t err;+ struct linux_kernel_header *lh;+
grub_relocator_chunk_t ch;+ void *ucode_mem;+ grub_addr_t ucode_mem_target;+
struct setup_data *hdr;++ if (argc == 0)+ {+ grub_error
(GRUB_ERR_BAD_ARGUMENT, "no module specified");+ goto fail;+ }++ if (!
loaded)+ {+ grub_error (GRUB_ERR_BAD_ARGUMENT, "you need to load the
kernel first");+ goto fail;+ }++ grub_file_filter_disable_compression
();+ file = grub_file_open (argv[0]);+ size = grub_file_size(file);++ lh =
(struct linux_kernel_header *) real_mode_mem;+ if
(grub_le_to_cpu16(lh->version) < 0x0209)+ {+ grub_printf("%s:%d: header
version=0x%x(<0x0209)\n",+ __FUNCTION__, __LINE__, lh->version);+
goto fail;+ }++ addr_max = grub_cpu_to_le32(lh->initrd_addr_max);+ if
(addr_max > GRUB_LINUX_INITRD_MAX_ADDRESS)+ addr_max =
GRUB_LINUX_INITRD_MAX_ADDRESS;+ addr_max -= 0x10000;++ if ((linux_mem_size !=
0) && (linux_mem_size < addr_max))+ addr_max = linux_mem_size;+ addr_max
= (addr_max - size - sizeof(*hdr)) & ~0xFFF;+ addr_min = prot_mode_target;++
grub_printf("microcode addr_min=%p, add_max=%p\n", + (void*)addr_min,
(void *)addr_max);++ err = grub_relocator_alloc_chunk_align(relocator, &ch,
addr_min,+ addr_max, size +
sizeof(*hdr),+ 0x1000,
GRUB_RELOCATOR_PREFERENCE_HIGH);+ if (err) return err;+ ucode_mem =
get_virtual_current_address(ch);+ ucode_mem_target =
get_physical_target_address(ch);++ if (grub_file_read(file, (unsigned
char*)ucode_mem + sizeof(*hdr), size) != size)+ {+ grub_error
(GRUB_ERR_FILE_READ_ERROR, "couldn't read file");+ goto fail;+ }++
hdr = (struct setup_data *)ucode_mem;+ hdr->type = SETUP_MICROCODE;+ hdr->len
= size;+ hdr->next = 0;++ lh->setup_data = ucode_mem_target;++
grub_printf("%s: header_version=0x%x, ucode_size=%d\n", __FUNCTION__,+
grub_le_to_cpu16 (lh->version), size);+ ++ fail:+ if (file)+
grub_file_close (file);++ return grub_errno;+}++static grub_command_t
cmd_linux, cmd_initrd, cmd_ucode;
thanks,-minskey
=== modified file 'grub-core/loader/i386/linux.c'
--- grub-core/loader/i386/linux.c 2011-03-09 17:38:31 +0000
+++ grub-core/loader/i386/linux.c 2011-03-28 15:44:34 +0000
@@ -994,7 +994,89 @@
return grub_errno;
}
-static grub_command_t cmd_linux, cmd_initrd;
+static grub_err_t
+grub_cmd_ucode (grub_command_t cmd __attribute__ ((unused)),
+ int argc, char *argv[])
+{
+ grub_file_t file = 0;
+ grub_ssize_t size;
+ grub_addr_t addr_min, addr_max;
+ grub_err_t err;
+ struct linux_kernel_header *lh;
+ grub_relocator_chunk_t ch;
+ void *ucode_mem;
+ grub_addr_t ucode_mem_target;
+ struct setup_data *hdr;
+
+ if (argc == 0)
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT, "no module specified");
+ goto fail;
+ }
+
+ if (! loaded)
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT, "you need to load the kernel first");
+ goto fail;
+ }
+
+ grub_file_filter_disable_compression ();
+ file = grub_file_open (argv[0]);
+ size = grub_file_size(file);
+
+ lh = (struct linux_kernel_header *) real_mode_mem;
+ if (grub_le_to_cpu16(lh->version) < 0x0209)
+ {
+ grub_printf("%s:%d: header version=0x%x(<0x0209)\n",
+ __FUNCTION__, __LINE__, lh->version);
+ goto fail;
+ }
+
+ addr_max = grub_cpu_to_le32(lh->initrd_addr_max);
+ if (addr_max > GRUB_LINUX_INITRD_MAX_ADDRESS)
+ addr_max = GRUB_LINUX_INITRD_MAX_ADDRESS;
+ addr_max -= 0x10000;
+
+ if ((linux_mem_size != 0) && (linux_mem_size < addr_max))
+ addr_max = linux_mem_size;
+ addr_max = (addr_max - size - sizeof(*hdr)) & ~0xFFF;
+ addr_min = prot_mode_target;
+
+ grub_printf("microcode addr_min=%p, add_max=%p\n",
+ (void*)addr_min, (void *)addr_max);
+
+ err = grub_relocator_alloc_chunk_align(relocator, &ch, addr_min,
+ addr_max, size + sizeof(*hdr),
+ 0x1000, GRUB_RELOCATOR_PREFERENCE_HIGH);
+ if (err) return err;
+ ucode_mem = get_virtual_current_address(ch);
+ ucode_mem_target = get_physical_target_address(ch);
+
+ if (grub_file_read(file, (unsigned char*)ucode_mem + sizeof(*hdr), size) != size)
+ {
+ grub_error (GRUB_ERR_FILE_READ_ERROR, "couldn't read file");
+ goto fail;
+ }
+
+ hdr = (struct setup_data *)ucode_mem;
+ hdr->type = SETUP_MICROCODE;
+ hdr->len = size;
+ hdr->next = 0;
+
+ lh->setup_data = ucode_mem_target;
+
+ grub_printf("%s: header_version=0x%x, ucode_size=%d\n", __FUNCTION__,
+ grub_le_to_cpu16 (lh->version), size);
+
+
+ fail:
+ if (file)
+ grub_file_close (file);
+
+ return grub_errno;
+}
+
+static grub_command_t cmd_linux, cmd_initrd, cmd_ucode;
GRUB_MOD_INIT(linux)
{
@@ -1002,6 +1084,8 @@
0, N_("Load Linux."));
cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd,
0, N_("Load initrd."));
+ cmd_ucode = grub_register_command ("microcode", grub_cmd_ucode,
+ 0, N_("Load microcode."));
my_mod = mod;
}
@@ -1009,4 +1093,5 @@
{
grub_unregister_command (cmd_linux);
grub_unregister_command (cmd_initrd);
+ grub_unregister_command (cmd_ucode);
}
=== modified file 'include/grub/i386/linux.h'
--- include/grub/i386/linux.h 2011-01-10 23:02:01 +0000
+++ include/grub/i386/linux.h 2011-03-28 09:41:12 +0000
@@ -87,6 +87,22 @@
GRUB_VIDEO_LINUX_TYPE_SIMPLE = 0x70 /* Linear framebuffer without any additional functions. */
};
+/* setup data types */
+#define SETUP_NONE 0
+#define SETUP_E820_EXT 1
+#define SETUP_DTB 2
+#define SETUP_MICROCODE 3
+
+/* extensible setup data list node */
+struct setup_data {
+ grub_uint64_t next;
+ grub_uint32_t type;
+ grub_uint32_t len;
+ grub_uint8_t data[0];
+} __attribute__ ((packed));
+
+
+
/* For the Linux/i386 boot protocol version 2.03. */
struct linux_kernel_header
{
@@ -130,6 +146,8 @@
grub_uint16_t pad1; /* Unused */
grub_uint32_t cmd_line_ptr; /* Points to the kernel command line */
grub_uint32_t initrd_addr_max; /* Highest address for initrd */
+ grub_uint32_t pad2[8];
+ grub_uint64_t setup_data;
} __attribute__ ((packed));
/* Boot parameters for Linux based on 2.6.12. This is used by the setup
_______________________________________________
Grub-devel mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/grub-devel