diff options
author | Jarkko Sakkinen <jarkko.sakkinen@intel.com> | 2012-05-08 14:22:29 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2012-05-08 14:46:05 -0400 |
commit | c9b77ccb52a5c77233b0e557b7d4417b00ef4012 (patch) | |
tree | 152d1c9b60796db21458583a76b57f995c4cd3bf /arch/x86/realmode | |
parent | 48927bbb97c7d4cf343c05827ab9ac30c60678cb (diff) |
x86, realmode: Move ACPI wakeup to unified realmode code
Migrated ACPI wakeup code to the real-mode blob.
Code existing in .x86_trampoline can be completely
removed. Static descriptor table in wakeup_asm.S is
courtesy of H. Peter Anvin.
Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@intel.com>
Link: http://lkml.kernel.org/r/1336501366-28617-7-git-send-email-jarkko.sakkinen@intel.com
Cc: Rafael J. Wysocki <rjw@sisk.pl>
Cc: Len Brown <len.brown@intel.com>
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Diffstat (limited to 'arch/x86/realmode')
-rw-r--r-- | arch/x86/realmode/rm/Makefile | 4 | ||||
-rw-r--r-- | arch/x86/realmode/rm/header.S | 5 | ||||
-rw-r--r-- | arch/x86/realmode/rm/realmode.lds.S | 4 | ||||
-rw-r--r-- | arch/x86/realmode/rm/wakeup/.gitignore | 3 | ||||
-rw-r--r-- | arch/x86/realmode/rm/wakeup/Makefile | 33 | ||||
-rw-r--r-- | arch/x86/realmode/rm/wakeup/bioscall.S | 1 | ||||
-rw-r--r-- | arch/x86/realmode/rm/wakeup/copy.S | 1 | ||||
-rw-r--r-- | arch/x86/realmode/rm/wakeup/regs.c | 1 | ||||
-rw-r--r-- | arch/x86/realmode/rm/wakeup/video-bios.c | 1 | ||||
-rw-r--r-- | arch/x86/realmode/rm/wakeup/video-mode.c | 1 | ||||
-rw-r--r-- | arch/x86/realmode/rm/wakeup/video-vesa.c | 1 | ||||
-rw-r--r-- | arch/x86/realmode/rm/wakeup/video-vga.c | 1 | ||||
-rw-r--r-- | arch/x86/realmode/rm/wakeup/wakemain.c | 82 | ||||
-rw-r--r-- | arch/x86/realmode/rm/wakeup/wakeup.h | 41 | ||||
-rw-r--r-- | arch/x86/realmode/rm/wakeup/wakeup_asm.S | 189 |
15 files changed, 368 insertions, 0 deletions
diff --git a/arch/x86/realmode/rm/Makefile b/arch/x86/realmode/rm/Makefile index 56ec64f94e69..2432acb6b04f 100644 --- a/arch/x86/realmode/rm/Makefile +++ b/arch/x86/realmode/rm/Makefile | |||
@@ -14,9 +14,13 @@ always := realmode.bin | |||
14 | realmode-y += header.o | 14 | realmode-y += header.o |
15 | realmode-$(CONFIG_X86_32) += reboot_32.o | 15 | realmode-$(CONFIG_X86_32) += reboot_32.o |
16 | realmode-y += trampoline_$(BITS).o | 16 | realmode-y += trampoline_$(BITS).o |
17 | realmode-$(CONFIG_ACPI_SLEEP) += wakeup/wakeup.o | ||
17 | 18 | ||
18 | targets += $(realmode-y) | 19 | targets += $(realmode-y) |
19 | 20 | ||
21 | $(obj)/wakeup/wakeup.o: FORCE | ||
22 | $(Q)$(MAKE) $(build)=$(obj)/wakeup $@ | ||
23 | |||
20 | REALMODE_OBJS = $(addprefix $(obj)/,$(realmode-y)) | 24 | REALMODE_OBJS = $(addprefix $(obj)/,$(realmode-y)) |
21 | 25 | ||
22 | sed-pasyms := -n -r -e 's/^([0-9a-fA-F]+) [ABCDGRSTVW] (.+)$$/pa_\2 = \2;/p' | 26 | sed-pasyms := -n -r -e 's/^([0-9a-fA-F]+) [ABCDGRSTVW] (.+)$$/pa_\2 = \2;/p' |
diff --git a/arch/x86/realmode/rm/header.S b/arch/x86/realmode/rm/header.S index a97900409c61..730b1316c099 100644 --- a/arch/x86/realmode/rm/header.S +++ b/arch/x86/realmode/rm/header.S | |||
@@ -27,4 +27,9 @@ ENTRY(real_mode_header) | |||
27 | .long pa_level3_ident_pgt | 27 | .long pa_level3_ident_pgt |
28 | .long pa_level3_kernel_pgt | 28 | .long pa_level3_kernel_pgt |
29 | #endif | 29 | #endif |
30 | /* ACPI sleep */ | ||
31 | #ifdef CONFIG_ACPI_SLEEP | ||
32 | .long pa_wakeup_start | ||
33 | .long pa_wakeup_header | ||
34 | #endif | ||
30 | END(real_mode_header) | 35 | END(real_mode_header) |
diff --git a/arch/x86/realmode/rm/realmode.lds.S b/arch/x86/realmode/rm/realmode.lds.S index c5b8a4f31ba3..91b83ea55c37 100644 --- a/arch/x86/realmode/rm/realmode.lds.S +++ b/arch/x86/realmode/rm/realmode.lds.S | |||
@@ -25,6 +25,10 @@ SECTIONS | |||
25 | .rodata : { | 25 | .rodata : { |
26 | *(.rodata) | 26 | *(.rodata) |
27 | *(.rodata.*) | 27 | *(.rodata.*) |
28 | . = ALIGN(16); | ||
29 | video_cards = .; | ||
30 | *(.videocards) | ||
31 | video_cards_end = .; | ||
28 | } | 32 | } |
29 | 33 | ||
30 | . = ALIGN(PAGE_SIZE); | 34 | . = ALIGN(PAGE_SIZE); |
diff --git a/arch/x86/realmode/rm/wakeup/.gitignore b/arch/x86/realmode/rm/wakeup/.gitignore new file mode 100644 index 000000000000..58f1f48a58f8 --- /dev/null +++ b/arch/x86/realmode/rm/wakeup/.gitignore | |||
@@ -0,0 +1,3 @@ | |||
1 | wakeup.bin | ||
2 | wakeup.elf | ||
3 | wakeup.lds | ||
diff --git a/arch/x86/realmode/rm/wakeup/Makefile b/arch/x86/realmode/rm/wakeup/Makefile new file mode 100644 index 000000000000..4c8533240cdd --- /dev/null +++ b/arch/x86/realmode/rm/wakeup/Makefile | |||
@@ -0,0 +1,33 @@ | |||
1 | # | ||
2 | # arch/x86/kernel/acpi/realmode/Makefile | ||
3 | # | ||
4 | # This file is subject to the terms and conditions of the GNU General Public | ||
5 | # License. See the file "COPYING" in the main directory of this archive | ||
6 | # for more details. | ||
7 | # | ||
8 | |||
9 | always := wakeup.o | ||
10 | |||
11 | wakeup-y += wakeup_asm.o wakemain.o video-mode.o | ||
12 | wakeup-y += copy.o bioscall.o regs.o | ||
13 | |||
14 | # The link order of the video-*.o modules can matter. In particular, | ||
15 | # video-vga.o *must* be listed first, followed by video-vesa.o. | ||
16 | # Hardware-specific drivers should follow in the order they should be | ||
17 | # probed, and video-bios.o should typically be last. | ||
18 | wakeup-y += video-vga.o | ||
19 | wakeup-y += video-vesa.o | ||
20 | wakeup-y += video-bios.o | ||
21 | |||
22 | targets += $(wakeup-y) | ||
23 | |||
24 | WAKEUP_OBJS = $(addprefix $(obj)/,$(wakeup-y)) | ||
25 | |||
26 | LDFLAGS_wakeup.o := -m elf_i386 -r | ||
27 | $(obj)/wakeup.o: $(WAKEUP_OBJS) FORCE | ||
28 | $(call if_changed,ld) | ||
29 | |||
30 | bootsrc := $(src)/../../../boot | ||
31 | |||
32 | ccflags-y += -D_WAKEUP -I$(srctree)/$(bootsrc) | ||
33 | asflags-y += -D_WAKEUP -I$(srctree)/$(bootsrc) | ||
diff --git a/arch/x86/realmode/rm/wakeup/bioscall.S b/arch/x86/realmode/rm/wakeup/bioscall.S new file mode 100644 index 000000000000..f51eb0bb56ce --- /dev/null +++ b/arch/x86/realmode/rm/wakeup/bioscall.S | |||
@@ -0,0 +1 @@ | |||
#include "../../../boot/bioscall.S" | |||
diff --git a/arch/x86/realmode/rm/wakeup/copy.S b/arch/x86/realmode/rm/wakeup/copy.S new file mode 100644 index 000000000000..dc59ebee69d8 --- /dev/null +++ b/arch/x86/realmode/rm/wakeup/copy.S | |||
@@ -0,0 +1 @@ | |||
#include "../../../boot/copy.S" | |||
diff --git a/arch/x86/realmode/rm/wakeup/regs.c b/arch/x86/realmode/rm/wakeup/regs.c new file mode 100644 index 000000000000..6206033ba202 --- /dev/null +++ b/arch/x86/realmode/rm/wakeup/regs.c | |||
@@ -0,0 +1 @@ | |||
#include "../../../boot/regs.c" | |||
diff --git a/arch/x86/realmode/rm/wakeup/video-bios.c b/arch/x86/realmode/rm/wakeup/video-bios.c new file mode 100644 index 000000000000..7deabc144a27 --- /dev/null +++ b/arch/x86/realmode/rm/wakeup/video-bios.c | |||
@@ -0,0 +1 @@ | |||
#include "../../../boot/video-bios.c" | |||
diff --git a/arch/x86/realmode/rm/wakeup/video-mode.c b/arch/x86/realmode/rm/wakeup/video-mode.c new file mode 100644 index 000000000000..328ad209f113 --- /dev/null +++ b/arch/x86/realmode/rm/wakeup/video-mode.c | |||
@@ -0,0 +1 @@ | |||
#include "../../../boot/video-mode.c" | |||
diff --git a/arch/x86/realmode/rm/wakeup/video-vesa.c b/arch/x86/realmode/rm/wakeup/video-vesa.c new file mode 100644 index 000000000000..9dbb9672226a --- /dev/null +++ b/arch/x86/realmode/rm/wakeup/video-vesa.c | |||
@@ -0,0 +1 @@ | |||
#include "../../../boot/video-vesa.c" | |||
diff --git a/arch/x86/realmode/rm/wakeup/video-vga.c b/arch/x86/realmode/rm/wakeup/video-vga.c new file mode 100644 index 000000000000..bcc81255f374 --- /dev/null +++ b/arch/x86/realmode/rm/wakeup/video-vga.c | |||
@@ -0,0 +1 @@ | |||
#include "../../../boot/video-vga.c" | |||
diff --git a/arch/x86/realmode/rm/wakeup/wakemain.c b/arch/x86/realmode/rm/wakeup/wakemain.c new file mode 100644 index 000000000000..91405d515ec6 --- /dev/null +++ b/arch/x86/realmode/rm/wakeup/wakemain.c | |||
@@ -0,0 +1,82 @@ | |||
1 | #include "wakeup.h" | ||
2 | #include "boot.h" | ||
3 | |||
4 | static void udelay(int loops) | ||
5 | { | ||
6 | while (loops--) | ||
7 | io_delay(); /* Approximately 1 us */ | ||
8 | } | ||
9 | |||
10 | static void beep(unsigned int hz) | ||
11 | { | ||
12 | u8 enable; | ||
13 | |||
14 | if (!hz) { | ||
15 | enable = 0x00; /* Turn off speaker */ | ||
16 | } else { | ||
17 | u16 div = 1193181/hz; | ||
18 | |||
19 | outb(0xb6, 0x43); /* Ctr 2, squarewave, load, binary */ | ||
20 | io_delay(); | ||
21 | outb(div, 0x42); /* LSB of counter */ | ||
22 | io_delay(); | ||
23 | outb(div >> 8, 0x42); /* MSB of counter */ | ||
24 | io_delay(); | ||
25 | |||
26 | enable = 0x03; /* Turn on speaker */ | ||
27 | } | ||
28 | inb(0x61); /* Dummy read of System Control Port B */ | ||
29 | io_delay(); | ||
30 | outb(enable, 0x61); /* Enable timer 2 output to speaker */ | ||
31 | io_delay(); | ||
32 | } | ||
33 | |||
34 | #define DOT_HZ 880 | ||
35 | #define DASH_HZ 587 | ||
36 | #define US_PER_DOT 125000 | ||
37 | |||
38 | /* Okay, this is totally silly, but it's kind of fun. */ | ||
39 | static void send_morse(const char *pattern) | ||
40 | { | ||
41 | char s; | ||
42 | |||
43 | while ((s = *pattern++)) { | ||
44 | switch (s) { | ||
45 | case '.': | ||
46 | beep(DOT_HZ); | ||
47 | udelay(US_PER_DOT); | ||
48 | beep(0); | ||
49 | udelay(US_PER_DOT); | ||
50 | break; | ||
51 | case '-': | ||
52 | beep(DASH_HZ); | ||
53 | udelay(US_PER_DOT * 3); | ||
54 | beep(0); | ||
55 | udelay(US_PER_DOT); | ||
56 | break; | ||
57 | default: /* Assume it's a space */ | ||
58 | udelay(US_PER_DOT * 3); | ||
59 | break; | ||
60 | } | ||
61 | } | ||
62 | } | ||
63 | |||
64 | void main(void) | ||
65 | { | ||
66 | /* Kill machine if structures are wrong */ | ||
67 | if (wakeup_header.real_magic != 0x12345678) | ||
68 | while (1) | ||
69 | ; | ||
70 | |||
71 | if (wakeup_header.realmode_flags & 4) | ||
72 | send_morse("...-"); | ||
73 | |||
74 | if (wakeup_header.realmode_flags & 1) | ||
75 | asm volatile("lcallw $0xc000,$3"); | ||
76 | |||
77 | if (wakeup_header.realmode_flags & 2) { | ||
78 | /* Need to call BIOS */ | ||
79 | probe_cards(0); | ||
80 | set_mode(wakeup_header.video_mode); | ||
81 | } | ||
82 | } | ||
diff --git a/arch/x86/realmode/rm/wakeup/wakeup.h b/arch/x86/realmode/rm/wakeup/wakeup.h new file mode 100644 index 000000000000..2dfaf06b8af1 --- /dev/null +++ b/arch/x86/realmode/rm/wakeup/wakeup.h | |||
@@ -0,0 +1,41 @@ | |||
1 | /* | ||
2 | * Definitions for the wakeup data structure at the head of the | ||
3 | * wakeup code. | ||
4 | */ | ||
5 | |||
6 | #ifndef ARCH_X86_KERNEL_ACPI_RM_WAKEUP_H | ||
7 | #define ARCH_X86_KERNEL_ACPI_RM_WAKEUP_H | ||
8 | |||
9 | #ifndef __ASSEMBLY__ | ||
10 | #include <linux/types.h> | ||
11 | |||
12 | /* This must match data at wakeup.S */ | ||
13 | struct wakeup_header { | ||
14 | u16 video_mode; /* Video mode number */ | ||
15 | u32 pmode_entry; /* Protected mode resume point, 32-bit only */ | ||
16 | u16 pmode_cs; | ||
17 | u32 pmode_cr0; /* Protected mode cr0 */ | ||
18 | u32 pmode_cr3; /* Protected mode cr3 */ | ||
19 | u32 pmode_cr4; /* Protected mode cr4 */ | ||
20 | u32 pmode_efer_low; /* Protected mode EFER */ | ||
21 | u32 pmode_efer_high; | ||
22 | u64 pmode_gdt; | ||
23 | u32 pmode_misc_en_low; /* Protected mode MISC_ENABLE */ | ||
24 | u32 pmode_misc_en_high; | ||
25 | u32 pmode_behavior; /* Wakeup routine behavior flags */ | ||
26 | u32 realmode_flags; | ||
27 | u32 real_magic; | ||
28 | u32 signature; /* To check we have correct structure */ | ||
29 | } __attribute__((__packed__)); | ||
30 | |||
31 | extern struct wakeup_header wakeup_header; | ||
32 | #endif | ||
33 | |||
34 | #define WAKEUP_HEADER_OFFSET 8 | ||
35 | #define WAKEUP_HEADER_SIGNATURE 0x51ee1111 | ||
36 | #define WAKEUP_END_SIGNATURE 0x65a22c82 | ||
37 | |||
38 | /* Wakeup behavior bits */ | ||
39 | #define WAKEUP_BEHAVIOR_RESTORE_MISC_ENABLE 0 | ||
40 | |||
41 | #endif /* ARCH_X86_KERNEL_ACPI_RM_WAKEUP_H */ | ||
diff --git a/arch/x86/realmode/rm/wakeup/wakeup_asm.S b/arch/x86/realmode/rm/wakeup/wakeup_asm.S new file mode 100644 index 000000000000..b61126cb599e --- /dev/null +++ b/arch/x86/realmode/rm/wakeup/wakeup_asm.S | |||
@@ -0,0 +1,189 @@ | |||
1 | /* | ||
2 | * ACPI wakeup real mode startup stub | ||
3 | */ | ||
4 | #include <asm/segment.h> | ||
5 | #include <asm/msr-index.h> | ||
6 | #include <asm/page_types.h> | ||
7 | #include <asm/pgtable_types.h> | ||
8 | #include <asm/processor-flags.h> | ||
9 | #include "wakeup.h" | ||
10 | |||
11 | .code16 | ||
12 | |||
13 | /* This should match the structure in wakeup.h */ | ||
14 | .section ".data", "aw" | ||
15 | .globl wakeup_header | ||
16 | wakeup_header: | ||
17 | video_mode: .short 0 /* Video mode number */ | ||
18 | pmode_entry: .long 0 | ||
19 | pmode_cs: .short __KERNEL_CS | ||
20 | pmode_cr0: .long 0 /* Saved %cr0 */ | ||
21 | pmode_cr3: .long 0 /* Saved %cr3 */ | ||
22 | pmode_cr4: .long 0 /* Saved %cr4 */ | ||
23 | pmode_efer: .quad 0 /* Saved EFER */ | ||
24 | pmode_gdt: .quad 0 | ||
25 | pmode_misc_en: .quad 0 /* Saved MISC_ENABLE MSR */ | ||
26 | pmode_behavior: .long 0 /* Wakeup behavior flags */ | ||
27 | realmode_flags: .long 0 | ||
28 | real_magic: .long 0 | ||
29 | signature: .long WAKEUP_HEADER_SIGNATURE | ||
30 | .size wakeup_header, .-wakeup_header | ||
31 | |||
32 | .text | ||
33 | .code16 | ||
34 | .globl wakeup_start | ||
35 | wakeup_start: | ||
36 | cli | ||
37 | cld | ||
38 | |||
39 | .byte 0xea /* ljmpw */ | ||
40 | .word 3f | ||
41 | .word real_mode_seg | ||
42 | 3: | ||
43 | /* Apparently some dimwit BIOS programmers don't know how to | ||
44 | program a PM to RM transition, and we might end up here with | ||
45 | junk in the data segment descriptor registers. The only way | ||
46 | to repair that is to go into PM and fix it ourselves... */ | ||
47 | movw $16, %cx | ||
48 | lgdtl %cs:wakeup_gdt | ||
49 | movl %cr0, %eax | ||
50 | orb $X86_CR0_PE, %al | ||
51 | movl %eax, %cr0 | ||
52 | ljmpw $8, $2f | ||
53 | 2: | ||
54 | movw %cx, %ds | ||
55 | movw %cx, %es | ||
56 | movw %cx, %ss | ||
57 | movw %cx, %fs | ||
58 | movw %cx, %gs | ||
59 | |||
60 | andb $~X86_CR0_PE, %al | ||
61 | movl %eax, %cr0 | ||
62 | .byte 0xea /* ljmpw */ | ||
63 | .word 3f | ||
64 | .word real_mode_seg | ||
65 | 3: | ||
66 | /* Set up segments */ | ||
67 | movw %cs, %ax | ||
68 | movw %ax, %ds | ||
69 | movw %ax, %es | ||
70 | movw %ax, %ss | ||
71 | lidtl wakeup_idt | ||
72 | |||
73 | movl $wakeup_stack_end, %esp | ||
74 | |||
75 | /* Clear the EFLAGS */ | ||
76 | pushl $0 | ||
77 | popfl | ||
78 | |||
79 | /* Check header signature... */ | ||
80 | movl signature, %eax | ||
81 | cmpl $WAKEUP_HEADER_SIGNATURE, %eax | ||
82 | jne bogus_real_magic | ||
83 | |||
84 | /* Check we really have everything... */ | ||
85 | movl end_signature, %eax | ||
86 | cmpl $WAKEUP_END_SIGNATURE, %eax | ||
87 | jne bogus_real_magic | ||
88 | |||
89 | /* Call the C code */ | ||
90 | calll main | ||
91 | |||
92 | /* Restore MISC_ENABLE before entering protected mode, in case | ||
93 | BIOS decided to clear XD_DISABLE during S3. */ | ||
94 | movl pmode_behavior, %eax | ||
95 | btl $WAKEUP_BEHAVIOR_RESTORE_MISC_ENABLE, %eax | ||
96 | jnc 1f | ||
97 | |||
98 | movl pmode_misc_en, %eax | ||
99 | movl pmode_misc_en + 4, %edx | ||
100 | movl $MSR_IA32_MISC_ENABLE, %ecx | ||
101 | wrmsr | ||
102 | 1: | ||
103 | |||
104 | /* Do any other stuff... */ | ||
105 | |||
106 | #ifndef CONFIG_64BIT | ||
107 | /* This could also be done in C code... */ | ||
108 | movl pmode_cr3, %eax | ||
109 | movl %eax, %cr3 | ||
110 | |||
111 | movl pmode_cr4, %ecx | ||
112 | jecxz 1f | ||
113 | movl %ecx, %cr4 | ||
114 | 1: | ||
115 | movl pmode_efer, %eax | ||
116 | movl pmode_efer + 4, %edx | ||
117 | movl %eax, %ecx | ||
118 | orl %edx, %ecx | ||
119 | jz 1f | ||
120 | movl $MSR_EFER, %ecx | ||
121 | wrmsr | ||
122 | 1: | ||
123 | |||
124 | lgdtl pmode_gdt | ||
125 | |||
126 | /* This really couldn't... */ | ||
127 | movl pmode_cr0, %eax | ||
128 | movl %eax, %cr0 | ||
129 | ljmpl *pmode_entry | ||
130 | #else | ||
131 | jmp trampoline_data | ||
132 | #endif | ||
133 | |||
134 | bogus_real_magic: | ||
135 | 1: | ||
136 | hlt | ||
137 | jmp 1b | ||
138 | |||
139 | .section ".rodata","a" | ||
140 | |||
141 | /* | ||
142 | * Set up the wakeup GDT. We set these up as Big Real Mode, | ||
143 | * that is, with limits set to 4 GB. At least the Lenovo | ||
144 | * Thinkpad X61 is known to need this for the video BIOS | ||
145 | * initialization quirk to work; this is likely to also | ||
146 | * be the case for other laptops or integrated video devices. | ||
147 | */ | ||
148 | |||
149 | .globl wakeup_gdt | ||
150 | .balign 16 | ||
151 | wakeup_gdt: | ||
152 | .word 3*8-1 /* Self-descriptor */ | ||
153 | .long pa_wakeup_gdt | ||
154 | .word 0 | ||
155 | |||
156 | .word 0xffff /* 16-bit code segment @ real_mode_base */ | ||
157 | .long 0x9b000000 + pa_real_mode_base | ||
158 | .word 0x008f /* big real mode */ | ||
159 | |||
160 | .word 0xffff /* 16-bit data segment @ real_mode_base */ | ||
161 | .long 0x93000000 + pa_real_mode_base | ||
162 | .word 0x008f /* big real mode */ | ||
163 | .size wakeup_gdt, .-wakeup_gdt | ||
164 | |||
165 | .data | ||
166 | .balign 8 | ||
167 | |||
168 | /* This is the standard real-mode IDT */ | ||
169 | wakeup_idt: | ||
170 | .word 0xffff /* limit */ | ||
171 | .long 0 /* address */ | ||
172 | .word 0 | ||
173 | |||
174 | .globl HEAP, heap_end | ||
175 | HEAP: | ||
176 | .long wakeup_heap | ||
177 | heap_end: | ||
178 | .long wakeup_stack | ||
179 | |||
180 | .bss | ||
181 | wakeup_heap: | ||
182 | .space 2048 | ||
183 | wakeup_stack: | ||
184 | .space 2048 | ||
185 | wakeup_stack_end: | ||
186 | |||
187 | .section ".signature","a" | ||
188 | end_signature: | ||
189 | .long WAKEUP_END_SIGNATURE | ||