Annotation of qemu/roms/ipxe/src/arch/i386/prefix/mromprefix.S, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (C) 2010 Michael Brown <[email protected]>.
                      3:  *
                      4:  * This program is free software; you can redistribute it and/or
                      5:  * modify it under the terms of the GNU General Public License as
                      6:  * published by the Free Software Foundation; either version 2 of the
                      7:  * License, or any later version.
                      8:  *
                      9:  * This program is distributed in the hope that it will be useful, but
                     10:  * WITHOUT ANY WARRANTY; without even the implied warranty of
                     11:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     12:  * General Public License for more details.
                     13:  *
                     14:  * You should have received a copy of the GNU General Public License
                     15:  * along with this program; if not, write to the Free Software
                     16:  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
                     17:  *
                     18:  */
                     19: 
                     20: FILE_LICENCE ( GPL2_OR_LATER )
                     21: 
                     22: #define PCIBIOS_READ_CONFIG_WORD       0xb109
                     23: #define PCIBIOS_READ_CONFIG_DWORD      0xb10a
                     24: #define PCIBIOS_WRITE_CONFIG_WORD      0xb10c
                     25: #define PCIBIOS_WRITE_CONFIG_DWORD     0xb10d
                     26: #define PCI_COMMAND                    0x04
                     27: #define PCI_COMMAND_MEM                                0x02
                     28: #define PCI_BAR_0                      0x10
                     29: #define PCI_BAR_5                      0x24
                     30: #define PCI_BAR_EXPROM                 0x30
                     31: 
                     32: #define ROMPREFIX_EXCLUDE_PAYLOAD 1
                     33: #define _rom_start _mrom_start
                     34: #include "romprefix.S"
                     35: 
                     36:        .text
                     37:        .arch i386
                     38:        .code16
                     39: 
                     40: /* Obtain access to payload by exposing the expansion ROM BAR at the
                     41:  * address currently used by a suitably large memory BAR on the same
                     42:  * device.  The memory BAR is temporarily disabled.  Using a memory
                     43:  * BAR on the same device means that we don't have to worry about the
                     44:  * configuration of any intermediate PCI bridges.
                     45:  *
                     46:  * Parameters:
                     47:  *   %ds:0000 : Prefix
                     48:  *   %esi : Buffer for copy of image source (or zero if no buffer available)
                     49:  * Returns:
                     50:  *   %esi : Valid image source address (buffered or unbuffered)
                     51:  *   CF set on error
                     52:  */
                     53:        .section ".text16.early", "awx", @progbits
                     54:        .globl  open_payload
                     55: open_payload:
                     56:        /* Preserve registers */
                     57:        pushl   %eax
                     58:        pushw   %bx
                     59:        pushl   %ecx
                     60:        pushl   %edx
                     61:        pushl   %edi
                     62:        pushw   %bp
                     63:        pushw   %ds
                     64: 
                     65:        /* Retrieve bus:dev.fn and image source length from .prefix */
                     66:        movw    init_pci_busdevfn, %bx
                     67:        movl    image_source_len_dword, %ecx
                     68: 
                     69:        /* Set up %ds for access to .text16.early */
                     70:        pushw   %cs
                     71:        popw    %ds
                     72: 
                     73:        /* Store bus:dev.fn and image source length to .text16.early */
                     74:        movw    %bx, payload_pci_busdevfn
                     75:        movl    %ecx, rom_bar_copy_len_dword
                     76: 
                     77:        /* Get expansion ROM BAR current value */
                     78:        movw    $PCI_BAR_EXPROM, %di
                     79:        call    pci_read_bar
                     80:        movl    %eax, rom_bar_orig_value
                     81: 
                     82:        /* Get expansion ROM BAR size */
                     83:        call    pci_size_mem_bar_low
                     84:        movl    %ecx, rom_bar_size
                     85: 
                     86:        /* Find a suitable memory BAR to use */
                     87:        movw    $PCI_BAR_0, %di         /* %di is PCI BAR register */
                     88:        xorw    %bp, %bp                /* %bp is increment */
                     89: find_mem_bar:
                     90:        /* Move to next BAR */
                     91:        addw    %bp, %di
                     92:        cmpw    $PCI_BAR_5, %di
                     93:        jle     1f
                     94:        stc
                     95:        jmp     99f
                     96: 1:     movw    $4, %bp
                     97: 
                     98:        /* Get BAR current value */
                     99:        call    pci_read_bar
                    100: 
                    101:        /* Skip non-existent BARs */
                    102:        notl    %eax
                    103:        testl   %eax, %eax
                    104:        notl    %eax
                    105:        jz      find_mem_bar
                    106: 
                    107:        /* Skip I/O BARs */
                    108:        testb   $0x01, %al
                    109:        jnz     find_mem_bar
                    110: 
                    111:        /* Set increment to 8 for 64-bit BARs */
                    112:        testb   $0x04, %al
                    113:        jz      1f
                    114:        movw    $8, %bp
                    115: 1:
                    116:        /* Skip 64-bit BARs with high dword set; we couldn't use this
                    117:         * address for the (32-bit) expansion ROM BAR anyway
                    118:         */
                    119:        testl   %edx, %edx
                    120:        jnz     find_mem_bar
                    121: 
                    122:        /* Get low dword of BAR size */
                    123:        call    pci_size_mem_bar_low
                    124: 
                    125:        /* Skip BARs smaller than the expansion ROM BAR */
                    126:        cmpl    %ecx, rom_bar_size
                    127:        ja      find_mem_bar
                    128: 
                    129:        /* We have a memory BAR with a 32-bit address that is large
                    130:         * enough to use.  Store BAR number and original value.
                    131:         */
                    132:        movw    %di, stolen_bar_register
                    133:        movl    %eax, stolen_bar_orig_value
                    134: 
                    135:        /* Remove flags from BAR address */
                    136:        xorb    %al, %al
                    137: 
                    138:        /* Write zero to our stolen BAR.  This doesn't technically
                    139:         * disable it, but it's a pretty safe bet that the PCI bridge
                    140:         * won't pass through accesses to this region anyway.  Note
                    141:         * that the high dword (if any) must already be zero.
                    142:         */
                    143:        xorl    %ecx, %ecx
                    144:        call    pci_write_config_dword
                    145: 
                    146:        /* Enable expansion ROM BAR at stolen BAR's address */
                    147:        movl    %eax, %ecx
                    148:        orb     $0x1, %cl
                    149:        movw    $PCI_BAR_EXPROM, %di
                    150:        call    pci_write_config_dword
                    151: 
                    152:        /* Copy payload to buffer, or set buffer address to BAR address */
                    153:        testl   %esi, %esi
                    154:        jz      1f
                    155:        /* We have a buffer; copy payload to it.  Since .mrom is
                    156:         * designed specifically for real hardware, we assume that
                    157:         * flat real mode is working properly.  (In the unlikely event
                    158:         * that this code is run inside a hypervisor that doesn't
                    159:         * properly support flat real mode, it will die horribly.)
                    160:         */
                    161:        pushl   %esi
                    162:        pushw   %es
                    163:        movl    %esi, %edi
                    164:        movl    %eax, %esi
                    165:        movl    rom_bar_copy_len_dword, %ecx
                    166:        xorw    %ax, %ax
                    167:        movw    %ax, %es
                    168:        addr32 es rep movsl
                    169:        popw    %es
                    170:        popl    %esi
                    171:        jmp     2f
                    172: 1:     /* We have no buffer; set %esi to the BAR address */
                    173:        movl    %eax, %esi
                    174: 2:
                    175: 
                    176:        clc
                    177:        /* Restore registers and return */
                    178: 99:    popw    %ds
                    179:        popw    %bp
                    180:        popl    %edi
                    181:        popl    %edx
                    182:        popl    %ecx
                    183:        popw    %bx
                    184:        popl    %eax
                    185:        lret
                    186:        .size   open_payload, . - open_payload
                    187: 
                    188:        .section ".text16.early.data", "aw", @progbits
                    189: payload_pci_busdevfn:
                    190:        .word   0
                    191:        .size   payload_pci_busdevfn, . - payload_pci_busdevfn
                    192: 
                    193:        .section ".text16.early.data", "aw", @progbits
                    194: rom_bar_orig_value:
                    195:        .long   0
                    196:        .size   rom_bar_orig_value, . - rom_bar_orig_value
                    197: 
                    198:        .section ".text16.early.data", "aw", @progbits
                    199: rom_bar_size:
                    200:        .long   0
                    201:        .size   rom_bar_size, . - rom_bar_size
                    202: 
                    203:        .section ".text16.early.data", "aw", @progbits
                    204: rom_bar_copy_len_dword:
                    205:        .long   0
                    206:        .size   rom_bar_copy_len_dword, . - rom_bar_copy_len_dword
                    207: 
                    208:        .section ".text16.early.data", "aw", @progbits
                    209: stolen_bar_register:
                    210:        .word   0
                    211:        .size   stolen_bar_register, . - stolen_bar_register
                    212: 
                    213:        .section ".text16.early.data", "aw", @progbits
                    214: stolen_bar_orig_value:
                    215:        .long   0
                    216:        .size   stolen_bar_orig_value, . - stolen_bar_orig_value
                    217: 
                    218: /* Restore original BAR values
                    219:  *
                    220:  * Parameters:
                    221:  *   none
                    222:  * Returns:
                    223:  *   none
                    224:  */
                    225:        .section ".text16.early", "awx", @progbits
                    226:        .globl  close_payload
                    227: close_payload:
                    228:        /* Preserve registers */
                    229:        pushw   %bx
                    230:        pushw   %di
                    231:        pushl   %ecx
                    232:        pushw   %ds
                    233: 
                    234:        /* Set up %ds for access to .text16.early */
                    235:        pushw   %cs
                    236:        popw    %ds
                    237: 
                    238:        /* Retrieve stored bus:dev.fn */
                    239:        movw    payload_pci_busdevfn, %bx
                    240: 
                    241:        /* Restore expansion ROM BAR original value */
                    242:        movw    $PCI_BAR_EXPROM, %di
                    243:        movl    rom_bar_orig_value, %ecx
                    244:        call    pci_write_config_dword
                    245: 
                    246:        /* Restore stolen BAR original value */
                    247:        movw    stolen_bar_register, %di
                    248:        movl    stolen_bar_orig_value, %ecx
                    249:        call    pci_write_config_dword
                    250: 
                    251:        /* Restore registers and return */
                    252:        popw    %ds
                    253:        popl    %ecx
                    254:        popw    %di
                    255:        popw    %bx
                    256:        lret
                    257:        .size   close_payload, . - close_payload
                    258: 
                    259: /* Get PCI BAR value
                    260:  *
                    261:  * Parameters:
                    262:  *   %bx : PCI bus:dev.fn
                    263:  *   %di : PCI BAR register number
                    264:  * Returns:
                    265:  *   %edx:%eax : PCI BAR value
                    266:  */
                    267:        .section ".text16.early", "awx", @progbits
                    268: pci_read_bar:
                    269:        /* Preserve registers */
                    270:        pushl   %ecx
                    271:        pushw   %di
                    272: 
                    273:        /* Read low dword value */
                    274:        call    pci_read_config_dword
                    275:        movl    %ecx, %eax
                    276: 
                    277:        /* Read high dword value, if applicable */
                    278:        xorl    %edx, %edx
                    279:        andb    $0x07, %cl
                    280:        cmpb    $0x04, %cl
                    281:        jne     1f
                    282:        addw    $4, %di
                    283:        call    pci_read_config_dword
                    284:        movl    %ecx, %edx
                    285: 1:
                    286:        /* Restore registers and return */
                    287:        popw    %di
                    288:        popl    %ecx
                    289:        ret
                    290:        .size   pci_read_bar, . - pci_read_bar
                    291: 
                    292: /* Get low dword of PCI memory BAR size
                    293:  *
                    294:  * Parameters:
                    295:  *   %bx : PCI bus:dev.fn
                    296:  *   %di : PCI BAR register number
                    297:  *   %eax : Low dword of current PCI BAR value
                    298:  * Returns:
                    299:  *   %ecx : PCI BAR size
                    300:  */
                    301:        .section ".text16.early", "awx", @progbits
                    302: pci_size_mem_bar_low:
                    303:        /* Preserve registers */
                    304:        pushw   %dx
                    305: 
                    306:        /* Disable memory accesses */
                    307:        xorw    %dx, %dx
                    308:        call    pci_set_mem_access
                    309: 
                    310:        /* Write all ones to BAR */
                    311:        xorl    %ecx, %ecx
                    312:        decl    %ecx
                    313:        call    pci_write_config_dword
                    314: 
                    315:        /* Read back BAR */
                    316:        call    pci_read_config_dword
                    317: 
                    318:        /* Calculate size */
                    319:        notl    %ecx
                    320:        orb     $0x0f, %cl
                    321:        incl    %ecx
                    322: 
                    323:        /* Restore original value */
                    324:        pushl   %ecx
                    325:        movl    %eax, %ecx
                    326:        call    pci_write_config_dword
                    327:        popl    %ecx
                    328: 
                    329:        /* Enable memory accesses */
                    330:        movw    $PCI_COMMAND_MEM, %dx
                    331:        call    pci_set_mem_access
                    332: 
                    333:        /* Restore registers and return */
                    334:        popw    %dx
                    335:        ret
                    336:        .size   pci_size_mem_bar_low, . - pci_size_mem_bar_low
                    337: 
                    338: /* Read PCI config dword
                    339:  *
                    340:  * Parameters:
                    341:  *   %bx : PCI bus:dev.fn
                    342:  *   %di : PCI register number
                    343:  * Returns:
                    344:  *   %ecx : Dword value
                    345:  */
                    346:        .section ".text16.early", "awx", @progbits
                    347: pci_read_config_dword:
                    348:        /* Preserve registers */
                    349:        pushl   %eax
                    350:        pushl   %ebx
                    351:        pushl   %edx
                    352: 
                    353:        /* Issue INT 0x1a,b10a */
                    354:        movw    $PCIBIOS_READ_CONFIG_DWORD, %ax
                    355:        int     $0x1a
                    356: 
                    357:        /* Restore registers and return */
                    358:        popl    %edx
                    359:        popl    %ebx
                    360:        popl    %eax
                    361:        ret
                    362:        .size   pci_read_config_dword, . - pci_read_config_dword
                    363: 
                    364: /* Write PCI config dword
                    365:  *
                    366:  * Parameters:
                    367:  *   %bx : PCI bus:dev.fn
                    368:  *   %di : PCI register number
                    369:  *   %ecx : PCI BAR value
                    370:  * Returns:
                    371:  *   none
                    372:  */
                    373:        .section ".text16.early", "awx", @progbits
                    374: pci_write_config_dword:
                    375:        /* Preserve registers */
                    376:        pushal
                    377: 
                    378:        /* Issue INT 0x1a,b10d */
                    379:        movw    $PCIBIOS_WRITE_CONFIG_DWORD, %ax
                    380:        int     $0x1a
                    381: 
                    382:        /* Restore registers and return */
                    383:        popal
                    384:        ret
                    385:        .size   pci_write_config_dword, . - pci_write_config_dword
                    386: 
                    387: /* Enable/disable memory access response in PCI command word
                    388:  *
                    389:  * Parameters:
                    390:  *   %bx : PCI bus:dev.fn
                    391:  *   %dx : PCI_COMMAND_MEM, or zero
                    392:  * Returns:
                    393:  *   none
                    394:  */
                    395:        .section ".text16.early", "awx", @progbits
                    396: pci_set_mem_access:
                    397:        /* Preserve registers */
                    398:        pushal
                    399: 
                    400:        /* Read current value of command register */
                    401:        pushw   %bx
                    402:        pushw   %dx
                    403:        movw    $PCI_COMMAND, %di
                    404:        movw    $PCIBIOS_READ_CONFIG_WORD, %ax
                    405:        int     $0x1a
                    406:        popw    %dx
                    407:        popw    %bx
                    408: 
                    409:        /* Set memory access enable as appropriate */
                    410:        andw    $~PCI_COMMAND_MEM, %cx
                    411:        orw     %dx, %cx
                    412: 
                    413:        /* Write new value of command register */
                    414:        movw    $PCIBIOS_WRITE_CONFIG_WORD, %ax
                    415:        int     $0x1a
                    416: 
                    417:        /* Restore registers and return */
                    418:        popal
                    419:        ret
                    420:        .size   pci_set_mem_access, . - pci_set_mem_access
                    421: 
                    422: /* Image source area length (in dwords)
                    423:  *
                    424:  */
                    425:        .section ".prefix", "ax", @progbits
                    426: image_source_len_dword:
                    427:        .long   0
                    428:        .size   image_source_len_dword, . - image_source_len_dword
                    429:        .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
                    430:        .ascii  "ADDL"
                    431:        .long   image_source_len_dword
                    432:        .long   4
                    433:        .long   0
                    434:        .previous

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.