1        .code16
2
3#define SMAP    0x534d4150
4#define E820_BIOS_MAX 128
5
6get_memory_map:
7
8.Lmeme820:
9        xorl    %ebx, %ebx                      # continuation counter
10        movw    $bootsym(e820map), %di             # point into the whitelist
11                                                # so we can have the bios
12                                                # directly write into it.
13
141:      movl    $0x0000e820, %eax               # e820, upper word zeroed
15        movl    $SMAP,%edx                      # ascii 'SMAP'
16        movl    $20,%ecx                        # size of the e820rec
17        pushw   %ds                             # data record.
18        popw    %es
19        int     $0x15
20        jc      .Lmem88
21
22        cmpl    $SMAP,%eax                      # check the return is `SMAP'
23        jne     .Lmem88
24
25        movb    bootsym(e820nr),%al             # up to 128 entries
26        cmpb    $E820_BIOS_MAX,%al
27        jae     .Lmem88
28
29        incb    bootsym(e820nr)
30        movw    %di,%ax
31        addw    $20,%ax
32        movw    %ax,%di
33        cmpl    $0,%ebx                         # check to see if
34        jne     1b                              # %ebx is set to EOF
35
36.Lmem88:
37        movb    $0x88, %ah
38        int     $0x15
39        movw    %ax,bootsym(highmem_kb)
40
41.Lmeme801:
42        stc                                     # fix to work around buggy
43        xorw    %cx,%cx                         # BIOSes which don't clear/set
44        xorw    %dx,%dx                         # carry on pass/error of
45                                                # e801h memory size call
46                                                # or merely pass cx,dx though
47                                                # without changing them.
48        movw    $0xe801, %ax
49        int     $0x15
50        jc      .Lint12
51
52        cmpw    $0x0, %cx                       # Kludge to handle BIOSes
53        jne     1f                              # which report their extended
54        cmpw    $0x0, %dx                       # memory in AX/BX rather than
55        jne     1f                              # CX/DX.  The spec I have read
56        movw    %ax, %cx                        # seems to indicate AX/BX
57        movw    %bx, %dx                        # are more reasonable anyway...
581:      andl    $0xffff,%edx                    # clear sign extend
59        shll    $6,%edx                         # and go from 64k to 1k chunks
60        movl    %edx,bootsym(highmem_kb)        # store extended memory size
61        andl    $0xffff,%ecx                    # clear sign extend
62        addl    %ecx,bootsym(highmem_kb)        # and add lower memory into
63
64.Lint12:
65        int     $0x12
66        movw    %ax,bootsym(lowmem_kb)
67
68        ret
69
70/*
71 * Copy E820 map obtained from BIOS to a buffer allocated by Xen.
72 * Input: %rdi: target address of e820 entry array
73 *        %esi: maximum number of entries to copy
74 * Output: %eax: number of entries copied
75 */
76        .code64
77ENTRY(e820map_copy)
78        mov     %esi, %eax
79        lea     e820map(%rip), %rsi
80        mov     e820nr(%rip), %ecx
81        cmp     %ecx, %eax
82        cmova   %ecx, %eax                      # number of entries to move
83        imul    $5, %eax, %ecx
84        rep movsl                               # do the move
85        ret
86
87        .align  4
88e820map:
89        .fill   E820_BIOS_MAX*20,1,0
90e820nr:
91        .long   0
92GLOBAL(lowmem_kb)
93        .long   0
94GLOBAL(highmem_kb)
95        .long   0
96