Annotation of qemu/roms/ipxe/src/arch/i386/prefix/mromprefix.S, revision 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.