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(bios_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        incw    bootsym(bios_e820nr)
26        cmpw    $E820_BIOS_MAX, bootsym(bios_e820nr) # up to this many entries
27        jae     .Lmem88
28
29        movw    %di,%ax
30        addw    $20,%ax
31        movw    %ax,%di
32        testl   %ebx,%ebx                       # check to see if
33        jnz     1b                              # %ebx is set to EOF
34
35.Lmem88:
36        movb    $0x88, %ah
37        int     $0x15
38        movw    %ax,bootsym(highmem_kb)
39
40.Lmeme801:
41        stc                                     # fix to work around buggy
42        xorw    %cx,%cx                         # BIOSes which don't clear/set
43        xorw    %dx,%dx                         # carry on pass/error of
44                                                # e801h memory size call
45                                                # or merely pass cx,dx though
46                                                # without changing them.
47        movw    $0xe801, %ax
48        int     $0x15
49        jc      .Lint12
50
51        testw   %cx, %cx                        # Kludge to handle BIOSes
52        jnz     1f                              # which report their extended
53        testw   %dx, %dx                        # memory in AX/BX rather than
54        jnz     1f                              # CX/DX.  The spec I have read
55        movw    %ax, %cx                        # seems to indicate AX/BX
56        movw    %bx, %dx                        # are more reasonable anyway...
571:      movzwl  %dx, %edx
58        shll    $6,%edx                         # and go from 64k to 1k chunks
59        movzwl  %cx, %ecx
60        addl    %ecx, %edx                      # add in lower memory
61        movl    %edx,bootsym(highmem_kb)        # store extended memory size
62
63.Lint12:
64        int     $0x12
65        movw    %ax,bootsym(lowmem_kb)
66
67        ret
68
69        .align  4
70GLOBAL(bios_e820map)
71        .fill   E820_BIOS_MAX*20,1,0
72GLOBAL(bios_e820nr)
73        .long   0
74GLOBAL(lowmem_kb)
75        .long   0
76GLOBAL(highmem_kb)
77        .long   0
78